使用unity xml配置注册一个嵌套泛型的接口

本文关键字:一个 嵌套 泛型 接口 xml unity 配置 注册 使用 | 更新日期: 2023-09-27 18:04:35

如果我有一个实现通用接口的类,使用unity xml配置可以很好地配置它。

public interface IReader<T> { }
public class Fund { }
public class FundReader : IReader<Fund> { }

和unity xml:

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
  <namespace name="System.ComponentModel" />
  <namespace name="TestUnityIssue" />
  <assembly name="TestUnityIssue" />
  <container>
    <register type="IReader[Fund]" mapTo="FundReader" />
  </container>
</unity>

只需使用下面的代码:

var container = new UnityContainer().LoadConfiguration();
var fundReader = container.Resolve<IReader<Fund>>();
然而,在某些情况下,在阅读器中使用的类型周围有一个包装器。例如,添加以下两个类:
public class Wrapper<T> { }
public class WrappedFundReader : IReader<Wrapper<Fund>> { }

如果我在unity配置中添加以下内容:

<register type="IReader[Wrapper[Fund]]" mapTo="WrappedFundReader" />

,然后尝试使用:

var wrappedReader = container.Resolve<IReader<Wrapper<Fund>>>();

我得到以下异常:

InvalidOperationException - The current type,
TestUnityIssue.IReader`1[TestUnityIssue.Wrapper`1[TestUnityIssue.Fund]],
is an interface and cannot be constructed. Are you missing a type
mapping?

我可以通过使用代码而不是xml来配置它来解决这个问题:

container.RegisterType<IReader<Wrapper<Fund>>, WrappedFundReader>();

或者我可以创建一个介于两者之间的接口,并使用

public interface IWrappedReader<T> : IReader<Wrapper<T>> { }
public class WrappedFundReader : IWrappedReader<Fund>

,配置将更改为:

<register type="IWrappedReader[Fund]" mapTo="WrappedFundReader" />

它仍然会给我一个实例,我可以转换到IReader<Wrapper<Fund>>,但似乎我应该能够使这个工作与统一配置。

我错过了什么使这个工作?

(如果也尝试创建特定的别名,也无法使其工作)

使用unity xml配置注册一个嵌套泛型的接口

Aliasing for me…

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <alias alias="WrappedFund" type="TestUnityIssue.Wrapper`1[[TestUnityIssue.Fund, TestUnityIssue, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], TestUnityIssue, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
    <namespace name="TestUnityIssue" />
    <assembly name="TestUnityIssue" />
    <container>
        <register type="IReader[Fund]" mapTo="FundReader" />
        <register type="IReader[WrappedFund]" mapTo="WrappedFundReader" />
    </container>
</unity>

这些都解决了…

var fundReader = container.Resolve<IReader<Fund>>();
var wrappedReader = container.Resolve<IReader<Wrapper<Fund>>>();

并且根据您的情况,您可以使用少于完整的AssemblyQualifiedName…

<alias alias="WrappedFund" type="TestUnityIssue.Wrapper`1[[TestUnityIssue.Fund, TestUnityIssue]], TestUnityIssue" />