Given the following program:
using System;
using System.Collections.Generic;
namespace ConsoleApplication49
{
using FooSpace;
class Program
{
static void Main(string[] args)
{
IEnumerable<FooBase> foos = FooFactory.CreateFoos();
foreach (var foo in foos)
{
HandleFoo(foo);
}
}
private static void HandleFoo(FooBase foo)
{
dynamic fooObject = foo;
ApplyFooDefaults(fooObject);
}
private static void ApplyFooDefaults(Foo1 foo1)
{
foo1.Name = "Foo 1";
Console.WriteLine(foo1);
}
private static void ApplyFooDefaults(Foo2 foo2)
{
foo2.Name = "Foo 2";
foo2.Description = "SomeDefaultDescription";
Console.WriteLine(foo2);
}
private static void ApplyFooDefaults(Foo3 foo3)
{
foo3.Name = "Foo 3";
foo3.MaxSize = Int32.MaxValue;
Console.WriteLine(foo3);
}
private static void ApplyFooDefaults(Foo4 foo4)
{
foo4.Name = "Foo 4";
foo4.MaxSize = 99999999;
foo4.EnableCache = true;
Console.WriteLine(foo4);
}
private static void ApplyFooDefaults(FooBase unhandledFoo)
{
unhandledFoo.Name = "Unhandled Foo";
Console.WriteLine(unhandledFoo);
}
}
}
namespace FooSpace
{
public static class FooFactory
{
public static IEnumerable<FooBase> CreateFoos()
{
List<FooBase> foos = new List<FooBase>();
foos.Add(new Foo1());
foos.Add(new Foo2());
foos.Add(new Foo3());
foos.Add(new Foo4());
foos.Add(new Foo5());
return foos;
}
}
public class FooBase
{
protected FooBase() { }
public string Name { get; set; }
public override string ToString()
{
return String.Format("Type = {0}, Name=\"{1}\"", this.GetType().FullName, this.Name);
}
}
public sealed class Foo1 : FooBase
{
internal Foo1() { }
}
public sealed class Foo2 : FooBase
{
internal Foo2() { }
public string Description { get; set; }
public override string ToString()
{
string baseString = base.ToString();
return String.Format("{0}, Description=\"{1}\"", baseString, this.Description);
}
}
public sealed class Foo3 : FooBase
{
internal Foo3() { }
public int MaxSize { get; set; }
public override string ToString()
{
string baseString = base.ToString();
return String.Format("{0}, MaxSize={1}", baseString, this.MaxSize);
}
}
public sealed class Foo4 : FooBase
{
internal Foo4() { }
public int MaxSize { get; set; }
public bool EnableCache { get; set; }
public override string ToString()
{
string baseString = base.ToString();
return String.Format("{0}, MaxSize={1}, EnableCache={2}", baseString,
this.MaxSize,
this.EnableCache);
}
}
public sealed class Foo5 : FooBase
{
internal Foo5() { }
}
}
Which produces the following output:
Type = ConsoleApplication49.Foo1, Name="Foo 1"
Type = ConsoleApplication49.Foo2, Name="Foo 2", Description="SomeDefaultDescription"
Type = ConsoleApplication49.Foo3, Name="Foo 3", MaxSize=2147483647
Type = ConsoleApplication49.Foo4, Name="Foo 4", MaxSize=99999999, EnableCache=True
Type = ConsoleApplication49.Foo5, Name="Unhandled Foo"
Press any key to continue . . .
I decided to use the dynamics here to avoid the following:
- using switch / if / else statements, for example.
switch(foo.GetType().Name) - explicit type checking instructions, for example.
foo is Foo1 - explicit casting instructions, for example.
(Foo1)foo
Due to the conversion, the dynamiccorrect method ApplyFooDefaultsis called based on the type of object passed to HandleFoo(FooBase foo). Any objects that have no corresponding handler method ApplyFooDefaults, enter the "catch all" method ApplyFooDefaults(FooBase unhandledFoo).
, FooBase , , .
"" , ?
* *
, , , . :
- Foos , FooFactory.
- Foo, Foo
.
.