【问题标题】:Unity named mapping issueUnity命名映射问题
【发布时间】:2012-11-30 13:58:12
【问题描述】:

我有两种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>

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

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

问题是当 unity 解析 BusinessService 时,它会尝试解析 (none) 命名映射 IEmailService 而不是 LiveTest 并抛出 ResolutionFailedException

container.Resolve&lt;BusinessService&gt;(); 抛出以下异常:

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 周围有一个包装方法,以使用(none) 命名映射以及基于appSetting 值注册IEmailService

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&lt;TFrom, TTo&gt;(string name)TestLive 实现注册为(none) 命名映射,具体取决于appSetting 值。 BusinessService 也无一例外的解决了。

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

container = new UnityContainer();

【问题讨论】:

    标签: c# dependency-injection unity-container


    【解决方案1】:

    在我看来,在配置中进行注册的唯一目的是在代码中没有它们并且能够在不重新编译的情况下替换实现。因此,您正在尝试将其从代码中删除。我不明白的是为什么你首先要在配置中同时注册。只需从配置中删除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);
       });
    

    【讨论】:

    • 是的,这是一种方式。我想保留两个实现的名称,以便通过编辑appSettings 部分而不是container 部分来轻松切换。这样,我将不得不评论一个注册并取消评论其他 - 只是多一点工作。
    • 工作不多。选择ctrl+e then c 进行评论,选择ctrl+e then u 取消评论,只有指针位于评论部分。这是配置文件的预期用途。在两个地方使用相同的配置选项是没有意义的,甚至是有害的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-24
    • 2019-01-22
    • 2011-07-28
    • 2011-08-07
    • 2010-10-10
    相关资源
    最近更新 更多