以下是我的解决方案中的几个类的简化版本以及它们实现的接口。它们共享一个接口并实现专用接口。
public interface ISharedContract
{
void ImplementSharedContract();
}
public interface IConcreteOne
{
void ImplementConcreteOne();
}
public interface IConcreteTwo
{
void ImplementConcreteTwo();
}
public class ConcreteOne : BaseConcrete, IConcreteOne, ISharedContract
{
public void ImplementSharedContract()
{
this.ImplementConcreteOne();
}
public void ImplementConcreteOne()
{
}
}
public class ConcreteTwo : BaseConcrete, IConcreteTwo, ISharedContract
{
public void ImplementSharedContract()
{
this.ImplementConcreteTwo();
}
public void ImplementConcreteTwo()
{
}
}
我的StructureMap注册表按如下方式注册这些依赖项:
public class MyRegistry : Registry
{
public MyRegistry()
{
this.For<ISharedContract>().Use<ConcreteOne>().Named("cOne");
this.For<ISharedContract>().Use<ConcreteTwo>().Named("cTwo");
this.For<IConcreteOne>().Use<ConcreteOne>();
this.For<IConcreteTwo>().Use<ConcreteTwo>();
}
}
最后,我有一个类在构造函数中注入这些依赖项,如下所示:
public MyDependent(ISomethingElse somethingElse, ISharedContract cOne, ISharedContract cTwo)
{
this.collection = new List<ISharedContract>()
{
cOne,
cTwo
};
}
在运行时我发现cOne和cTwo都是ConcreteTwo
的注入实例。如果我在StructureMap注册表中交换两个命名注册的顺序,则cOne和cTwo都是ConcreteOne
的实例。
这不是我第一次使用命名实例,但我之前没有注意到这一点。有什么我想念的吗?我已检查并仔细检查传递给Named方法的值是否与构造函数中的参数名称相对应。
更新
这是更新的注册表项,这是使我的示例案例工作所必需的。感谢@ jeremy-d-miller我需要的信息:
this.For<IMyDependent>().Use<MyDependent>()
.Ctor<ISharedContract>("cOne").Is<ConcreteOne>()
.Ctor<ISharedContract>("cTwo").Is<ConcreteTwo>();
答案 0 :(得分:2)
StructureMap没有任何魔术功能,它将构造函数参数名称与该类型的命名实例相匹配。在这种情况下,您必须显式映射内联依赖项:http://structuremap.github.io/registration/inline-dependencies/
在此代码中:
this.For<ISharedContract>().Use<ConcreteOne>().Named("cOne");
this.For<ISharedContract>().Use<ConcreteTwo>().Named("cTwo");
您将默认ISharedContext
设置为ConcreteOne
,然后立即将其覆盖为ConcreteTwo
。在这种情况下,最后一个获胜。在构建MyDependent
类时,StructureMap只是使用自动布线来推送ISharedContext
的默认实例。