k3b k3b - 2 years ago 116
C# Question

IoC Factory: Pros and contras for Interface versus Delegates

Any place where you need a run-time value to construct a particular dependency, Abstract Factory is the solution.

My qestion is: Why do many sources favor FactoryInterface over FactoryDelegate to implement this pattern?
What are the pros and contras for both solutions?

Here is an example to understand what i mean

If you have a Service that needs a Repository with a certain Context then the Service constructor
needs a factory to create or access its repository.

The common solution for this is to create a RepositoryFactoryInterface like this.

public IRepositoryFactory {
IRepository Create(ContextInformation context);
}

public class MyService {
private IRepositoryFactory repositoryFactory;
public MyService(IRepositoryFactory repositoryFactory)
{
this.repositoryFactory = repositoryFactory:
}

public void DoSomeService()
{
ContextInformation context = ....;

IRepository repository = this.repositoryFactory.Create(context);

repository.Load(...);
...
repository.Save(...);
}
}


You also need to implement IRepositoryFactory interface some way

public MyEf4RepositoryFactory : IRepositoryFactory
{
IRepository Create(ContextInformation context)
{
return new MyEf4Repository(context);
}
}


... and use it in the application

public void main()
{
IRepositoryFactory repoFactory = new MyEf4RepositoryFactory();
IService service = new MyService(repoFactory);

service.DoSomeService();
}


----- End of mainstream solution ------

Instead of the RepositoryFactoryInterface you can do the same with a factorydelegate that requires less coding like this.

public class MyService {
private Func<ContextInformation, IRepository> repositoryFactory;
public MyService(Func<ContextInformation, IRepository> repositoryFactory)
{
this.repositoryFactory = repositoryFactory:
}

public void DoSomeService()
{
ContextInformation context = ....;

IRepository repository = this.repositoryFactory(context);

repository.Load(...);
...
repository.Save(...);
}
}


... and use it in the application

public void main()
{
IService service = new MyService(context => new MyEf4Repository(context));

service.DoSomeService();
}


In my opinion the factorydelegate
context => new MyEf4Repository(context)
is much more compact than
declaring and implementing an interface
IRepositoryFactory
and
MyEf4RepositoryFactory
.

There must be a reason for this and i want to know why.

Here is one example source that uses the interface aproach: answer to is-there-a-pattern-for-initializing-objects-created-via-a-di-container

[Update]15 Months after asking this question and having more experience with the java universers i changed my mind: Now I prefer interfaces over delegates . But i cannot say why. It is just a feeling. Maybe because I am more used to it?

Answer Source

Personally, I have always used the mainstream solution, simply because I didn't think of using a delegate.

After I thought of it, I faced the problem of separation of concerns. I'm using Ninject, and I didn't want my binding module to look like this (imagine the repositoy having some dependencies of itself):

class IoCModule : NinjectModule
{
    public override Load()
    {
        Bind<Func<Context, IRepository>>()
            .ToConstant( context => new MyEf4Repository(context, Kernel.Get<IRepositoryDependency1>, Kernel.Get<IRepositoryDependency2>) );
    }
}

That isn't readable at all. So I still used fully typed out abstract factories for Separation of Concern and readability.

Now I use the FuncModule described in this question (a la AutoFac). So I can do this:

class IoCModule : NinjectModule
{
    public override Load()
    {
        Bind<IRepository>().To<MyEf4Repository>();
        Bind<IRepositoryDependency1>().To<...>();
        Bind<IRepositoryDependency2>().To<...>();
    }
}

and let ninject figure the dependencies out for me. As you can see, it's both more readable than using the method described above, and having to bind the factories for each dependency. This is the way I made the transition from the mainstream solution to the delegate solution.

So to answer your question. The reason I used the mainstream solution was because I didn't know how to do it another way at first (this is partly caused by most blogs fully typing out the abstract factories, can you see the circle?).

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download