New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RegistrationAccessor passed into IRegistrationSource does not account for registrations in child lifetime scope #1028
Comments
In the future it might help to see what's actually failing and where, like an exception with a call stack. Here's an update to the minimal repro that builds without warnings: using System;
using System.Collections.Generic;
using Autofac;
using Autofac.Features.ResolveAnything;
namespace autofacdemo
{
class Program
{
public interface IDependency
{
}
public class Concrete
{
public Concrete(IDependency dependency)
{
}
}
public class Dependency: IDependency
{
}
static void Main(string[] args)
{
var builder = new ContainerBuilder();
// Removing ACTNARS fixes things.
builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource());
using (var container = builder.Build())
{
// Removing the lifetime scope registration does not change the exception.
using (var scope = container.BeginLifetimeScope(cfg => cfg.RegisterInstance(new Concrete(new Dependency()))))
{
try
{
var concrete = scope.Resolve<IEnumerable<Concrete>>();
}
catch (Exception e)
{
Console.WriteLine("Unexpected exception {0}", e);
}
}
}
}
}
} When this runs, the exception is:
I find there are a couple of interesting things here, which I noted in the updated repro:
ACTNARS is a tricky beast. There are a couple of things at play: First, the var builder = new ContainerBuilder();
builder.RegisterType<Concrete>();
builder.RegisterType<Dependency>();
var container = builder.Build();
// This will FAIL because there's no `IDependency` registered.
container.Resolve<Concrete>(); Second, there's a false sense of security in using ACTNARS. It's not "try to resolve things and it's OK if you can't." It's more like... "If it's a concrete type, pretend I did You can totally register two identical things. var builder = new ContainerBuilder();
builder.RegisterType<Dependency>();
builder.RegisterType<Dependency>();
var container = builder.Build();
// There will be two things in this collection.
container.Resolve<IEnumerable<Dependency>>(); I understand the larger issue here is that this demonstrates a problem with how ACTNARS (and possibly other registration sources) detect "what's registered" vs. "what's not." I'm not entirely sure how to solve that. Just brainstorming about different factors...
Likely what needs to happen is that the I'm not sure how to adjust for that off the top of my head. It may be part of the new Definitely a bug, at least from the standpoint that it's doing something unexpected. |
This issue has been open for quite some time without any traction. Much as we understand the challenges presented here, we also get very few substantial contributions and we don't have time to really dig into non-trivial issues like this. As such, we're closing this issue. If someone feels like they really want this, we would love to see a PR where this gets addressed. |
When
RegistrationsFor
is invoked due to resolving inside a child lifetime scope, that has scoped registrations, those registrations are not available through the passed inregistrationAccessor
parameter.This is particularly problematic for sources such as ACTNARS that return a registration if there is not already one. In this case this results in multiple registrations for an already registered service.
Probably related to #218 and other lifetime scope related bugs.
Minimal repro:
The text was updated successfully, but these errors were encountered: