Autofac: Allow a specific dependency on a named instance
Using Autofac I would like to register a component and specify which specific dependency will be resolved for the named instance.
I found samples like the following using constructor injection, which is almost what I want.
builder.Register(c => new ObjectContainer(ConnectionStrings.CustomerDB))
.As<IObjectContainer>()
.Named("CustomerObjectContainer");
builder.Register(c => new ObjectContainer(ConnectionStrings.FooDB))
.As<IObjectContainer>()
.Named("FooObjectContainer");
builder.Register(c => new CustomerRepository(
c.Resolve<IObjectContainer>("CustomerObjectContainer"));
builder.Register(c => new FooRepository(
c.Resolve<IObjectContainer>("FooObjectContainer"));
However, I need this with introducing properties and I don't want to list all dependencies.
Something like:
builder.Register<CustomerRepository>().With<IObjectContainer>("CustomerObjectContainer");
builder.Register<FooRepository>().With<IObjectContainer>("FooObjectContainer");
Combining all undefined dependencies must happen on unnamed instances.
Thanks, Alex
[ADDITION FROM ANSWER FROM Danielg]
An overload for type resolution for any property of that type.
public static IRegistrationBuilder<TLimit, TReflectionActivatorData, TStyle> WithDependency<TLimit, TReflectionActivatorData, TStyle, TProperty>(
this IRegistrationBuilder<TLimit, TReflectionActivatorData, TStyle> registration,
Func<IComponentContext, TProperty> valueProvider)
where TReflectionActivatorData : ReflectionActivatorData
{
return registration.WithProperty(new ResolvedParameter((p, c) =>
{
PropertyInfo prop;
return p.TryGetDeclaringProperty(out prop) &&
prop.PropertyType == typeof(TProperty);
},
(p, c) => valueProvider(c)));
}
source to share
I don't think autofac has a shorthand way to do this yet, but it is possible with a little effort.
I wrote an extension method that does this. Throw it into a static extension class and you should be fine. The extension also shows you how to do it a long way.
public static IRegistrationBuilder<TLimit, TReflectionActivatorData, TStyle> WithResolvedProperty<TLimit, TReflectionActivatorData, TStyle, TProperty>(
this IRegistrationBuilder<TLimit, TReflectionActivatorData, TStyle> registration,
string propertyName, Func<IComponentContext, TProperty> valueProvider)
where TReflectionActivatorData : ReflectionActivatorData
{
return registration.WithProperty(new ResolvedParameter((p, c) =>
{
PropertyInfo prop;
return p.TryGetDeclaringProperty(out prop) &&
prop.Name == propertyName;
},
(p, c) => valueProvider(c)));
}
Ignore the super long method signature, autofac registration is very verbose.
You can use an extension like this.
builder.RegisterType<Foo>()
.WithResolvedProperty("Bar", c => c.Resolve<IBar>());
source to share