I just can't seem to wrap my brain around this situation in Autofac:
So I tried to create a factory for IFinal, but I can't seem to get the resolution right.
Example code:
public static void Main(string[] args)
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<Dependency>().As<IDependency>();
builder.RegisterType<Final>().As<IFinal>();
// this fails because context c is not available at the time finalObjectFactoryMethod is used
builder.Register<Factory>((c,p)=>{
var dependency = c.Resolve<IDependency>();
Func<int, IFinal> finalObjectFactoryMethod =
rta => c.Resolve<IFinal>(
new TypedParameter(typeof(IDependency), dependency),
new TypedParameter(typeof(int), rta)
);
return new Factory(finalObjectFactoryMethod);
}).As<IFactory>();
// this works but doesn't use the resolve mechanism for IFinal
/*
builder.Register<Factory>((c,p)=>{
var dependency = c.Resolve<IDependency>();
Func<int, IFinal> finalObjectFactoryMethod = rta => new Final(dependency, rta);
return new Factory(finalObjectFactoryMethod);
}).As<IFactory>();
*/
IContainer container = builder.Build();
IFactory factory = container.Resolve<IFactory>();
IFinal final = factory.GetFinalObject(42);
}
}
public interface IDependency{}
public class Dependency: IDependency{}
public interface IFinal
{
void Test();
}
public class Final: IFinal
{
public Final(IDependency dependency, int runtimeArgument){}
public void Test(){}
}
public interface IFactory
{
IFinal GetFinalObject(int runtimeArgument);
}
public class Factory: IFactory
{
readonly Func<int, IFinal> _finalObjectFactoryMethod;
public Factory(Func<int, IFinal> finalObjectFactoryMethod)
{
_finalObjectFactoryMethod = finalObjectFactoryMethod;
}
public IFinal GetFinalObject(int runtimeArgument)
{
return _finalObjectFactoryMethod(runtimeArgument);
}
}
Google and Autofac documentation could not help me on this.
Somehow there seems to be a knot in my brain, maybe I just try to use the wrong pattern.
I'm pretty sure there is a solution for this, but I just can't find it.
You have to add a factory delegate
to Final
:
public class Final : IFinal
{
public delegate IFinal Factory(int runtimeArgument);
public Final(IDependency dependency, int runtimeArgument) { }
public void Test() { }
}
Autofac is clever enough to fill the other parameters in so your factory delegate can only have parameters you specify at runtime and the other ones are resolved by magic.
Then you register the type:
builder
.RegisterType<Final>()
.As<IFinal>();
Here's the complete example:
public static void Main(string[] args)
{
ContainerBuilder builder = new ContainerBuilder();
builder
.RegisterType<Dependency>()
.As<IDependency>();
builder
.RegisterType<Final>()
.As<IFinal>();
using(var container = builder.Build())
using (var scope = container.BeginLifetimeScope())
{
var finalFactory = scope.Resolve<Final.Factory>();
IFinal final = finalFactory(42);
}
}
You don't need the Factory
class at all. The delegate can either be resolved directly from scope
or used the same way as any other dependency and injected by Autofac. Just juse Final.Factory
as your dependency.
The documentation describes this technique in the Delegate Factories
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With