Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid switch case in factory

Tags:

c#

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) { ... }
like image 625
Neil Avatar asked Nov 26 '25 02:11

Neil


1 Answers

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

like image 161
Carlos Muñoz Avatar answered Nov 28 '25 16:11

Carlos Muñoz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!