I have an object graph as,
Client -> Handler -> HandlerSettings
and my app has multiple Client
s with different HandlerSettings
s.
// instances
Client1 -> Handler1 -> HandlerSettings1
Client2 -> Handler2 -> HandlerSettings2
...
Autofac's dynamic instantiation for named services is not working. I can get it to work with just named services and skipping dynamic instantiation, but wanted to know why it fails and, what are my options?
For example, with,
public class Depy1
{ }
public class Class1
{
public Class1(Depy1 depy1)
{ }
}
public class Class2
{
public Class2(Func<Depy1> depy1) // dynamic instantiation
{ }
}
and DI as,
var named = "bork!";
builder.RegisterType<Depy1>()
.Named<Depy1>(named)
.InstancePerDependency();
builder.RegisterType<Class1>()
.WithParameter(ResolvedParameter.ForNamed<Depy1>(named))
.InstancePerDependency();
builder.RegisterType<Class2>()
.WithParameter(ResolvedParameter.ForNamed<Depy1>(named))
.InstancePerDependency();
and resolution as,
var class1 = container.Resolve<Class1>(); // works
var class2 = container.Resolve<Class2>(); // throws!
the class2
resolution throws DependencyResolutionException
as,
Autofac.Core.DependencyResolutionException
HResult=0x80131500
Message=None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'Example.Class2' can be invoked with the available services and parameters:
Cannot resolve parameter 'System.Func`1[Example.Depy1] depy1' of constructor 'Void .ctor(System.Func`1[Example.Depy1])'.
Source=Autofac
StackTrace:
at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)
at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)
at Autofac.Core.Resolving.InstanceLookup.Execute()
at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)
at Autofac.Core.Resolving.ResolveOperation.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)
at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters)
at Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)
at Autofac.Core.Container.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)
at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance)
at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable`1 parameters)
at Autofac.ResolutionExtensions.Resolve(IComponentContext context, Type serviceType, IEnumerable`1 parameters)
at Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context, IEnumerable`1 parameters)
at Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context)
at Example.Program.<Showcase>d__2.MoveNext() in D:\work\client\samples\Example\Program.cs:line 175
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Example.Program.<Main>d__0.MoveNext() in D:\work\client\samples\Example\Program.cs:line 34
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Example.Program.<Main>(String[] args)
This exception was originally thrown at this call stack:
[External Code]
Example.Program.Showcase(Autofac.IContainer, Microsoft.Extensions.Configuration.IConfigurationRoot) in Program.cs
[External Code]
Example.Program.Main(string[]) in Program.cs
[External Code]
When calling ResolvedParameter.ForNamed
, you need to use the actual type in the constructor. That means that instead of ForNamed<Depy1>(...)
, you need to specify ForNamed<Func<Depy1>>(...)
, changing your registration of Class2
to:
builder.RegisterType<Class2>()
.WithParameter(ResolvedParameter.ForNamed<Func<Depy1>>(named))
.InstancePerDependency();