spring.net 泛型接口注入+泛型接口结合协变注入

版权所有,禁止匿名转载;禁止商业使用。

首先看下 spring.net 操作手册中关于类型别名的说明


4.12.3.注册类型别名


作为类型全名的替代物,类型别名可以简化Spring.NET的配置文件。别名可以在config文件中注册,也可以通过编程方式注册,注册之后就可以在对象定义中任何需要类型全名的地方使用。也可以为泛型类定义类型别名。


若要配置类型别名,一种方式是在Web/App.config文件中添加typeAliases节点和相应的节点处理器。请参看本节一开始的例子,其中为WebServiceExporter类定义了一个类型别名。一旦定义了类型别名,就可以象全名一样使用它们:


<object id="MyWebService" type="WebServiceExporter">
  ...
</object>
<object id="cacheAspect" type="DefaultPointcutAdvisor">
  <property name="Pointcut">
    <object type="AttributePointcut">
      <property name="Attribute" value="CacheAttribute"/>   
    </object>
  </property>
  <property name="Advice" ref="aspNetCacheAdvice"/>
</object>

关于如何为泛型类型定义类型别名,请参看4.2.4,创建泛型类型的对象。


另外,也可以通过Spring.Objects.Factory.Config.TypeAliasConfigurer类来注册类型别名。这种定义方法更加模块化,如果没有App/Web.config,也可以通过这种方式注册别名。请看下面的例子:


<

object id="myTypeAlias" type="Spring.Objects.Factory.Config.TypeAliasConfigurer, Spring.Core">
      <property name="TypeAliases">
          <dictionary>
              <entry key="WebServiceExporter" value="Spring.Web.Services.WebServiceExporter, Spring.Web"/>
              <entry key="DefaultPointcutAdvisor" value="Spring.Aop.Support.DefaultPointcutAdvisor, Spring.Aop"/>
              <entry key="MyType" value="MyCompany.MyProject.MyNamespace.MyType, MyAssembly"/>
          </dictionary>
      </property>
</object>

再看泛型接口注入说明


4.2.4.泛型类的对象创建


泛型对象的创建方法和普通对象是一样的。


4.2.4.1.通过构造器创建泛型对象


下面是一个泛型类的代码:


namespace GenericsPlay
{
  public class FilterableList<T>
  {
    private List<T> list;
    private String name;
    public List<T> Contents
    {
      get { return list; }
      set { list = value; }
    }
    public String Name
    {
      get { return name; }
      set { name = value; }
    }
    public List<T> ApplyFilter(string filterExpression)
    {
      /// should really apply filter to list ;)
      return new List<T>();
    }
  }
}

下面是该类的对象定义:


<object id="myFilteredIntList" type="GenericsPlay.FilterableList<int>, GenericsPlay">
  <property name="Name" value="My Integer List"/>
</object>

在为泛型类对象指定type属性的时候要注意:第一,左尖括号<要替换成字符串“&lt;”,因为在XML中左尖括号会被认为是小于号。从可读性来讲,我们都知道这并不是理想的方式。第二,type参数值中不能包含程序集的名称,因为程序集名称要求和类型全名用逗号隔开,而在这里逗号已经被用来分隔泛型类的类型参数了。将来可能会用其它字符代替这两个符号,但目前还没找到更具可读性的方案。若要提高可读性,建议使用类型别名,如下所示:


<typeAliases>
 <alias name="GenericDictionary" type=" System.Collections.Generic.Dictionary<,>" />
 <alias name="myDictionary" type="System.Collections.Generic.Dictionary<int,string>" />
</typeAliases>
然后,下面的对象定义:
<object id="myGenericObject" 
        type="GenericsPlay.ExampleGenericObject<System.Collections.Generic.Dictionary<int , string>>, GenericsPlay" />
就可以缩短为:
<object id="myOtherGenericObject" 
        type="GenericsPlay.ExampleGenericObject<GenericDictionary<int , string>>, GenericsPlay" />
或者更短:
<object id="myOtherOtherGenericObject" 
        type="GenericsPlay.ExampleGenericObject<MyIntStringDictionary>, GenericsPlay" />

下面来看例子

/

// <summary>
  /// 模型接口
  /// </summary>
  public interface IModel { }
  /// <summary>
  /// 模型实现
  /// </summary>
  public class Model : IModel { }
  /// <summary>
  /// 泛型接口 
  /// </summary>
  /// <typeparam name="T"></typeparam>
  public interface GenericsInterface<out T> where T : IModel
  { }
  /// <summary>
  /// 泛型接口实现类
  /// </summary>
  /// <typeparam name="T"></typeparam>
  public class GenericsClass<T> : GenericsInterface<T> where T : IModel
  { }
   public class GenericsClassTest
  {
    public Dictionary<int, GenericsInterface<Model>> dic { get; set; }
    public Dictionary<int, GenericsClass<Model>> dic1 { get; set; }
    public Dictionary<int, GenericsInterface<IModel>> dic2 { get; set; }
    public List<GenericsInterface<Model>> list { get; set; }
    public List<GenericsClass<Model>> list1 { get; set; }
    public GenericsInterface<Model> gi { get; set; }
    /// <summary>
    /// 成功-因为这里是 协变的接口
    /// </summary>
    public GenericsInterface<IModel> gi1 { get; set; }
  }

看配置文件


<!--配置-->
    <objects xmlns="http://www.springframework.net">
      <!--类型别名注入-->
      <object id="myTypeAlias" type="Spring.Objects.Factory.Config.TypeAliasConfigurer, Spring.Core">
        <property name="TypeAliases">
          <dictionary>
            <entry key="type1" value="spring.net.Model,spring.net"></entry>
            <entry key="type2" value="spring.net.IModel,spring.net"></entry>
          </dictionary>
        </property>
      </object>
      <object name="gc1" type="spring.net.GenericsClass<type1>,spring.net"></object>
      <object name="p1" type="spring.net.GenericsClassTest,spring.net">
        <property name="gi" ref="gc1"></property>
        <property name="gi1" ref="gc1"></property>
        <property name="dic">
          <dictionary key-type="int" value-type="spring.net.GenericsInterface<type1>,spring.net">
            <entry key="1" value-ref="gc1"></entry>
          </dictionary>
        </property>
        <property name="dic1">
          <dictionary key-type="int" value-type="spring.net.GenericsClass<type1>,spring.net">
            <entry key="1" value-ref="gc1"></entry>
          </dictionary>
        </property>
        <property name="dic2">
          <dictionary key-type="int" value-type="spring.net.GenericsInterface<type2>,spring.net">
            <entry key="1" value-ref="gc1"></entry>
          </dictionary>
        </property>
        <property name="list">
          <list element-type="spring.net.GenericsInterface<type1>,spring.net">
            <ref object="gc1"/>
            <ref object="gc1"/>
          </list>
        </property>
        <property name="list1">
          <list element-type="spring.net.GenericsClass<type1>,spring.net">
            <ref object="gc1"/>
            <ref object="gc1"/>
          </list>
        </property>
      </object>

其它的不做说明


类中的属性 dic2 与 gi1 在使用 泛型接口的同时,参数同时也为接口


所以我们声明的时候 指定泛型接口的参数为 协变参数


这样就可以处理


0 0