5

La página wiki autofac sobre Circular References dice que use:¿Cómo manejar referencias circulares con Autofac 2.4.5?

cb.Register<DependsByProp>().OnActivated(ActivatedHandler.InjectUnsetProperties); 

pero parece que ActivatedHandler ya no existe en 2.4.5. Buscando en la fuente, encontré la implementación de esa clase, así que puse la implementación del método en OnActivated. Lamentablemente, esto todavía no funciona.

He creado una copia mínima aquí que se parece a lo que estaba en la página Wiki.

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); 
    } 
} 

Este código todavía arroja una excepción de desbordamiento de pila cuando se intenta resolver. ¿Qué me estoy perdiendo? ¿Cuál es la forma correcta de hacer que Autofac maneje dependencias circulares?

+0

Sí. Pensé que las dependencias circulares significaban lo mismo que los ciclos de instancias. Su respuesta a continuación señaló lo que me faltaba sobre los conceptos de dependencias circulares entre clases e instancias. – Ants

Respuesta

7

La documentación Autofac para circular dependencies estados:

Nota, no tiene sentido para establecer este escenario, si ambas clases son registrado en el alcance de la fábrica.

Ambas sus M y VM registros se InstancePerDependency (anteriormente conocidos como FactoryScope) por lo que esta afirmación se aplica a su escenario. Como resultado, obtiene un bucle sin fin de crear instancias de M y VM.

Si desea que la propiedad inyecta VM a tomar la misma instancia de M que resuelva, debe cambiar el curso de la vida de M a algo distinto de InstancePerDependency (por ejemplo SingleInstance). Esto se muestra a continuación:

builder.RegisterType<M>().PropertiesAutowired(true).SingleInstance(); 

Nota: También estoy usando el reciente PropertiesAutowired método (verdadero) de extensión más. Puedes usar esto en lugar del código OnActivated en tu repro.

Si no desea que una sola instancia de M por aplicación, usted puede configurar un LifetimeScope y utilizar InstancePerLifetimeScope.

5

Para cualquier persona interesada aquí es la nueva forma de hacer esto:

class DependsByProp1 
{ 
    public DependsByProp2 Dependency { get; set; } 
} 

class DependsByProp2 
{ 
    public DependsByProp1 Dependency { get; set; } 
} 

// ... 

var cb = new ContainerBuilder(); 
cb.RegisterType<DependsByProp1>() 
     .InstancePerLifetimeScope() 
     .PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies); 
cb.RegisterType<DependsByProp2>() 
     .InstancePerLifetimeScope() 
     .PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies); 

Property/Property Dependencies

Cuestiones relacionadas