I have this factory class which converts a Foo into a list of Bar objects. Foo is a very complex object which I flatten into a list of simple Bar objects. There are about 60 different bits of data that could be transformed from a Foo into a Bar. The following implementation works but there's definite scope for improvement here.
public class FooToBarsConverter
{
public List<Bar> Convert(Foo foo)
{
return Enum.GetValues(typeof(BarTypeEnum))
.Cast<BarTypeEnum>()
.Select(barType => CreateBar(foo, barType))
.Where(newBar => newBar != null)
.ToList();
}
public Bar CreateBar(Foo foo, BarTypeEnum barType)
{
switch (barType)
{
case BarTypeEnum.TypeA:
return CreateTypeA(foo);
case BarTypeEnum.TypeB:
return CreateTypeB(foo);
}
return null;
}
private Bar CreateTypeA(Foo foo)
{
return new Bar(...);
}
private Bar CreateTypeB(Foo foo)
{
return new Bar(...);
}
}
Ideally I'd like to avoid having to write a new case to the switch every time a new BarType is added. Perhaps a dictionary of types and delegate functions but that would still require a mapping of sorts? Is there any feature of the language that I can exploit to avoid this switch case a make the compiler choose the create create function?
Assuming you don't mind the factory methods being statics this does neaten it up a bit without needing the cruft of having to create ~60 more sub-classes to get the type system to do the work for me. I think the statics aren't needed if you make it a func with the factory as well but I've not got that far yet. The statics don't particularly bother me with it just being data transposition
private static readonly IDictionary<BarTypeEnum, Func<Foo, Bar>>
CreateLookup = new Dictionary<BarTypeEnum, Func<Foo, Bar>>
{
{ BarTypeEnum.TypeA, CreateTypeA },
{ BarTypeEnum.TypeB, CreateTypeB }
};
public Bar Create(Foo foo, BarTypeEnum barType)
{
Func<Foo, Bar> createDelegate;
CreateLookup.TryGetValue(barType, out createDelegate);
return createDelegate != null ? createDelegate(foo) : null;
}
private static Bar CreateTypeA(Foo foo) { ... }
private static Bar CreateTypeB(Foo foo) { ... }
Is there any feature of the language that I can exploit to avoid this switch case a make the compiler choose the create create function?
Yes. It's called polymorphism
Check this video: Jimmy Bogard - Crafting Wicked Domain Models on how an enum could be converted into a polimorhic class hierachy.
Basically you create an abstract class called BarTypeEnum that feels like an enum and create n derived types, one for each enum value. Then you could have this method
public abstract Bar CreateBar(Foo foo);
and override it in every subclass each returning a diferent subtype of Bar
e.g.
public override Bar CreateBar(Foo foo)
{
return CreateTypeA(foo);
}
BTW: The enumeration class he talks about is on NuGet as the NuGet package Enumeration
EDIT I just checked and the nuget package class is not the same as the video. It is a Generic, nonpolimorphic way to implement it though
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With