Help with structuremap configuration

2019-09-01 13:26发布

问题:

I am trying to configure Structuremap something like the following but I can seem to get it quite right

ObjectFactory.Initialize(x => {

    x.For<TunaRepository>()
        .Use(new TunaRepository(serviceEndpoint))
        .Named("Tuna");

    x.For<CodRepository>()
        .Use(new CodRepository(serviceEndpoint))
        .Named("Cod");

    x.For<HaddockRepository>()
        .Use(new HaddockRepository(serviceEndpoint))
        .Named("Haddock");

    x.For<IFishRepository>().AddInstances(y =>
                                        {
                                            y.OfConcreteType<TunaRepository>().
                                            // Somehow add all instances here???

                                        });

    x.For<TunaController>().Use<TunaController>()
        .Ctor<IFishRepository>("repo").Is<TunaRepository>(); // This Is should use the instance registered above

    x.For<CodController>().Use<CodController>()
        .Ctor<IFishRepository>("repo").???

    x.For<HaddockController>().Use<HaddockController>()
        .Ctor<IFishRepository>("repo").???

});

At points in my code I want to be able to do:

var instances = ObjectFactory.GetAllInstances<IFishRepository>();

and also:

var instance = ObjectFactory.GetNamedInstance<IFishRepository>("Cod");

and also use IFishRepository as an arguement to my controllers:

public TunaController(IFishRepository repo ...

So my question is whats the best way to configure my ObjectFactory?

回答1:

When registering named instances that should not be the Default instance you use the Add method:

 x.For<IFishRepository>()
   .Add(() => new TunaRepository(serviceEndpoint))
   .Named("Tuna");

Also observe that unless you want the TunaRepository to be a Singleton you should register it using a lambda. The lambda will be evaluated when the instance is requested and will in my example return a new instance. Watch out with the serviceEndpoint as well and make sure if you want that single instance for all repositories. Generally I tend to wire up all my dependencies using For<>().Use<>() in structure map where possible instead of using "new". Doing so makes the architecture much more flexible, especially since you can add new parameters to the ctors without changing the registrations.

For specifying a named instance to be used in a constructor you can use this syntax:

 x.For<TunaController>().Use<TunaController>().
   Ctor<IFishRepository>("repo").
   Is(i => i.TheInstanceNamed("Tuna")); 

Since all your registrations are following the same patterns, I would use an IRegistrationConvention in order to remove duplicate code and minimize the effort of adding new repositories.