简体   繁体   English

具有泛型的Unity配置映射

[英]Unity configuration mapping with generics

I have Class and Interface that use generics. 我有使用泛型的类和接口。 We use configuration files to manage mappings with Microsoft Unity for DI. 我们使用配置文件来管理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>
    }
}   

Interface: 接口:

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

What I was hoping for was something like this: 我希望的是这样的:

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

I know * is not proper syntax but my goal is to allow any type to be passed for the type and mapTo for the generic type. 我知道*是不正确的语法,但是我的目标是允许为类型传递任何类型,对于通用类型传递mapTo。 For the constructor I'd like to pass the value for the cacheKey parameter, I have value="*" to illustrate the goal of passing any value. 对于构造函数,我想传递cacheKey参数的值,我使用value =“ *”来说明传递任何值的目标。

What is the correct syntax for this mapping to work? 该映射起作用的正确语法是什么?

You can accomplish something like what you are after by first registering the open generic type and then (if you wish) override that registration with closed generics. 您可以先注册开放的泛型类型,然后(如果您愿意)用封闭的泛型覆盖该注册,从而完成类似的工作。

First add a default constructor to implement the behavior you wish when no closed generic registration is present... 首先添加默认构造函数,以在不存在封闭通用注册的情况下实现您希望的行为。

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

Open Generics Registration 开放通用注册

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

Close Generics Registration(s) 关闭仿制药注册

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

But I would recommend you instead remove value types from your constructor. 但我建议您改为从构造函数中删除值类型。 This could be done by introducing a new class as a dependency to set up the type to cache key map. 这可以通过引入新类作为依赖关系来设置类型以缓存键映射来完成。 That could in turn read from config. 依次可以从config中读取。

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

According to documentation about 根据有关文件

Specifying Types in the Configuration File. 在配置文件中指定类型。

Generic Types 通用类型

The CLR type name syntax for generic types is extremely verbose, and it also does not allow for things like aliases. 泛型类型的CLR类型名称语法非常冗长,并且也不允许使用别名之类的东西。 The Unity configuration system allows for a shorthand syntax for generic types that also allows for aliases and type searching. Unity配置系统允许通用类型的简写语法,还允许别名和类型搜索。

To specify a closed generic type, you provide the type name followed by the type parameters in a comma-separated list in square brackets. 要指定封闭的通用类型,请在方括号中以逗号分隔的列表中提供类型名称,后跟类型参数。

The Unity shorthand would look like the following example. Unity的简写将类似于以下示例。 XML XML格式

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

If you wish to use an assembly name-qualified type as a type parameter, rather than an alias or an automatically found type, you must place that entire name in square brackets, as shown in the following example: XML 如果希望使用程序集名称限定的类型作为类型参数,而不是别名或自动找到的类型,则必须将该全名放在方括号中,如以下示例所示:XML

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

To specify an open generic type you simply leave out the type parameters. 要指定一个开放的泛型类型,您只需忽略类型参数。 You have two options: 您有两种选择:

  • Use the CLR notation of `N where N is the number of generic parameters. 使用N的CLR表示法,其中N是通用参数的数量。

  • Use the square brackets, with commas, to indicate the number of generic parameters. 使用方括号(带逗号)指示通用参数的数量。

    Generic Type | 通用类型| Configuration file XML using CLR notation | 使用CLR表示法的配置文件XML Configuration file XML using comma notation 使用逗号表示法的配置文件XML

    IList => IList`1 => IList[] IList => IList`1 => IList []

    IDictionary => IDictionary`2 => IDictionary[,] IDictionary => IDictionary`2 => IDictionary [,]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM