Autofac skip option for nested types

I use Autofac as my IoC in my WCF service. I have a situation where I want to pass an object a nested type (i.e. a Type that is not directly resolved, but when resolving another type). As I understand it, passing this object as a constructor parameter is the preferred method in Autofac. Here is an example of such a situation.

Nested Type:

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

The type I'm actually trying to solve is:

 public class SomeBusinessObject { public SomeBusinessObject(IEventLogger<SomeLogEventType> logger, ...) { ... } } 

Registration:

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

Permission inside my WCF service:

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

How and where should I transfer the current user to my registrar? Should I assume that the WCF operation needs to know that to solve SomeBusinessObject, you first need to enable IEventLogger and pass the allowed instance when SomeBusinessObject resolves? Something like this (forgive me if this does not work, this is just an idea):

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

If this is a decision, what happens if the type is nested deeper? Doesn't that spoil at least part of the goal of dependency injection?

+6
source share
1 answer

IMHO, I think that you violate one of the principles of IOC in that the component does not need to know about the dependencies of its dependencies. In your case, the container does not know that SomeBusinessObject has a dependency on User .

This way you can use Autofac Delegate Factories . You can manually register Func<User, SomeBusinessObject> to hide the dependency chain information from the client code:

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

Now in the client code you can:

 var currentUser = GetUserFromServiceContext(); var sboFactory = lifetimeScope.Resolve<Func<User, SomeBusinessObject>>(); var bo = sboFactory(currentUser); 

Aside, I think lamba / Func support is what makes Autofac a better IOC container. You can do some crazy powerful stuff if you know how to compose Funcs.

+5
source

Source: https://habr.com/ru/post/886370/


All Articles