首页 > 代码库 > spring.net 泛型接口注入+泛型接口结合协变注入

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="http://www.mamicode.com/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="http://www.mamicode.com/Spring.Web.Services.WebServiceExporter, Spring.Web"/>              <entry key="DefaultPointcutAdvisor" value="http://www.mamicode.com/Spring.Aop.Support.DefaultPointcutAdvisor, Spring.Aop"/>              <entry key="MyType" value="http://www.mamicode.com/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&lt;int>, GenericsPlay">  <property name="Name" value="http://www.mamicode.com/My Integer List"/></object>

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

<typeAliases> <alias name="GenericDictionary" type=" System.Collections.Generic.Dictionary&lt;,>" /> <alias name="myDictionary" type="System.Collections.Generic.Dictionary&lt;int,string>" /></typeAliases>

然后,下面的对象定义:

<object id="myGenericObject"         type="GenericsPlay.ExampleGenericObject&lt;System.Collections.Generic.Dictionary&lt;int , string>>, GenericsPlay" />

就可以缩短为:

<object id="myOtherGenericObject"         type="GenericsPlay.ExampleGenericObject&lt;GenericDictionary&lt;int , string>>, GenericsPlay" />

或者更短:

<object id="myOtherOtherGenericObject"         type="GenericsPlay.ExampleGenericObject&lt;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="http://www.mamicode.com/spring.net.Model,spring.net"></entry>						<entry key="type2" value="http://www.mamicode.com/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 在使用 泛型接口的同时,参数同时也为接口

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

这样就可以处理

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