Passage automatique des parameters aux types nesteds

J’utilise Autofac comme IoC dans mon service WCF. Je souhaite transférer un object à un type nested (c’est-à-dire un type qui n’est pas résolu directement, mais lors de la résolution d’un autre type). Autant que je sache, passer cet object en tant que paramètre constructeur est la méthode préférée dans Autofac. Voici un exemple d’une telle situation.

Le type nested:

public class EventLogger : IEventLogger { public EventLogger(IRepository repository, User currentUser) { ... } } 

Le type que je suis en train d’essayer de résoudre:

 public class SomeBusinessObject { public SomeBusinessObject(IEventLogger logger, ...) { ... } } 

L’enregistrement:

 var builder = new ContainerBuilder(); builder.RegisterGeneric(typeof(Repository)).As(typeof(IRepository)); builder.RegisterGeneric(typeof(EventLogger)).As(typeof(IEventLogger)); builder.RegisterType(); 

La résolution à l’intérieur de mon opération de service WCF:

 var currentUser = GetUserFromServiceContext(); var bo = lifetimeScope.Resolve(); 

Comment et où devrais-je passer l’utilisateur actuel à mon enregistreur? Devrais-je supposer que l’opération WCF doit savoir que la résolution de SomeBusinessObject nécessite de résoudre d’abord IEventLogger et de transmettre une instance résolue lors de la résolution de SomeBusinessObject? Quelque chose comme ça (pardonnez-moi si ça ne marche pas, c’est juste une idée):

 var currentUser = GetUserFromServiceContext(); var logger = lifetimeScope.Resolve<IEventLogger>(new NamedParameter("currentUser", currentUser)); var bo = lifetimeScope.Resolve(new NamedParameter("logger", logger)); 

Si c’est la solution, que se passe-t-il si le type est nested plus profondément? Cela n’atteint-il pas au moins une partie de l’objective de l’dependency injection?

IMHO, je pense que vous enfreignez l’un des principes de la COI en ce sens qu’un composant ne devrait pas avoir besoin de connaître les dépendances de ses dépendances. Dans votre cas, le conteneur ne sait pas que SomeBusinessObject a une dépendance sur User .

Cela étant dit, vous pourrez peut-être utiliser les usines de délégué d’Autofac. Vous pouvez enregistrer manuellement un Func pour masquer les détails de la chaîne de dépendance à partir du code client:

 var builder = new ContainerBuilder(); builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)); builder.RegisterGeneric(typeof(EventLogger<>)).As(typeof(IEventLogger<>)); builder.RegisterType(); builder.Register>(c => { // Autofac should be able to resolve these Func<> automatically: var loggerFactory = c.Resolve>>(); var sboFactory = c.Resolve, SomeBusinessObject>>(); // Now we can chain the Funcs: return u => sboFactory(loggerFactory(u)); }); 

Maintenant, dans votre code client, vous pouvez faire:

 var currentUser = GetUserFromServiceContext(); var sboFactory = lifetimeScope.Resolve>(); var bo = sboFactory(currentUser); 

En passant, je pense que le support de lamba / Func est ce qui fait d’Autofac le meilleur conteneur IOC. Vous pouvez faire des choses folles et puissantes si vous savez composer des Funcs.