¿Cómo manejar este escenario de resolución de DI?

So, lets assume I can draw in paint:

Horrible depiction of my problem

Di que tengo una clase A which depends on objects B y C to be instanced, but C also depends on an instance of B, and I want this instance of B to be the same that I pass to A. ¿Cómo puedo lograr esto?

Now, you probably didn't understand that at all either; so I'll go ahead and turn it into code:

public class A
{
    private readonly B b;
    private readonly C c;

    public A(B b, C c)
    {
        this.b = b;
        this.c = c;
    }
}

public class B
{    
}

public class C
{
    private readonly B b;

    public C(B b)
    {
        this.b = b;
    }
}

Without DI, I would resolve it like this:

var b = new B();
var c = new C(b);
var a = new A(b,c);

How can I accomplish something like this through DI, cleanly? What I want is pretty straightforward: use the same instance of B when instancing both C y A.

Forgot to mention I do want this in a per-web-request lifestyle, not singleton or transient.

preguntado el 10 de marzo de 12 a las 01:03

If you provided more context, give the classes more meaningful names, you may get a better answer ... -

I'm using castle, A -> Service, B -> Repository, C -> SupportClass -

What you are showing us is clearly DI. You want to know how to configure this in Castle Windsor? Can you update your question with your current configuration? -

3 Respuestas

Según la documentación del castillo, singleton behavior is already the default. Therefore, castle will create only one instance of B and pass it to both A and C.

It's the cases where you no want this that you should worry about. You need some extra configuration then, as described in the linked documentation.

respondido 10 mar '12, 09:03

I see two options. One, use your container to manage the lifetime of the class:

StructureMap Container, scoping IUnitOfWork a la corriente HttpContext:

For<IUnitOfWork>().HttpContextScoped().Use<UnitOfWork>();

This ensures that all requests for IUnitOfWork, en el mismo HttpContext, have the same instance.

Option two, refactor your code so you won't have this issue...

respondido 10 mar '12, 01:03

Assuming you really want to keep B unexposed in class C, how about this:

class Program
{
  static void Main(string[] args)
  {
     var b = new B();
     var c = new C(b);
     var a = c.GetA();
  }
}

public class A
{
  private readonly B b;
  private readonly C c;

  public abstract class AFactory
  {
     private B b;

     public AFactory(B b)
     {
        this.b = b;
     }

     protected A GetA(C c)
     {
        return new A(b, c);
     }

     abstract public A GetA();
  }

  private A(B b, C c)
  {
     this.b = b;
     this.c = c;
  }
}

public class B
{
}

public class C
{
  private readonly B b;
  private CAFactory afactory;

  private class CAFactory : A.AFactory
  {
     private C c;
     public CAFactory(C c) : base(c.b)
     {
        this.c = c;
     }

     public A GetA()
     {
        return GetA(c);
     }
  }

  public C(B b)
  {
     this.b = b;
     afactory = new CAFactory(this);
  }

  public A GetA()
  {
     return afactory.GetA();
  }
}

respondido 10 mar '12, 03:03

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.