Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependency Injection and Factories

What is a decent way to handle conditional sub-factories with a DI approach. The scenario is the loader object that gets injected into an entry is dependent on the settings of that entry. Originally I was injecting the IoC container into the factory and using that to resolve based on naming conventions. However, I'd really like to keep the factory clean of the container.

The factory is injected into a class that will load all the settings from a database, and then use the factory to create a set of entries. The settings determine which loader will be used inside that given entry.

Edit: Changing code to better highlight the actual question. The issue is that multiple database managers must be supported simultaneously, if this were not the case then it would be simple. The database manager type is determined by the entry settings stored for a particular entry.

public class Entry : IEntry
{
     private ISomething loader;

     public Entry(ISomething something)
     {
         this.loader = something;
     }
}

public class EntryFactory : IEntryFactory
{
    IEntry BuildEntry(IEntrySetting setting)
    {
        //Use setting object to determine which database manager will be used
    }
}

public class EntryManager
{
    public EntryManager(IEntryFactory entryFactory)
    {
        var entrySettings = this.settings.Load();
        foreach(var setting in entrySettings)
        {
             this.entries.Add(entryFactory.BuildEntry(setting));
        }
    }
}

I had considered having the sub-factories register with a primary factory and resolve them that way, but I don't know if there is a better approach.

like image 594
crb04c Avatar asked Jul 27 '11 19:07

crb04c


1 Answers

What I typically do is create a wrapper for my DI container... Something like IDependencyResolver... And inject it into my factories. Then, you can have an implementation like StructureMapDependencyResolver that does the lifting. I like this better than injecting the container itself because this keeps me free to change DI containers (almost) instantly. At least my factories don't have to change.

public interface IDependencyResolver
{
    T Resolve<T>();
}

public class UnityDependencyResolver : IDependencyResolver
{
    private readonly IUnityContainer _container;

    public UnityDependencyResolver(IUnityContainer container)
    {
        _container = container;
    }

    public T Resolve<T>()
    {
        return _container.Resolve<T>();
    }
}

This approach is so flexible that you could implement your own Dependency Resolvers and inject them manually.

public class ManualDependencyResolver : IDependencyResolver
{
    public T Resolve<T>()
    {
        if (typeof(T)==typeof(ITransactionRepository))
        {
            return new CheckTransactionRespostory(new DataContext());
        }

        throw new Exception("No dependencies were found for the given type.");
    }
}
like image 65
Byron Sommardahl Avatar answered Oct 14 '22 14:10

Byron Sommardahl