structuremapproperty-injection

How can StructureMap be used to create setter dependencies of objects that have primitive constructor argumeents?


I have an object "TestProperty" which implements "ITestProperty". "TestProperty" takes a string constructor argument. This is configured in StructureMap using something along the lines CtorDependency or WithCtorArg.

I want to inject the an instance of "ITestProperty" (implemented with "TestProperty") into another class as a property. When I try to run the code I get an exception (StructureMap Error Code 205, "Missing requested Instance property").

Here's a simplified version that recreates the problem:

Test:

[Test]
public void Can_resolve_the_correct_property()
{
    ObjectFactory.Initialize( x => x.AddRegistry( new TestRegistry() ) );

    var instance = ObjectFactory.GetInstance<TestController>();
}

Registry Setup:

public class TestRegistry : Registry
{
    public TestRegistry()
    {
        ForRequestedType<ITestProperty>().AddInstances( 
            i => i.OfConcreteType<TestProperty>().WithName( "Test" )
                .CtorDependency<string>( "arg" ).Is( "abc" )
        );

        //ForConcreteType<TestProperty>().Configure
            .CtorDependency<string>( "arg" ).Is( "abc" );

        ForConcreteType<TestController>().Configure
            .SetterDependency( p => p.Property ).Is<TestProperty>()
            .WithName( "Test" );
    }
}

Test Objects:

public interface ITestProperty { }

public class TestProperty : ITestProperty
{
    private readonly string arg;

    public TestProperty( string arg )
    {
        this.arg = arg;
    }

    public string Arg { get { return arg; } }
}

public class TestController
{
    public ITestProperty Property { get; set; }
}

When we go to initialize the "TestController" object above the exception is thrown. Is it possible to do this with StructureMap? Assuming that it is possible, what do I need to do to get it working?

Thanks in advance.


Solution

  • There are several ways to do this, as Josh mentioned if the named instance is important then you want this in your registry:

    ForRequestedType<ITestProperty>().AddInstances(i => 
        i.OfConcreteType<TestProperty>().WithName("Test")
            .WithCtorArg("arg").EqualTo("abc"));
    
    ForConcreteType<TestController>().Configure
        .SetterDependency(p => p.Property).Is(c => c
            .GetInstance<ITestProperty>("Test"));
    

    Otherwise, you can do this:

    ForRequestedType<ITestProperty>().TheDefault.Is
        .OfConcreteType<TestProperty>()
        .WithCtorArg("arg").EqualTo("abc");
    
    ForConcreteType<TestController>().Configure
        .SetterDependency(p => p.Property).IsTheDefault();
    

    Also, this is old StructureMap syntax, you might want to update to the latest version. Here is the new syntax:

    For<ITestProperty>().Add<TestProperty>().Named("Test")
        .Ctor<string>("arg").Is("abc");
    
    ForConcreteType<TestController>().Configure
        .Setter(p => p.Property).Is(c => c
            .GetInstance<ITestProperty>("Test"));