具有命名实例的 StructureMap 4 未按预期工作
StructureMap 4 with named instances not working as expected
这是我的解决方案中几个 classes 及其实现的接口的简化版本。它们既共享一个接口,又实现了一个专用接口。
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>();
}
}
最后我有一个 class 它将这些依赖项注入构造函数中,如下所示:
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>();
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
class 时,StructureMap 只是使用自动连接来推送 ISharedContext
.
的默认实例
这是我的解决方案中几个 classes 及其实现的接口的简化版本。它们既共享一个接口,又实现了一个专用接口。
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>();
}
}
最后我有一个 class 它将这些依赖项注入构造函数中,如下所示:
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>();
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
class 时,StructureMap 只是使用自动连接来推送 ISharedContext
.