gpt4 book ai didi

c# - 统一命名映射问题

转载 作者:行者123 更新时间:2023-11-30 15:01:58 25 4
gpt4 key购买 nike

我有两个 IEmailService 的实现,一个用于测试,一个用于实时 (is-A)。我有一个 BusinessService有-A IEmailService引用。

BusinessService
IEmailService (has-A)

IEmailService
TestEmailService (is-A)
LiveEmailService (is-A)

在统一配置中,我注册了两个 IEmailService实现如下。

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<container>
<register type="DataAccess.IEmailService, DataAccess"
mapTo="DataAccess.LiveEmailService, DataAccess"
name="Live">
<lifetime type="singleton" />
</register>
<register type="DataAccess.IEmailService, DataAccess"
mapTo="DataAccess.TestEmailService, DataAccess"
name="Test">
<lifetime type="singleton" />
</register>
<container>
</unity>

基于appSetting对于 IEmailService我希望 Unity 选择正确的实现。这将有助于测试。

<appSettings>
<add key="IEmailService" value="Test"/>
</appSettings>

问题是统一何时解决BusinessService , 它试图解决 (none) IEmailService 的命名映射而不是 LiveTest并抛出 ResolutionFailedException .

container.Resolve<BusinessService>();抛出以下异常:

BusinessServices.Test.BusinessServiceTest_Integration.Test103:

Microsoft.Practices.Unity.ResolutionFailedException : Resolution of the dependency failed, type = "BusinessServices.BusinessService", name = "(none)".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The current type, DataAccess.IEmailService, is an interface and cannot be constructed. Are you missing a type mapping?
-----------------------------------------------
At the time of the exception, the container was:

Resolving BusinessServices.BusinessService,(none)
Resolving parameter "emailService" of constructor BusinessServices.BusinessService(DataAccess.IEmailService emailService)
Resolving DataAccess.IEmailService,(none)

----> System.InvalidOperationException : The current type, DataAccess.IEmailService, is an interface and cannot be constructed. Are you missing a type mapping?

我想出的解决方法是在代码中也指定注册,并在 container.RegisterType 周围有一个包装器方法注册IEmailService(none)命名映射也基于 appSetting值(value)。

IUnityContainer container;

// registering unity
static void Load()
{
container = new UnityContainer().LoadConfiguration();

RegisterType<IEmailService, TestEmailService>("Test");
RegisterType<IEmailService, LiveEmailService>("Live");
}

// register the `Test` or `Live` implementation with `(none)` named mapping as per appSetting
static void RegisterType<TFrom, TTo>(string name)
where TTo : TFrom
{
var tFromAppSetting= ConfigurationManager.AppSettings[typeof(TFrom).Name];
if (!string.IsNullOrEmpty(tFromAppSetting) && tFromAppSetting == name)
container.RegisterType<TFrom, TTo>();
}

这行得通,但我最终在两个地方指定了注册 - 配置和代码。有更好的方法吗?

更新

实际上我已经通过代码把它弄对了。我根本不需要统一配置。 RegisterType<TFrom, TTo>(string name)注册或者 TestLive实现为 (none) 命名映射取决于 appSetting值(value)。 BusinessService也无一异常(exception)地解决了。

由于没有统一配置,我没有加载配置。

container = new UnityContainer();

最佳答案

在我看来,在配置中进行注册的唯一目的是不要在代码中进行注册,并且能够在不重新编译的情况下替换实现。所以你写的是试图从代码中删除它。我不明白的是为什么你首先要在配置中同时注册。只需从测试配置中删除 Live 并从应用程序配置中删除 Test 并在没有名称的情况下注册它们。

例如在应用程序 app.config 中:

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<container>
<register type="DataAccess.IEmailService, DataAccess"
mapTo="DataAccess.LiveEmailService, DataAccess">
<lifetime type="singleton" />
</register>

既然你真的不敢按照自己的方式去做:

另一种方法是在代码中仅注册一种确定哪个实例是默认实例的方法:

 container.RegisterType<IEmailService>(new InjectionFactory((c)=>
{
var name = GetImplementationsNameFromAppSettings();
return c.Resolve<IEmailService>(name);
});

关于c# - 统一命名映射问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13275826/

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