I'm using Unity as IoC with C#, but I guess the question really isn't really limited to Unity and C#, but IoC in general.
I try to follow the SOLID-principle, which means that I got very few dependencies between two concrete classes. But when I need to create new instances of a model, what's the best way to do it?
I usually use a factory create my instances, but there's a few alternatives and I wonder which is better, and why?
Simple Factory:
public class FooFactory : IFooFactory
{
public IFoo CreateModel()
{
return new Foo(); // references a concrete class.
}
}
Service-locator-factory
public class FooFactory : IFooFactory
{
private readonly IUnityContainer _container;
public FooFactory (IUnityContainer container)
{
_container = container;
}
public IFoo CreateModel()
{
return _container.Resolve<IFoo>(); // Service-locator anti-pattern?
}
}
Func-factory. No dependencies to other classes.
public class FooFactory : IFooFactory
{
private readonly Func<IFoo> _createFunc;
public FooFactory (Func<IFoo> createFunc)
{
_createFunc= createFunc;
}
public IFoo CreateModel()
{
return _createFunc(); // Is this really better than service-locator?
}
}
Which IFooFactory
should I use, and why? Is there a better option?
The examples above are of a more conceptual level, where I try to find a balance between SOLID, maintainable code and service locator. Here's an actual example:
public class ActionScopeFactory : IActionScopeFactory
{
private readonly Func<Action, IActionScope> _createFunc;
public ActionScopeFactory(Func<Action, IActionScope> createFunc)
{
_createFunc = createFunc;
}
public IActionScope CreateScope(Action action)
{
return _createFunc(action);
}
}
public class ActionScope : IActionScope, IDisposable
{
private readonly Action _action;
public ActionScope(Action action)
{
_action = action;
}
public void Dispose()
{
_action();
}
}
public class SomeManager
{
public void DoStuff()
{
using(_actionFactory.CreateScope(() => AllDone())
{
// Do stuff. And when done call AllDone().
// Another way of actually writing try/finally.
}
}
}
Why do I use a Factory at all? Because I sometimes need to create new models. There are various scenarios when this is necessary. For eg. in a mapper and when the mapper has a longer lifetime than the object it should map. Example for factory usage:
public class FooManager
{
private IService _service;
private IFooFactory _factory;
public FooManager(IService service, IFooFactory factory)
{
_service = service;
_factory = factory;
}
public void MarkTimestamp()
{
IFoo foo = _factory.CreateModel();
foo.Time = DateTime.Now;
foo.User = // current user
_service.DoStuff(foo);
}
public void DoStuffInScope()
{
using(var foo = _factoru.CreateModel())
{
// do stuff with foo...
}
}
}
Func<IFoo>
is already a factory, no need to wrap it in another class+interface.