Autofac passing parameter to nested types - c#

I am using Autofac as my IoC in my WCF service. I have a situation where I want to pass an object to a nested type (ie a type that is not resolved directly, but when resolving another type). As far as I understood, passing this object as a constructor parameter is the preferred way in Autofac. Here is an example of such a situation.
The nested type:
public class EventLogger<T> : IEventLogger<T>
{
public EventLogger(IRepository<T> repository, User currentUser) { ... }
}
The type I am actually trying to resolve:
public class SomeBusinessObject
{
public SomeBusinessObject(IEventLogger<SomeLogEventType> logger, ...) { ... }
}
The registration:
var builder = new ContainerBuilder();
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));
builder.RegisterGeneric(typeof(EventLogger<>)).As(typeof(IEventLogger<>));
builder.RegisterType<SomeBusinessObject>();
The resolving inside my WCF service operation:
var currentUser = GetUserFromServiceContext();
var bo = lifetimeScope.Resolve<SomeBusinessObject>();
How and where should I pass the current user to my logger? Should I assume that the WCF operation has to know that resolving SomeBusinessObject requires to resolve IEventLogger first and pass a resolved instance when resolving SomeBusinessObject? Something like this (pardon me if this does not work, it 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 the solution, what happens if the type is nested deeper? Doesn't that defeat at least some of the purpose of dependency injection?

IMHO, I think you're violating one of the principles of IOC in that a component should not need to know about the dependencies of it's dependencies. In your case, the container doesn't know that SomeBusinessObject has a dependency on User.
That being said, you may be able to leverage Autofac's Delegate Factories. You could manually register a Func<User, SomeBusinessObject> to hide the dependency chain details 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 your client code, you can do:
var currentUser = GetUserFromServiceContext();
var sboFactory = lifetimeScope.Resolve<Func<User, SomeBusinessObject>>();
var bo = sboFactory(currentUser);
As an aside, I think the lamba/Func support is what makes Autofac the best IOC container. You can do some crazy powerful things if you know how to compose Funcs.

Related

When using Autofac's autoregister functionality, how can I specify that one type should be InstancePerRequest

We have a Web API project and using the Autofac Web API Integration as the IoC container. The code that we use to register all of our types is as follows:
public class CompositionRootConfigurator
{
public static AutofacWebApiDependencyResolver Configure(Assembly servicesAssembly)
{
var container = BuildContainer(servicesAssembly);
var resolver = new AutofacWebApiDependencyResolver(container);
return resolver;
}
public static IContainer BuildContainer(Assembly servicesAssembly)
{
/*TO DELETE ONCE THE REFERENCES ISSUE IS RESOLVED!*/
var dummy = new EmployeesBL(new ContextFactory(new DBContextFactory(new RoleBasedSecurity(), new Identity())));
var builder = new ContainerBuilder();
if (servicesAssembly != null) // this is a temporary workaround, we need a more solid approach here
{
builder.RegisterApiControllers(servicesAssembly);
}
/* Registers all interfaces and their implementations from the following assemblies in the IoC container
* 1. CB.CRISP.BL
* 2. CB.CRISP.BL.CONTRACTS
* 3. CB.CRISP.DAL
* 4. CB.CRISP.DAL.CONTRACTS
* The current assembly is excluded because the controllers were registered with the builder.RegisterApiControllers expression above.
*/
var appAssemblies = AppDomain.CurrentDomain
.GetAssemblies()
.Where(a => a.ToString().StartsWith("CB.CRISP"))
.ToArray();
builder.RegisterAssemblyTypes(appAssemblies).AsImplementedInterfaces();
if (servicesAssembly != null)
{
builder.RegisterAssemblyTypes(servicesAssembly).AsImplementedInterfaces();
}
return builder.Build();
}
}
Now suppose we have a MyType which implements IMyType and this is the only one that must be a single instance per request and it will be injected in several objects along the hierarchy.
I am at a loss in how to specify this within this existing code. If I just go ahead and just do
builder.RegisterType<MyType>()
.As<IMyType>()
.InstancePerRequest();
since it will also be registered with all the others Will one registration overwrite the other one, will they be duplicated, are there potential problems?
Thank you for your insight.
Autofac will override the first registration and will accept the last one. Here is more detail.
So you should register MyType after registering all type.
I haven't seen any potential problem of this.
But you can register all types like this to be sure.
builder.RegisterAssemblyTypes(servicesAssembly).Except<MyType>().AsImplementedInterfaces();
Here is more detail about scanning.

Any DI Container where Transient is truly Transient during a nested/child container?

I have a requirement were I need some instances of my domain to remain the same during a scope of my choosing. These instances are an exception and the norm should be that all instances are new each time they are requested by the domain. (The way transient life time should work)
Problem is I cant find a DI Container that works this way.
I have tested Castle Windsor and StructureMap.
In StructureMap you do
using(var nested = container.GetNestedContainer())
{
var whatEver = nested.GetInstance<IWhatEver>();
}
The default will now be that the instances live during the entire life of the nested container. If you want the behavior I want you need to register all types that should be truly transient like
config
.For<IMyTransientType>()
.LifecycleIs(new UniquePerRequestLifecycle())
.Use<MyTransientType>();
This will not work, I want the default behavior to be the other way around. So do you guys know a IoC that work this way, or that can be configured so that default behavior is like this.
edit: For the curious you can check out this working branch here using Structure map, https://github.com/AndersMalmgren/FreePIE/blob/MoveToStructureMap/FreePIE.Core/Common/StructureMap/StructureMapScopedContext.cs. You can anywere in the domain create a scoped life time using the interface IScopedContext<TEntryPoint>. Problem is that it defualts to "scoped" lifetime instead of transient life time. To get real transient life time you need set it to always unique. I have solved it for unregister concrete types with this little hacky helper
https://github.com/AndersMalmgren/FreePIE/blob/MoveToStructureMap/FreePIE.Core/Common/StructureMap/ConcreteTypeConventionScanner.cs
From the DI bootstrapper I then do
var assebmlies = container
.GetInstance<IPluginDataSource>()
.ListAllPluginTypes()
.GroupBy(t => t.Assembly)
.Select(g => g.Key);
assebmlies.ForEach(a => container.Configure(config => config.Scan(scan =>
{
scan.Assembly(a);
scan.Convention<ConcreteTypeRegistrationConvention>();
})));
Simple Injector offers support for a variety of scoped lifestyles without the need for child containers. By default Simple Injector will return Transient within any lifetime scope unless explicitly instructed to do otherwise. Here are 3 tests to demonstrate the functionality ...
Transient with no scope
[Fact]
public void GetInstance_NoSpecificLifestyleOutsideOfAnyScope_IsAlwaysANewInstance()
{
var container = new Container();
container.Register<IService, Service>();
container.Verify();
var a = container.GetInstance<IService>();
var b = container.GetInstance<IService>();
Assert.NotSame(a, b);
}
Non transient IService registered with an explicit lifestyle
[Fact]
public void GetInstance_SpecificLifestyleWithinAScope_IsTheSameInstance()
{
var container = new Container();
container.Options.DefaultScopedLifestyle = new LifetimeScopeLifestyle();
container.Register<IService, Service>(Lifestyle.Scoped);
container.Verify();
using (container.BeginLifetimeScope())
{
var a = container.GetInstance<IService>();
var b = container.GetInstance<IService>();
Assert.Same(a, b);
}
}
Transient IService resolved within a lifetime scope
[Fact]
public void GetInstance_NoSpecificLifestyleWithinAScope_IsAlwaysANewInstance()
{
var container = new Container();
container.Options.DefaultScopedLifestyle = new LifetimeScopeLifestyle();
container.Register<IService, Service>();
container.Verify();
using (container.BeginLifetimeScope())
{
var a = container.GetInstance<IService>();
var b = container.GetInstance<IService>();
Assert.NotSame(a, b);
}
}

Autofac - Components ignore dependency defined in lifetime scope

I could well be misunderstanding something here, so perhaps there is a simple answer here but I'm currently scratching my head.
I have a class UnitOfWork that implements IUnitOfWork (yes yes I know). The constructor for unit of work takes an IPrincipalFactory. TResponder is the top level of the graph which takes an IUnitOfWork.
I'm trying to register the ApplicationPrincipalFactory as a specific instance in a lifetime scope... it's dependant on some properties passed to the HandleAsync function. I'm doing the following:
public async Task<TResponse> HandleAsync<TMessage, TResponse, TResponder>(TMessage message)
where TMessage : class
where TResponder : IRespondAsync<TMessage, TResponse>
{
using (var scope = this.BeginLifetimeScope(message))
{
var responder = scope.Resolve<TResponder>();
return await responder.Respond(message);
}
}
private ILifetimeScope BeginLifetimeScope<TMessage>(TMessage message)
{
var unwrapped = GetDomainContext(message);
var applicationPrincipalFactory = this.CreateApplicationPrincipalFactory(unwrapped);
var lifetime = this.container.BeginLifetimeScope(
r => r.RegisterInstance(applicationPrincipalFactory).As<IPrincipalFactory>());
return lifetime;
}
private ApplicationPrincipalFactory CreateApplicationPrincipalFactory(IDomainContext unwrapped)
{
var applicationPrincipalFactory =
new ApplicationPrincipalFactory(
unwrapped.Tenant,
unwrapped.ActingTenant,
unwrapped.Username);
return applicationPrincipalFactory;
}
Based on everything I've read, defining the dependency within BeginLifetimeScope(r => should override the parent container binding, so when I call resolve, it should all slot neatly together.
However, I get an exception:
None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'Platform.Engine.Persistence.UnitOfWork' can be invoked with the available services and parameters: Cannot resolve parameter 'Platform.Engine.Security.IPrincipalFactory principalFactory' of constructor
I am not registering the IPrincipalFactory anywhere other than in this method. The IUnitOfWork is defined in the outer scope as follows:
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerLifetimeScope();
I have also tried re-defining the unitofwork registration within the child container in case it was an issue cause by registering it in the outer container rather than the lifetime one:
var lifetime = this.container.BeginLifetimeScope(
r => r.RegisterInstance(applicationPrincipalFactory).As<IPrincipalFactory>());
var overrides = new ContainerBuilder();
overrides.RegisterType<UnitOfWork>().As<IUnitOfWork>();
overrides.Update(lifetime.ComponentRegistry);
return lifetime;
I'm not sure what I'm missing... any ideas or suggestions?
Register your factory with the rest of your types during the initial container configuration.
builder.RegisterType<ApplicationPrincipalFactory>().As<IPrincipalFactory>();
Then in your lifetime scope resolve a delegate factory that you can pass the context into.
var factory = container.Resolve<Func<IDomainContext, IPrincipalFactory>>();
var instance = factory(context);
You could also add three string parameters to the Func<> signature, but since you already have a nice context object I would just pass that in instead.
Finally, use the factory as needed.
instance.DoesSomethingButNotSureWhat();
That will prevent you from having to update the lifetime scope just to pass in the context parameter.

Is there a way to eagerly resolve all components registered with Windsor IoC container?

I have C# application where I register a few dozen interfaces with their implementation classes in the Windsor container. All these implementation classes are resolved as singletons by Windsor. The question is can I somehow make Windsor manually resolve all these stuff and wire them to create a object graph? Rather than lazy resolving that Windsor does by default when some component is request, I need to resolve them all at once for some debugging and testing purposes. Ideally I'd like to get the array of instances for all registered types. Is this possible?
The dependency graph is available through the GraphNodes property. Here's a simple demonstration:
[Test]
public void Get1()
{
var container = new WindsorContainer();
container.Register(Component.For<SomeClass>().LifestyleSingleton());
container.Register(Component.For<Dependency>().LifestyleSingleton());
var graphNodes = container.Kernel.GraphNodes;
Assert.That(graphNodes.Length, Is.EqualTo(2));
Assert.That(graphNodes[0].Dependents[0].ToString(), Is.EqualTo(typeof(Dependency).Name));
Assert.That(graphNodes[1].Dependents.Length, Is.EqualTo(0));
}
You should easily be able to establish which types are "root" types by filtering out any types that are a dependency ...
UPDATE
One of the ways to create an instance from a GraphNode is to cast the GraphNode to Castle.Core.ComponentModel
[Test]
public void Resolve1()
{
var container = new WindsorContainer();
container.Register(Component.For<SomeClass>().LifestyleSingleton());
container.Register(Component.For<Dependency>().LifestyleSingleton());
var graphNodes = container.Kernel.GraphNodes;
var name = (graphNodes[0] as ComponentModel).ComponentName.ToString();
var type = Type.GetType(name);
dynamic instance1 = container.Resolve(type);
Assert.That(instance1, Is.Not.Null);
}
Usually for debugging and testing the container you may use the component handler instead of resolving the component itself.
Said so, Simon is right: when you Resolve a component, windsor creates the real instance and all its dependencies. Nothing is "deferred" unless you mean "late dependency" achived through a (typed) factory, but that's somenthing else...
The solution that uses ComponentName doesn't work. ComponentModel.Services should be used instead. Tested with version 3.3
container.Kernel.GraphNodes
.Cast<ComponentModel>()
.ToList()
.ForEach(component =>
{
component.Services
.ToList()
.ForEach(type =>
{
var instance = container.Resolve(type);
Assert.IsNotNull(instance);
});
});

C# Dependency Injection and the Strategy Pattern

I'm using Munq as the DI container in a MVC3 project. I have a service layer that retrieves a DTO from a repository. Depending on a property in that DTO I need to use one of two strategies to perform calculations on the DTO. I can register a named type in the container e.g.
Container.Register<ICalculation>("Type1", c => new Type1Calculation);
Container.Register<ICalculation>("Type2", c => new Type2Calculation);
Then I can refer directly to the container when trying to instantiate the appropriate strategy e.g.
var calc = Container.Resolve<ICalculation>(dto.ServiceType);
But this leaves me with a dependency on the container itself with the associated coupling and testing issues. What do I need to pass into the service constructor that would allow me to get the correct calculation but without the dependency on the container? Should I pass in a factory instead so the dependency is in the factory and not in the service class?
Not sure about Munq, but Autofac allows you to pass around Funcs, so that you can skip all factories altogether:
public class Foo
{
public Foo(Func<string, IBar> barFactory) { }
}
Check if Munq allows for such behavior.
Otherwise -- yes, you'll have to resort to hand-written factories to provide yet another level of indirection.
I've added the Munq solution to this. First the factory which includes the IDependencyResolver interface to allow the factory to use the container to resolve dependencies in the factory method:
public class CalculationFactory
{
private readonly IDependencyResolver _resolver;
public CalculationFactory(IDependencyResolver resolver)
{
ThrowIfNullArgument(resolver, "resolver", typeof(IDependencyResolver));
_resolver = resolver;
}
public static ICalculation CreateCalculator(int serviceType)
{
switch (serviceType)
{
case 1: return _resolver.Resolve<ICalculation>("Type1");
case 2: return _resolver.Resolve<ICalculation>("Type2");
default: return _resolver.Resolve<ICalculation>("InvalidType");
}
}
}
Then in Global.asax.cs register the appropriate interfaces/classes, passing in the container to the factory. So now I can set up my tests and the only extra dependency is IDependencyResolver within the factory:
ioc.Register(c => new CalculationFactory(c));
ioc.Register<ICalculation>("Type1", c => c.Resolve<Type1Calculation>());
ioc.Register<ICalculation>("Type2", c => c.Resolve<Type2Calculation>());
ioc.Register<ICalculation>("InvalidType", c => c.Resolve<InvalidCalculation>());

Categories