我正在尝试注册同一个接口的多个实现......然后......使用Setter在我的Application实例上设置属性。我已经尝试了多个在线示例,并始终将SAME实例插入到2个应用程序属性中。
例如......
当我在Quick Watch中查看应用程序对象时,我得到以下内容
MY CONFIGURATION:
显然,我已经解析了所有其他对象......
public ContainerRegistry()
{
Scan(
scan =>
{
scan.TheCallingAssembly();
scan.WithDefaultConventions();
scan.LookForRegistries();
scan.AssembliesFromApplicationBaseDirectory(f => f.FullName.StartsWith("Demo.Common", true, null));
scan.AssembliesFromApplicationBaseDirectory(f => f.FullName.StartsWith("XXX.XXX.MeasurementContracts", true, null));
scan.AddAllTypesOf(typeof(IMeasurementContractsApplication));
scan.AddAllTypesOf(typeof(IInstanceProvider));
scan.SingleImplementationsOfInterface();
});
// --------
// NAMED INSTANCES - IInstanceProvider
For<IInstanceProvider>().Use<DistributionListProvider>();
For<IInstanceProvider>().Add<FirstDeliveryNoticeDocumentRecallManager>().Named("firstDeliveryNoticeDocumentRecallManager");
// --------
// APPLICATION
For<IMeasurementContractsApplication>().Use<MeasurementContractsApplication>()
// Component
.Setter(x => x.DistributionListProvider).Is<DistributionListProvider>()
.Setter(x => x.FirstDeliveryNoticeDocumentRecallManager).IsNamedInstance("firstDeliveryNoticeDocumentRecallManager");
}
应用示例:
显然,我已经解析了所有其他对象......
public class MeasurementContractsApplication : IMeasurementContractsApplication
{
[SetterProperty]
public IMeasurementContractsUnitOfWork UnitOfWork { get; set; }
[SetterProperty]
public IInstanceProvider DistributionListProvider { get; set; }
[SetterProperty]
public IInstanceProvider FirstDeliveryNoticeDocumentRecallProvider { get; set; }
}
IInstanceProvider's:
public class DistributionListProvider : ProviderBase, IInstanceProvider
{
// Purposely left-out Properties, Methods etc.
}
public class FirstDeliveryNoticeDocumentAdminUpdateProvider : ProviderBase, IInstanceProvider
{
// Purposely left-out Properties, Methods etc.
}
public class ProviderBase
{
[SetterProperty]
public IMeasurementContractsUnitOfWork UnitOfWork { get; set; }
}
----------------------------------------
更新:从提出的问题
为了把事情降到极端......我决定实现MINIMAL的2个类来尝试建议:
public interface ITesting
{
string Name();
}
public class Foo : ITesting
{
public string Name()
{
return string.Empty;
}
}
public class Bar : ITesting
{
public string Name()
{
return string.Empty;
}
}
public ContainerRegistry()
{
Scan(
scan =>
{
scan.TheCallingAssembly();
scan.WithDefaultConventions();
scan.LookForRegistries();
scan.AssembliesFromApplicationBaseDirectory(f => f.FullName.StartsWith("Demo.Common", true, null));
scan.AssembliesFromApplicationBaseDirectory(f => f.FullName.StartsWith("XXX.MeasurementContracts", true, null));
scan.AddAllTypesOf(typeof(IMeasurementContractsApplication));
scan.AddAllTypesOf(typeof(IManager<>));
scan.AddAllTypesOf(typeof(IDocumentDependency));
scan.AddAllTypesOf(typeof(IDataItemProviderFor<>));
scan.AddAllTypesOf(typeof(IDatasetBuilderFor<>));
scan.AddAllTypesOf(typeof(IXmlTransformerFor<>));
scan.AddAllTypesOf(typeof(IWorkflowProvider));
scan.AddAllTypesOf(typeof(IInstanceProvider));
scan.AddAllTypesOf(typeof(IPdfConverterClient));
scan.AddAllTypesOf(typeof(IReportFor<>));
scan.AddAllTypesOf(typeof(IAdminUpdateCommandFor<>));
scan.AddAllTypesOf(typeof(ITesting));
scan.SingleImplementationsOfInterface();
});
Component Providers
For<IMeasurementContractsApplication>().Use<MeasurementContractsApplication>()
Setter(x => x.Bar).Is<Bar>()
Setter(x => x.Foo).Is<Foo>();
}
总是会发生两种结果之一
“未注册默认实例,无法自动生成 确定类型'IInstanceProvider'没有默认实例 指定“。
问:目标实施位于何处?
XXX.MeasurementContracts.Business
包含“ContainerRegistry”以及所有类,接口等。
XXX.MeasurementContracts.Web
包含“StructuremapMvcConfig”,“IoC”初始化程序及其“自己的”DefaultRegistry“
MeasurementContracts.UnitTests
在其“IoC”初始化程序中添加Business“ContainerRegistry”...然后添加自己的“ContainerRegistry”。
尝试:尝试命名注册 我将以下内容添加到“ContainerRegistry”中,同时,BOTH已填充...它们的类型为“Bar”
// Component Providers
For<ITesting>().Use<Bar>().Named("Bar");
For<ITesting>().Add<Foo>().Named("Foo");
// Component Providers
For<IMeasurementContractsApplication>().Use<MeasurementContractsApplication>()
.Setter(x => x.Bar).Is<Bar>()
.Setter(x => x.Foo).Is<Foo>();
我如何解决“Foo”? 我也试过“.Setter(x =&gt; x.Foo).Is(c =&gt; c.GetInstance(”Foo“));”
分析:使用container.WhatDoIHave() 好的,使用“WhatDoIHave”显示我已正确配置“ITesting”实例。
我如何解决“Foo”&amp; “吧”进入他们各自的属性?
答案 0 :(得分:1)
删除DistributionListProvider
和FirstDeliveryNoticeDocumentRecallProvider
属性的显式setter属性。
Explicit Setter Injection with [SetterProperty] Attributes
如果没有
[SetterProperty]
属性来装饰setter,StructureMap会在构建DistributionListProvider
对象时忽略FirstDeliveryNoticeDocumentRecallProvider
和MeasurementContractsApplication
属性。使用这些属性,StructureMap将尝试构建和附加两个属性的值,作为对象构造的一部分。
public class MeasurementContractsApplication : IMeasurementContractsApplication {
[SetterProperty]
public IMeasurementContractsUnitOfWork UnitOfWork { get; set; }
public IInstanceProvider DistributionListProvider { get; set; }
public IInstanceProvider FirstDeliveryNoticeDocumentRecallProvider { get; set; }
}
由于它无法区分哪个接口用于哪个属性,因此它将第一个注册接口应用于两个属性。
这就是为什么,在这种情况下,您应该只应用内置的setter
Inline Setter Configuration
如果内联依赖项配置为匹配该setter属性,则任何未使用
[SetterProperty]
配置的setter属性或下一节中的setter策略仍可由StructureMap填充,如下例所示:
For<IMeasurementContractsApplication>()
.Use<MeasurementContractsApplication>()
// Component
.Setter(x => x.DistributionListProvider)
.Is<DistributionListProvider>()
.Setter(x => x.FirstDeliveryNoticeDocumentRecallManager)
.Is<FirstDeliveryNoticeDocumentAdminUpdateProvider>();
以下Minimal Complete和Verifiable示例演示了上述内容并在测试时通过。
namespace StructureMap.Unit_Tests.Misc {
[TestClass]
public class StructureMapTests {
[TestMethod]
public void _Inline_Setter_Should_Populate_Multiple_Implementations() {
//Arrange
var registry = new StructureMap.Registry();
registry.IncludeRegistry<ContainerRegistry>();
// build a container
var container = new StructureMap.Container(registry);
//Act
var application = container.GetInstance<IMeasurementContractsApplication>();
//Assert
application.Should().NotBeNull();
application.Foo.Should().BeOfType<Foo>();
application.Bar.Should().BeOfType<Bar>();
}
}
class ContainerRegistry : StructureMap.Registry {
public ContainerRegistry() {
Scan(
scan => {
scan.TheCallingAssembly();
scan.WithDefaultConventions();
scan.LookForRegistries();
scan.AssembliesFromApplicationBaseDirectory(f => f.FullName.StartsWith("Demo.Common", true, null));
scan.AssembliesFromApplicationBaseDirectory(f => f.FullName.StartsWith("XXX.MeasurementContracts", true, null));
scan.AddAllTypesOf(typeof(IMeasurementContractsApplication));
scan.AddAllTypesOf(typeof(ITesting));
scan.SingleImplementationsOfInterface();
});
//Component Providers
For<IMeasurementContractsApplication>()
.Use<MeasurementContractsApplication>()
.Setter(x => x.Bar)
.Is<Bar>()
.Setter(x => x.Foo)
.Is<Foo>();
}
}
public interface IMeasurementContractsApplication {
ITesting Foo { get; set; }
ITesting Bar { get; set; }
}
public class MeasurementContractsApplication : IMeasurementContractsApplication {
public ITesting Foo { get; set; }
public ITesting Bar { get; set; }
}
public interface ITesting {
string Name();
}
public class Foo : ITesting {
public string Name() {
return string.Empty;
}
}
public class Bar : ITesting {
public string Name() {
return string.Empty;
}
}
}