【问题标题】:Unity configuration mapping with generics使用泛型的 Unity 配置映射
【发布时间】:2016-04-11 16:28:31
【问题描述】:

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

类:

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="*" 来说明传递任何值的目标。

这个映射的正确语法是什么?

【问题讨论】:

    标签: c# .net unity-container


    【解决方案1】:

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

    首先添加一个默认构造函数来实现在没有关闭的泛型注册存在时所希望的行为...

    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>
    

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

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

    【讨论】:

    • 我收到此错误:无法解析类型名称或别名CommonCache1。请检查您的配置文件并验证此类型名称。 ExceptionType: System.InvalidOperationException` 注册:
    • 仔细检查您是否在 节点中包含了 CommonCache 的正确命名空间和程序集名称。
    • 很好,我错过了一个命名空间
    • 收到以下错误(第 1 部分):依赖项解析失败,类型 = \"Acme.Core.Interfaces.ICommonCache`1[Acme.Core.Interfaces.Domains.IApplicationSetting]\", name = \"(none)\"。\r\n出现异常 while: while resolve。
    • 内部异常?
    【解决方案2】:

    documentation

    Specifying Types in the Configuration File.

    泛型类型

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

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

    Unity 速记类似于以下示例。 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[,]

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      • 2018-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多