使用泛型的 Unity 配置映射

Unity configuration mapping with generics

我有 Class 和使用泛型的接口。我们使用配置文件来管理与 Microsoft Unity for DI 的映射。

Class:

namespace Acme.Core
{    
  public class CommonCache<T> : ICommonCache<T>
  {
    private string _cacheKey;

    public CommonCache(string cacheKey)
    {
        _cacheKey = cacheKey;
    }

    public IReadOnlyList<T> GetAll(List<T> dataList)
    {
       // Code returns IReadOnlyList<T>
    }
}   

接口:

namespace Acme.Core.Interfaces
{
    public interface ICommonCache<T>
    {
        IReadOnlyList<T> GetAll(List<T> dataList);
    }
}

我希望的是这样的:

 <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <assembly name="Acme.Core" />
    <namespace name="Acme.Core" />
    <namespace name="Acme.Core.Interfaces" />

   <container name="Default">
    <register type="ICommonCache[*]" mapTo="CommonCache[*]">
      <constructor>
       <param name="cacheKey" value="*" />
      </constructor>
    </register>
   </container>
  </unity>

我知道 * 不是正确的语法,但我的目标是允许为类型传递任何类型,为泛型类型传递 mapTo。对于我想为 cacheKey 参数传递值的构造函数,我有 value="*" 来说明传递任何值的目标。

此映射起作用的正确语法是什么?

您可以通过首先注册开放泛型然后(如果您愿意)用封闭泛型覆盖该注册来完成您想要的事情。

首先添加一个默认构造函数以在不存在封闭通用注册时实现您希望的行为...

public CommonCache()
{
    _cacheKey = typeof(T).FullName;
}

开放仿制药注册

<register type="ICommonCache`1" mapTo="CommonCache`1">
  <!-- Use the default constructor -->
  <constructor />
</register>

关闭仿制药注册

<register type="ICommonCache`1[BusinessType]" mapTo="CommonCache`1[BusinessType]">
  <constructor>
    <param name="cacheKey" value="BusinessTypeCacheKeyOverride" />
  </constructor>
</register>

但我建议您改为从构造函数中删除值类型。这可以通过引入一个新的 class 作为依赖项来设置缓存键映射的类型来完成。这又可以从配置中读取。

public interface ICacheKeyMap
{
    string GetCacheKey(Type t);
    void SetCacheKey(Type t, string cacheKey);
}

根据documentation关于

Specifying Types in the Configuration File.

通用类型

泛型类型的 CLR 类型名称语法非常冗长,而且它也不允许使用别名之类的东西。 Unity 配置系统允许对通用类型使用 shorthand 语法,该语法还允许别名和类型搜索。

要指定一个封闭的泛型类型,您需要在方括号中以逗号分隔的列表形式提供类型名称,后跟类型参数。

Unity shorthand 如下例所示。 XML

<container>
    <register type="IDictionary[string,int]" </register>
</container>

如果您希望使用程序集名称限定的类型作为类型参数,而不是别名或自动找到的类型,则必须将整个名称放在方括号中,如下例所示: XML

<register type="IDictionary[string, [MyApp.Interfaces.ILogger, MyApp]]"/>

要指定一个开放的通用类型,您只需省略类型参数。您有两个选择:

  • 使用 `N 的 CLR 表示法,其中 N 是泛型参数的数量。

  • 使用方括号和逗号表示泛型参数的个数。

    通用类型 |使用 CLR 表示法的配置文件 XML |配置文件 XML 使用逗号表示法

    IList => IList`1 => IList[]

    IDictionary => IDictionary`2 => IDictionary[]