How to setup named instances using StructureMap profiles?

我怕爱的太早我们不能终老 提交于 2020-01-15 05:51:05

问题


I've done quite a bit of googling and searching here on SO, but couldn't find a similar question or answer.

In typical SM configuration you can add multiple named instances for a single PluginType:

ForRequestedType<IFoo>()
  .AddInstances( x => {
      x.OfConcreteType<FooA>().WithName( "FooA" );
      x.OfConcreteType<FooB>().WithName( "FooB" );
    } );

No problem there. The problem is that I can't do the same when creating a profile. Most examples explaining how to use profiles use the For<>() method of the passed ProfileExpression:

CreateProfile( "Default", p => {
    p.For<IFoo>().UseConcreteType<FooC>();
  } );

I can't seem to find a way to add multiple named instances for the same PluginType as you can do above with regular configuration. The only other method available through ProfileExpression is Type<>(), but I'm not sure if it can be used for this purpose.

Edit: I tried to use Type<>() instead of For<>() and it seems to be taking me in the right direction, but I bumped into another problem. To better explain it here's a better example of what I'm trying to do (this is what I posted to the structuremap-users group, no answer yet):

ObjectFactory.Initialize( x => {
    x.CreateProfile( "Nissan", p =>
    {
        p.Type<ICar>().Is.OfConcreteType<NewNissanCar>().WithName( "New" );
            p.Type<ICar>().Is.OfConcreteType<OldNissanCar>().WithName( "Old" );
    } );

    x.CreateProfile( "Honda", p =>
    {
        p.Type<ICar>().Is.OfConcreteType<NewHondaCar>().WithName( "New" );
        p.Type<ICar>().Is.OfConcreteType<OldHondaCar>().WithName( "Old" );
    } );

} );

ObjectFactory.Profile = "Nissan";

ICar newCar = ObjectFactory.GetNamedInstance<ICar>( "New" ); // -> returns NewHondaCar
ICar car = ObjectFactory.GetInstance<ICar>(); // -> returns OldNissanCar

So even though I set the profile to "Nissan", GetNamedInstance<>("New") returned an instance from the incorrect profile - it should've returned NewNissanCar instead of NewHondaCar.

Interestingly, GetInstance<>() uses the correct profile, but because I can't pass an instance name, it returns an arbitrary concrete type from that profile that implements ICar (I guess it just returns the last concrete type added for that interface).


回答1:


I'm not 100% sure on the syntax, but I believe this is correct:

container = new Container(x => {

    x.ForRequestedType<IFoo>()
        .AddInstances(y =>
        {
            y.OfConcreteType<FooA>().WithName("FooA");
            y.OfConcreteType<FooB>().WithName("FooB");
        });

    x.CreateProfile("Default")
        .For<IFoo>().UseNamedInstance("FooA");

});



回答2:


It doesn't look like StructureMap respects named instances at the profile level. I just tried the car example with SM 2.6.3 and got the same results. You can also see it in the output of ObjectFactory.WhatDoIHave():

ICar (ConsoleApplication1.ICar)                       
Scoped as:  Transient
      "New" Configured Instance of ConsoleApplication1.NewHondaCar, ConsoleApplication1
      "Old" Configured Instance of ConsoleApplication1.OldHondaCar, ConsoleApplication1

It looks like the profiles might be implemented internally by using the name as well, which would explain why it's not supported. When I registered a non-named instance for each profile, I see this in the output:

ICar (ConsoleApplication1.ICar)                       
Scoped as:  Transient
      "Default Instance for Profile Nissan" Configured Instance of ConsoleApplication1.NewNissanCar, ConsoleApplication1
      "Default Instance for Profile Honda" Configured Instance of ConsoleApplication1.NewHondaCar, ConsoleApplication1

Notice how the name of the profile is actually part of the instance key's name. I haven't walked through the code, but this is what appears to be happening.



来源:https://stackoverflow.com/questions/1288192/how-to-setup-named-instances-using-structuremap-profiles

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!