Sto usando Unity come IoC con C #, ma suppongo che la domanda non sia realmente limitata a Unity e C #, ma IoC in generale.
Cerco di seguire il principio SOLID, il che significa che ho ottenuto pochissime dipendenze tra due classi concrete. Ma quando ho bisogno di creare nuove istanze di un modello, qual è il modo migliore per farlo?
Di solito uso una factory per creare le mie istanze, ma ci sono alcune alternative e mi chiedo quale sia il migliore, e perché?
Fabbrica semplice:
public class FooFactory : IFooFactory
{
public IFoo CreateModel()
{
return new Foo(); // references a concrete class.
}
}
Servizio-locator-fabbrica
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-fabbrica. Nessuna dipendenza dalle altre classi.
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?
}
}
Quale% di co_de dovrei usare e perché? Esiste un'opzione migliore?
Gli esempi sopra riportati sono di livello più concettuale, in cui cerco di trovare un equilibrio tra SOLID, codice gestibile e localizzatore di servizi. Ecco un esempio reale:
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.
}
}
}
Perché uso una fabbrica? Perché a volte ho bisogno di creare nuovi modelli. Ci sono vari scenari quando questo è necessario. Per es. in un mappatore e quando il mappatore ha una durata maggiore rispetto all'oggetto che dovrebbe mappare. Esempio di utilizzo di fabbrica:
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...
}
}
}