Search code examples
c#structuremap

StructureMap - How to make different instances of an interface (by different constructor values) for use in constructor of different classes


I have this class and interfaces:

Public interface IBook{
}

public class Book:IBook
{
    public Book(int num){
        //...
    }
}

//------------------------------------------------------

Public interface IBox{
}

Public interface IBoxA:IBox{
}

Public interface IBoxB:IBox{
}

Public interface IBoxC:IBox{
}

//------------------------------------------------------

public class Box1:IBoxA
{
    public Box1(IBook myBook, ..........){
        //...
    }
}

public class Box2:IBoxB
{
    public Box2(IBook myBook, ..........){
        //...
    }
}

public class Box3:IBoxC
{
    public Box3(IBook myBook, ..........){
        //...
    }
}

I want pass the Book object to constructor of Box1, Box2 & Box3 by StructureMap IOC but each one should has different value in their constructor.

Really I want a mechanism to determin witch Book objects (witch witch parameter value) should be passed to the witch Box class. It is a condition for instancing Box classes.

For a better explanation please see the following image:

enter image description here

I write the following config:

For<IBoxA>()
   .HybridHttpOrThreadLocalScoped()
   .Use<Box1>();

For<IBoxB>()
   .HybridHttpOrThreadLocalScoped()
   .Use<Box2>();

For<IBoxC>()
   .HybridHttpOrThreadLocalScoped()
   .Use<Box3>();

ForConcreteType<Box1>()
        .Configure
        .Ctor<IBook>("myBook")
        .Is(new Book(1));

ForConcreteType<Box2>()
        .Configure
        .Ctor<IBook>("myBook")
        .Is(new Book(2));

ForConcreteType<Box3>()
        .Configure
        .Ctor<IBook>("myBook")
        .Is(new Book(3));

But really Box1, Box2 and Box3 has many parameter in their constructors and one of them is IBook myBook. I don't know how can I set a config to just set myBook parameter in the constructor of Box1, Box2 and Box3 with appropriate object.


Edit1:

My real project is different and I tried to simplify my question by reduce names and relations of it, then it is possible that I have some mistakes in the real project but I get an error like it:

No default Instance is registered and cannot be automatically determined for type 'IBook' There is no configuration specified for 'IBook'. Should I define another config for IBook in the above scenario?

My code has not another config for IBook »» Book because Book has a constructor with parameter and value of its parameter is depended on where (in witch Box) it is.


Solution

  • I'm not sure what goes wrong where in your real example, but in general all you need is:

    c.For<IBoxA>()                    
        .Use<Box1>()
        .Ctor<IBook>().Is(new Book(1));
    
    c.For<IBoxB>()                    
        .Use<Box2>()
        .Ctor<IBook>().Is(new Book(2));
    
    c.For<IBoxC>()                    
        .Use<Box3>()
        .Ctor<IBook>().Is(new Book(3));
    

    And resolve using interface (so IBoxB and not Box2):

    var box = container.GetInstance<IBoxB>();