spring.net 泛型接口注入+泛型接口结合协变注入
首先看下 spring.net 操作手册中关于类型别名的说明
作为类型全名的替代物,类型别名可以简化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>
再看泛型接口注入说明
泛型对象的创建方法和普通对象是一样的。
下面是一个泛型类的代码:
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属性的时候要注意:第一,左尖括号<要替换成字符串“<”,因为在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 在使用 泛型接口的同时,参数同时也为接口
所以我们声明的时候 指定泛型接口的参数为 协变参数
这样就可以处理