gpt4 book ai didi

c# - 为同一接口(interface)的多个实现设置属性

转载 作者:行者123 更新时间:2023-11-30 12:38:38 26 4
gpt4 key购买 nike

我正在尝试注册同一接口(interface)的多个实现...然后...使用 Setter 在我的 Application 实例上设置属性。我已经尝试了多个在线示例,并且总是将相同的实例插入到 2 个应用程序属性中。

  • 注意:我试过很多网上的例子,下面是最新的版本

例如……
当我在 Quick Watch 中查看应用程序对象时,我得到以下信息

enter image description here

我的配置:
显然,我已经解析出所有其他对象...

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 的:

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; }

}

----------------------------------------
更新:来自向我提出的问题
为了将事情降低到极其基本的水平......我决定实现一组最小的 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>();
}

总是会发生两种结果之一

  1. 属性为NULL
  2. 我收到以下错误消息

"No default Instance is registered and cannot be automatically determined for type 'IInstanceProvider' No default instance is specified."

问:目标实现位于何处?

XXX.MeasurementContracts.Business
包含“ContainerRegistry”和所有类、接口(interface)等。

XXX.MeasurementContracts.Web
包含“StructuremapMvcConfig”、“IoC”初始化器和它自己的“DefaultRegistry”

MeasurementContracts.UnitTests
在其“IoC”初始值设定项中添加业务“ContainerRegistry”...然后添加其自己的“ContainerRegistry”。

尝试:尝试命名注册我将以下内容添加到“ContainerRegistry”,同时,两者都被填充了......它们的类型为“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 => x.Foo).Is(c => c.GetInstance("Foo"));"

分析:使用 container.WhatDoIHave()好的,使用“WhatDoIHave”显示我已正确配置“ITesting”实例。

  • transient - XXX.MeasurementContracts.Business.Providers.Bar('bar') - bar(默认)
  • transient - XXX.MeasurementContracts.Business.Providers.Foo('foo') - foo

如何将“Foo”和“Bar”分解为各自的属性?

最佳答案

删除 DistributionListProviderFirstDeliveryNoticeDocumentRecallProvider 属性的显式 setter 属性。

Explicit Setter Injection with [SetterProperty] Attributes

Without the [SetterProperty] attributes decorating the setters, StructureMap would ignore the DistributionListProvider and FirstDeliveryNoticeDocumentRecallProvider properties when it builds up a MeasurementContractsApplication object. With the attributes, StructureMap will try to build and attach values for the two properties as part of object construction.

public class MeasurementContractsApplication : IMeasurementContractsApplication {
[SetterProperty]
public IMeasurementContractsUnitOfWork UnitOfWork { get; set; }


public IInstanceProvider DistributionListProvider { get; set; }


public IInstanceProvider FirstDeliveryNoticeDocumentRecallProvider { get; set; }
}

并且由于它无法区分哪个接口(interface)用于哪个属性,因此它将第一个注册的接口(interface)应用于两个属性。

这就是为什么在这种情况下,您应该直接应用内联 setter

Inline Setter Configuration

Any setter property not configured with [SetterProperty] or the setter policies in the next section can still be filled by StructureMap if an inline dependency is configured matching that setter property as shown in the example below:

For<IMeasurementContractsApplication>()
.Use<MeasurementContractsApplication>()
// Component
.Setter(x => x.DistributionListProvider)
.Is<DistributionListProvider>()
.Setter(x => x.FirstDeliveryNoticeDocumentRecallManager)
.Is<FirstDeliveryNoticeDocumentAdminUpdateProvider>();

以下最小完整且可验证的示例演示了上述内容并在测试时通过。

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;
}
}
}

Quick watch

关于c# - 为同一接口(interface)的多个实现设置属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50802502/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com