How do I replace a factory class by the Unity container?

Apr 28, 2014 at 4:44 PM
Hi,

I have a question on how to inject a dependency that depends on some specific data value in an entity object by using the Unity container. Currently, a static factory class instantiates the dependency and injects it to the client class's constructor. I would like to replace it with the Unity container.

Let me elaborate on it by using the following example:

The client class that expects the dependency is as follows:
public class Client
{
    private readonly IDoProcess doProcess;

    public Client(IDoProcess doProcess)
    {
        this.doProcess = doProcess;
    }

    public void Run()
    {
        this.doProcess.Run();
    }
}
Now, there are two classes that implement the IDoProcess interface:
public class DoProcess1 : IDoProcess
{
    public void Run()
    {
        …
    }
}

public class DoProcess2 : IDoProcess
{
    public void Run()
    {
        …
    }
}
My current factory class instantiates either DoProcess1 or DoProcess2 depending on an entity data:
public static class DoProcessFactory
{
    public static IDoProcess CreateDoProcess(Entity entity)
    {
        if (entity.ProcessType == ProcessType.Normal)
        {
            return new DoProcess1();
        }
        
        return new DoProcess2();
    }
}
Since the Entity object is a data, it is retrieved from IDataService:
public interface IDataService
{
    Entity GetEntity();
}

public class DataService : IDataService
{
    public Entity GetEntity()
    {
        return new Entity { ProcessType = ProcessType.Special };
    }
}
Could anyone help me how I can configure the Unity container to replace the DoProcessFactory class?

Thanks,

Tetsu
Apr 29, 2014 at 7:11 AM
I'm just curious why you don't want to use a factory? It is a common approach in a scenario where you need to obtain a reference to an object based on runtime values. I would change the implementation a bit to not be static and you could also rely on the container to inject the values:
public class DoProcessFactory
{
    private Func<IDoProcess> normalProcess;
    private Func<IDoProcess> specialProcess;

    public DoProcessFactory(Func<IDoProcess> normalProcess, Func<IDoProcess> specialProcess)
    {
        this.normalProcess = normalProcess;
        this.specialProcess = specialProcess;
    }

    public IDoProcess CreateDoProcess(Entity entity)
    {
        if (entity.ProcessType == ProcessType.Normal)
        {
            return normalProcess();
        }
        
        return new specialProcess();
    }
}
It would just be a matter of wiring up the correct InjectionConstructor for the factory.

Another alternative would to use InjectionFactory:
                container.RegisterType<IDoProcess>(new InjectionFactory(c =>
                {
                    if (entity.ProcessType == ProcessType.Normal)
                    {
                        return new DoProcess1();
                    }
        
                   return new DoProcess2();                
               }));
But the issue with the above InjectionFactory is how to get the runtime value to base the decision on. Depending on the scenario there are a few ways to do that (closure, (thread) static variable, per request based value registered in the container).

In general, I would tend to lean toward a factory except for when it seems that there are too many factory classes being created.

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Apr 29, 2014 at 3:51 PM
Hi Randy,

Thanks for your code. Your use of Func<IDoProcess> intrigued me and lead me to the section "Automatic Factories" in the Unity chm file. I'll study it and see if it is reasonable to my app.

Thanks again for your response.

Tetsu