Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How Do I Bind Different Concretes to a Property Using StructureMap

They use StructureMap for IoC where I am currently working.

I have an application class that will implement multiple properties of the same interface...and I need to bind DIFFERENT IMPLEMENTATIONS

...and no, I cannot do this: IProvider<T>

FOR INSTANCE:

    public class MyApplication
    {
        [SetterProperty]
        public IProvider OneProvider { get; set; }

        [SetterProperty]
        public IProvider TwoProvider { get; set; }
    }

    public class FooProvider: IProvider {
        // I would like to force this one to bind-on OneProvider ...
    }
    public class BarProvider: IProvider {
        // I would like to force this one to bind-on TwoProvider ...
    }

In Unity, there are many ways to do this, for instance;

[Dependency("FooProvider")]
public IProvider OneProvider { get; set; }

[Dependency("BarProvider")]
public IProvider TwoProvider { get; set; }

...however, StructureMaps SetterProperty attribute doesnt allow for this.

QUESTION:
How do I bind different implementations into an instance-property?

SAMPLE REGISTRY:
Here is an example of what my registry might look like...

public ContainerRegistry()
{
    Scan(
        scan =>
        {
            scan.TheCallingAssembly();
            scan.WithDefaultConventions();
            scan.LookForRegistries();
            scan.AssembliesFromApplicationBaseDirectory(f => f.FullName.StartsWith("My.Awesome.Company", true, null));
            scan.AddAllTypesOf(typeof(IApplication));
            scan.AddAllTypesOf(typeof(IManager<>));
            scan.AddAllTypesOf(typeof(IProvider));
            scan.AddAllTypesOf(typeof(IUnitOfWorkFactory<>));
            scan.SingleImplementationsOfInterface();
        });

    For(typeof(IApplication)).Use(typeof(MyApplication));
} 
like image 527
Prisoner ZERO Avatar asked Oct 18 '22 07:10

Prisoner ZERO


1 Answers

Update

According to documentation, you can use Inline Setter Configuration

the setter policies in the next section can still be filled by StructureMap if an inline dependency is configured matching that setter property as shown in the example below:

public class MyApplication : IApplication {
    public IProvider OneProvider { get; set; }
    public IProvider TwoProvider { get; set; }
}


public class RuleWithSettersRegistry : Registry {
    public RuleWithSettersRegistry() {

        //...other code removed for brevity

        For<IApplication>().Use<MyApplication>()
            // I would like to force FooProvider to bind-on OneProvider        
            .Setter(x => x.OneProvider).Is<FooProvider>()
            // I would like to force BarProvider to bind-on TwoProvider
            .Setter(x => x.TwoProvider).Is<BarProvider>();            
    }
}

Original Answer

If you are able to modify the implementations and the target class then try to differentiate the intended dependencies.

public interface IFooProvider : IProvider { }

public interface IFooProvider : IProvider { }

Have the implementations

public class MyApplication {
    [SetterProperty]
    public IFooProvider OneProvider { get; set; }

    [SetterProperty]
    public IBarProvider TwoProvider { get; set; }
}

public class FooProvider: IFooProvider { }

public class BarProvider: IBarProvider { }

That way when registering all IProvider derived implementations with

scan.AddAllTypesOf(typeof(IProvider));

it will grab the intended implementations and bind them.

like image 183
Nkosi Avatar answered Oct 21 '22 00:10

Nkosi