4

I have some handler classes in my application which are created in runtime according to passed enum value. It looks like this:

public interface IMyHandler
{
    void Handle();
}

public class SimpleHandler : IMyHandler
{
    public void Handle()
    {
        //logic here...
    }
}

public class ComplexHandler : IMyHandler
{
    public void Handle()
    {
        //logic here...
    }
}

public enum HandlerTypes
{
    Simple,
    Complex
}

public class Hanlderfactory
{
    public IMyHandler CreateHandler(HandlerTypes type)
    {
        switch(type)
        {
            case HandlerTypes.Simple:
                return new SimpleHandler();
            case HandlerTypes.Complex:
                return new ComplexHandler();
            default:
                throw new NotSupportedException();
        }
    }
}

It's ok for me. But there is a problem here if I want to inject some components in my handlers like this:

public class SimpleHandler : IMyHandler
{
    public SimpleHandler(IComponentOne c1, IComponentTwo c2, IComponentThree c3)
    {
        //...
    }

    public void Handle()
    {
        //logic here...
    }
}

I use Unity IoC container and of course I want to use it here. But it looks ugly to call Resolve method here manually. Am I on wrong path? How to use both of this patterns together gracefully? Is it a single option here to call IoC container inside facotry?

UPDATE: I tried to use injection of delegate with InjectionFactory class. It works fine. But in this case if I need such factory logic in two applications I need to register this delegate and mapping between enums and classes in both applications startup:

var container = new UnityContainer();
container.RegisterType<IMyHandler, SimpleHandler>(HandlerTypes.Simple.ToString());
container.RegisterType<IMyHandler, ComplexHandler>(HandlerTypes.Complex.ToString());
container.RegisterType<Func<HandlerTypes, IMyHandler>>(new InjectionFactory(c => new Func<HandlerTypes, IMyHandler>(type => c.Resolve<IMyHandler>(type.ToString()))));
mtkachenko
  • 5,389
  • 9
  • 38
  • 68
  • tip: `public class Handler : IHandlerService` Unity can resolve type parameters – Aydin Feb 07 '16 at 10:38
  • What do you mean? I have HandlerTypes.Simple in runtime and need to create instance of right class. – mtkachenko Feb 07 '16 at 11:19
  • @AydinAdn is right; you should make the handler abstraction generic. That will solve your problems (and much more). Take a look at [this article](https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=91). – Steven Feb 26 '16 at 04:06

1 Answers1

3

Using Enum with a factory is a code smell that indicates you need to do more refactoring.

An alternative is to use the strategy pattern as in this example. Note the use of Type instead of an Enum ensures you only have to change one piece of code when the design changes (you could alternatively use a string datatype).

Another alternative would be to inject a Func into the factory so your DI container can resolve instances.

Injecting the container into an abstract factory is a way of making a framework extension point. As long as the factory is part of your composition root, this is okay.

Community
  • 1
  • 1
NightOwl888
  • 55,572
  • 24
  • 139
  • 212
  • 2
    Enum value is stored in database, Using timer application retrieves row from db and needs to instantiate appropriate handler for this row. is it bad smell? Yes, it's a strategy pattern. But it's unclear for me how can I define type of strategy class? There should be some mapping between some input data (like enum value from db) and startegy type. – mtkachenko Feb 07 '16 at 12:39
  • All types in .NET can be identified using a string representation. You could use the [`Type.GetType(string)` method](https://msdn.microsoft.com/en-us/library/w3f99sx1(v=vs.110).aspx) to convert the string to a `Type` datatype. It is this string you could store in your database, but be sure not to save the version number along with it (as would happen if you were using strong naming). – NightOwl888 Feb 07 '16 at 12:53