views:

25

answers:

1

Hi, I have a problem.... Lest say I have a class like this one:

public class A: InterfaceA
{
    private FileInfo _fileInfo = null;
    public A(FileInfo fileInfo)
    {
        this._fileInfo = fileInfo;
    }

    ...
}

and another one:

public class B: InterfaceB
{
    private A _classA = null;
    public B(A classA)
    {
        this._classA = classA;
    }

    public void Do()
    {
        FileInfo fi = new FileInfo(...);
        _classA.DoSomething();
    }
}

Now, I have setup StructureMap registers like this:

For<InterfaceA>().Use<A>();
For<InterfaceB>().Use<B>();

and when I execute B.Do() structuremap will throw an error because there is no registry entry for FileInfo parameter. The parameter of class A (FileInfo) is constructed in class B; I know that I can do: ObjectFactor.GetInstance() and pass parameters, but I want Dependency injection not service provider. And I want that when I do ObjectFactory.GetInstance(), to construct entire object graph.

How to do this?

+1  A: 

You can use the Ctor instruction to tell SM what objects to use for the Ctor parameters.

var myFile = new FileInfo(...);
For<InterfaceA>.Use<A>().Ctor<FileInfo>().Is(myFile);

Read more about Ctor arguments here.

Edit: In case the file name is not known until the execution of the Do method in B, you have to postpone the creation of the A-object until the do method is executed. In order to do so you can use a factory, either hand coded or a Func/Lazy.

For a Func approach you can change your B to take a Func of A as ctor dependency:

public class B : InterfaceB
{
  private readonly Func<string, InterfaceA> _aBuilder;
  public B(Func<string, InterfaceA> aBuilder)
  {
    _aBuilder = aBuilder;
  }

  public void Do()
  {
    InterfaceA anA = _aBuilder("fileName");
    anA.DoSomething();
  }
}

Boot strap it using:

ObjectFactory.Initialize(
  c=>
  {
    c.For<InterfaceA>().Use<A>();
    c.For<Func<string, InterfaceA>>().Use(d => 
      new Func<string, InterfaceA>( s => 
        ObjectFactory.With(new FileInfo(s)).GetInstance<InterfaceA>()));
    c.For<InterfaceB>().Use<B>();
  }
);
PHeiberg
Yes, but where to put:For<InterfaceA>.Use<A>().Ctor<FileInfo>().Is(myFile);I cant put it into my registers because the FileInfo is not known on the instantiation?
Luka
In case the file name is not known until the execution of the Do method, you either have to go for a factory approach or consider passing the file to the method.
PHeiberg
Edited my answer to include a factory approach.
PHeiberg
Thanks, I'll go for the factory :-D
Luka