8

Tengo el tipo más simple de dependencia circular en structuremap: la clase A se basa en la clase B en su constructor, y la clase B se basa en la clase A en su constructor. Para romper la dependencia, hice que la clase B tomara la clase A como propiedad, en lugar de un argumento de constructor, pero structuremap aún se queja.Dependencias circulares en StructureMap: ¿se pueden romper con la inyección de propiedades?

He visto las dependencias circulares rotas con este método en otros marcos DI. ¿Esto es un problema con Structuremap o estoy haciendo algo mal?

Editar: debería mencionar la propiedad de que la clase de B es un conjunto de instancias de la clase A, cableados así:

x.For<IB>().Singleton().Use<B>().Setter(y => y.ArrayOfA).IsTheDefault(); 

Solo para aclarar, quiero que la siguiente secuencia de eventos que se produzcan:

  • Construir una instancia de B, "b"
  • Construir una instancia de a, "a", la inyección de "b" en su constructor
  • Set "b.ArrayOfA" a [ "a"]

Y quiero que todo esto suceda usando autowiring, si es posible ...

Edición 2: Aquí está un ejemplo simplificado que los usos explícita cableado hasta:

interface ILoader { } 
interface ILoaderManager { } 

class Loader : ILoader 
{ 
    public Loader(ILoaderManager lm) { } 
} 
class LoaderManager : ILoaderManager 
{ 
    public ILoader Loader { get; set; } // Was an array, but same circular dependency appears here 
} 

ObjectFactory.Configure 
(
    x => 
    { 
     x.For<ILoader>.Singleton().Use<Loader>(); 
     x.For<ILoaderManager>().Singleton().Use<LoaderManager>().OnCreation((c, a) => a.Loader = c.GetInstance<ILoader>()); 
    } 
); 

Validación de las causas de configuración "bidireccional Dependencia problema detectado con requestedType: IocTest2.ILoader ..."

Respuesta

3

Lo más cerca que se puede conseguir es algo como esto:

x.For<IB>().Use<B>() 
    .OnCreation((ctx, instance) => 
    { 
     instance.ArrayOfA = new IA[] {new A(instance) }; 
    }); 

Si A tiene otras dependencias que desea resolver desde el contenedor, puede recuperarlas desde ctx dentro de la conexión de OnCreation.

+0

Hola Joshua - Acabo de probarlo y obtuve un "Problema de dependencia bidireccional" - ¿Creo que esto es un signo de una dependencia circular en StructureMap? ¿Es la construcción y configuración de un objeto por StructureMap efectivamente atómica, por lo que las referencias circulares no se pueden resolver? Parece poco probable, pero hasta ahora no he podido hacer que funcione ... – Andy

+0

Dependencia bidireccional El problema indica una referencia circular. Sin embargo, la muestra de código que proporcioné FUNCIONará, ya que la instancia de B se crea antes de que se invoque a OnCreation lambda. Luego puede pasar esa instancia de B al constructor de A y luego establecer la propiedad de B en A. He probado el código anterior y funciona. Si aún tiene problemas de referencia circular, debe haber otras dependencias que no haya mencionado. –

+0

Debo aclarar que al usar mi ejemplo de código, NO debe establecer ninguna política para que StructureMap realice la inyección setter en B. Está realizando manualmente la inyección setter en OnCreation lambda. –

0

Es probable que StructureMap realice Setter Injection donde poblará propiedades públicas configurables en un objeto que está resolviendo. Según la documentación,

Por defecto, todas las "Incubadoras" públicas son opcionales, lo que significa que estos emisores sólo se pueden configurar si se están configuradas de forma explícita para una instancia específica

Así que tienes por casualidad configurar las propiedades para ser auto cableadas? Si es así, igual tendrá el problema de dependencia circular.

Editar: Veo que tienes. En el ejemplo, porque tiene una [] inyectada B, StructureMap debe resolver la dependencia de cada una para un B que necesita un [], y así sucesivamente ...

+0

IIRC, he intentado lo mismo en el castillo de Windsor. Hizo la resolución de la propiedad después de resolver los constructores del componente, lo que significaba que la dependencia circular se había roto efectivamente. Asumiendo que no estaba soñando con este hecho, me preguntaba si StructureMap tenía una instalación similar. – Andy

+0

Hay un ejemplo de soluciones de dependencia circular con Windsor y StructureMap aquí: http://bit.ly/aZsr9c. Sé que es un poco más viejo, pero aún puede aplicarse. Noté que usó 'TheInstanceNamed (" Processor1 ")' para la última configuración de SetterDependency, ¿quizás eso ayude? – statenjason

+0

Hola statenjason, muchas gracias por su ayuda y el enlace. Lo intenté y todavía obtuve la dependencia circular. He modificado mi pregunta con un pequeño fragmento de código para ilustrar el problema. – Andy

5

StructureMap puede manejar situaciones bidireccionales también con una solución mediante la resolución Lazy.

Si usted tiene una situación simple como ClassA que depende de ClassB y ClassB que depende de ClassA, a continuación, puede elegir uno de ellos y convertir la dependencia como una dependencia perezoso. De esta manera trabajó para mí y ese error nunca apareció de nuevo ..

public class ClassA 
{ 
    private readonly Lazy<IClassB> _classB; 

    public Thing1(Lazy<IClassB> classB) 
    { 
     _classB = classB; 
    } 

    public IClassB ClassB => _classB.Value; 
} 

public class ClassB 
{ 
    public IClassA _classA { get; set; } 

    public ClassB (IClassA classA) 
    { 
     _classA = classA; 
    } 
} 

Más información aquí: http://structuremap.github.io/the-container/lazy-resolution/

+0

Esto es ** mucho ** mejor que la respuesta aceptada. –

Cuestiones relacionadas