The autofac wiki page about Circular References says to use:
cb.Register<DependsByProp>().OnActivated(ActivatedHandler.InjectUnsetProperties);
But it looks like ActivatedHandler does not exist anymore in 2.4.5. Digging around in the source, I found the implementation of that class, and so I put in the method implementation in the OnActivated instead. Unfortunately, it this still doesn't work.
I've put together a minimal repro here that looks like what was on the Wiki page.
class M
{
public VM VM { get; set; }
public M()
{
}
}
class VM
{
public VM(M m)
{
}
}
[Fact]
void CanResolveCircular()
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<VM>();
builder.RegisterType<M>().OnActivated(e => e.Context.InjectUnsetProperties(e.Instance));
using (var container = builder.Build())
{
var m = container.Resolve<M>();
Assert.NotNull(m);
}
}
This code still throws a stack overflow exception as a Resolve is attempted. What am I missing? What is the correct way to get Autofac to handle circular dependencies?
The Autofac documentation for circular dependencies states:
Note, it doesn't make sense to set up this scenario if both classes are registered with Factory scope.
Both your M
and VM
registrations are InstancePerDependency
(previously known as FactoryScope
) so this statement applies to your scenario. As a result, you get in an endless loop of creating M and VM instances.
If you want the property injected VM
to take the same instance of M
that you resolve, you should change the lifetime of M
to something other than InstancePerDependency
(e.g. SingleInstance
). This is shown below:
builder.RegisterType<M>().PropertiesAutowired(true).SingleInstance();
Note: I'm also using the more recent PropertiesAutowired(true) extension method. You can use this in place of the OnActivated code in your repro.
If you don't want a single instance of M
per app, you could setup a LifetimeScope
and use InstancePerLifetimeScope
.