I have an Autofac container that uses "AnyConcreteTypeNotAlreadyRegisteredSource" to allow resolution of any concrete type without explicit need to register it. If I register a singleton instance of a concrete type using the RegisterInstance method, there are no issues with the resolution. However, if I create a child lifetime scope and do the same concrete type singleton instance registration, the child lifetime scope is not able to resolve the type anymore. It throws the following exception:
Autofac.Core.Activators.Reflection.NoConstructorsFoundException: 'No accessible constructors were found for the type 'AutofacTests.IssueTests+Manager'.'
Why is it even trying to instantiate the object when I have a singleton instance of that type registered already? It seems like this problem only comes when I try to resolve a concrete type instead of an interface.
Here is the test code that demonstrates the problem (The test method name and comments show what works and what does not):
using Autofac;
using Autofac.Features.ResolveAnything;
namespace AutofacTests
{
[TestClass]
public class IssueTests
{
private interface IPerson
{
}
private class Employee : IPerson
{
public Employee()
{
}
}
private class Manager : Employee
{
internal Manager(IPerson worker)
{
string s = "";
}
}
[TestMethod]
public void Resolution_ThatWorks()
{
ContainerBuilder builder = new ContainerBuilder();
var mgr = new Manager(null);
builder.RegisterInstance<IPerson>(mgr);
builder.RegisterInstance<Manager>(mgr);
using (var container = builder.Build())
{
var person = container.Resolve<Manager>();
Assert.IsNotNull(person, "Employee could not be resolved!");
}
}
[TestMethod]
public void ResolutionWithAnyTypeSource_ThatWorks()
{
ContainerBuilder builder = new ContainerBuilder();
// NOTE: This source registration does not impact the concrete type resolution when no child lifetime scope is involved.
builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource());
var mgr = new Manager(null);
builder.RegisterInstance<IPerson>(mgr);
builder.RegisterInstance<Manager>(mgr);
using (var container = builder.Build())
{
var person = container.Resolve<Manager>();
Assert.IsNotNull(person, "Employee could not be resolved!");
}
}
[TestMethod]
public void NestedResolution_ThatWorks()
{
ContainerBuilder builder = new ContainerBuilder();
using (var container = builder.Build())
{
void RegisterNestedServices(ContainerBuilder builder)
{
var mgr = new Manager(null);
builder.RegisterInstance<IPerson>(mgr);
builder.RegisterInstance<Manager>(mgr);
}
using (var childContainer = container.BeginLifetimeScope(RegisterNestedServices))
{
var person = childContainer.Resolve<Manager>();
Assert.IsNotNull(person, "Employee could not be resolved!");
}
}
}
[TestMethod]
public void NestedResolutionWithAnyTypeSource_ThatFails()
{
ContainerBuilder builder = new ContainerBuilder();
// NOTE: This source registration causes the resolution of a concrete type to fail in a child lifetime scope.
builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource());
using (var container = builder.Build())
{
void RegisterNestedServices(ContainerBuilder builder)
{
var mgr = new Manager(null);
builder.RegisterInstance<IPerson>(mgr);
builder.RegisterInstance<Manager>(mgr);
}
using (var childContainer = container.BeginLifetimeScope(RegisterNestedServices))
{
// Works
var person = childContainer.Resolve<IPerson>();
Assert.IsNotNull(person, "Person could not be resolved!");
// *** Fails ***
var emp = childContainer.Resolve<Manager>();
Assert.IsNotNull(emp, "Employee could not be resolved!");
}
}
}
}
}
Anyone has any idea what am I doing wrong or how to make this work in the child lifetime scopes?
Thanks.