Réponse courte: Oui. Réponse plus longue: Tout d'abord, dans les cas simples où une classe Foo est enregistrée comme implémentation pour IFoo, les paramètres du constructeur ou les propriétés de type Func<IFoo>
seront automatiquement résolus par Autofac, sans nécessiter de câblage supplémentaire. Autofac va injecter un délégué qui exécute essentiellement container.Resolve<IFoo>()
lorsqu'il est appelé.
Dans les cas plus complexes comme le vôtre, où la concrétion exacte renvoyée est basée sur les paramètres d'entrée, vous pouvez faire l'une des deux choses suivantes. D'abord, vous pouvez enregistrer une méthode de fabrication comme valeur de retour pour fournir une résolution paramétrées:
builder.Register<IElement>((c, p) => {
var dom= p.Named<IHtml>("dom");
switch (dom.ElementType)
{
case "table":
return new TableElement(dom);
case "div":
return new DivElement(dom);
case "span":
return new SpanElement(dom);
}
return new PassthroughElement(dom);
});
//usage
container.Resolve<IElement>(new NamedParameter("dom", domInstance))
C'est le type-safe (domInstance ne sera pas vérifiée par le compilateur pour vous assurer qu'il est un iHTML), ni très nettoyer. Au lieu de cela, une autre solution consiste à enregistrer en fait la méthode d'usine comme Func:
builder.Register<Func<IHtml, IElement>>(dom =>
{
switch (dom.ElementType)
{
case "table":
return new TableElement(dom);
case "div":
return new DivElement(dom);
case "span":
return new SpanElement(dom);
}
return new PassthroughElement(dom);
});
public class NeedsAnElementFactory //also registered in AutoFac
{
protected Func<IHtml,IElement> CreateElement {get; private set;}
//AutoFac will constructor-inject the Func you registered
//whenever this class is resolved.
public NeedsAnElementFactory(Func<IHtml,IElement> elementFactory)
{
CreateElement = elementFactory;
}
public void MethodUsingElementFactory()
{
IHtml domInstance = GetTheDOM();
var element = CreateElement(domInstance);
//the next line won't compile;
//the factory method is strongly typed to IHtml
var element2 = CreateElement("foo");
}
}
Si vous voulez garder le code ElementFactory au lieu de le mettre dans le module Autofac, vous pouvez faire de la fabrique statique et inscrivez-vous dès que (Cela fonctionne particulièrement bien dans votre cas car votre méthode d'usine est trivialement statique):
public class ElementFactory
{
public static IElement Create(IHtml dom)
{
switch (dom.ElementType)
{
case "table":
return new TableElement(dom);
case "div":
return new DivElement(dom);
case "span":
return new SpanElement(dom);
}
return new PassthroughElement(dom);
}
}
...
builder.Register<Func<IHtml, IElement>>(ElementFactory.Create);
Quel est l'avantage de remplacer cette usine par Autofac? – Steven
Désolé, comme je l'ai fait allusion dans mon commentaire sur la réponse de KeithS, j'espérais qu'il y aurait un peu de vaudou AutoFac qui m'a permis d'éviter le changement. Quel est l'avantage d'éviter l'interrupteur? Je ne sais pas ... Je semble juste avoir été endoctriné avec une aversion pour eux :( –
IoC n'est pas une baguette magique.Vous pouvez utiliser des enregistrements nommés, et vous pouvez supprimer le commutateur, mais à la fin, il y aura toujours une sorte de Logique de commutation Mon conseil: utiliser une usine pour son usine et enregistrer l'usine dans Autofac – Steven