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.