C#动态调用泛型类、泛型方法

在制作一个批量序列化工具时遇到了如下问题,在此记录一下,仅供参考。

主程序加载另一个程序集,将其中的所有类取出,然后对这些类分别调用泛型类或泛型方法。控制台程序解决方案如下:

  • Main工程:提供Worker类进行数据操作,XMLTool<T>泛型类将数据集序列化为.xml文档,RootCollection<T>类封装数据集

    • Worker类

           提供成员方法void DoWork<T>()、List<T> GetList<T>()、静态成员方法StaticDoWork<T>(),代码如下:

     1 public class Worker 2     { 3         public Worker() 4         { 5         } 6  7         public void DoWork<T>() 8         { 9             Type t = typeof(T);10             Console.WriteLine("Get Class: {0}", t.Name);11             PropertyInfo[] properties = t.GetProperties();12             foreach (PropertyInfo property in properties)13             {14                 Console.WriteLine("\tproperty.Name: " + property.Name + "\tproperty.MemberType: " + property.PropertyType);15             }16         }17 18         public static void StaticDoWork<T>()19         {20             Type t = typeof(T);21             Console.WriteLine("Get Class: {0}", t.Name);22             PropertyInfo[] properties = t.GetProperties();23             foreach (PropertyInfo property in properties)24             {25                 Console.WriteLine("\tproperty.Name: " + property.Name + "\tproperty.MemberType: " + property.PropertyType);26             }27         }28 29         public List<T> GetList<T>()30         {31             Console.WriteLine("Generate List for [{0}]", typeof(T).Name);32             return new List<T>() 33             { 34                 Activator.CreateInstance<T>(), 35                 Activator.CreateInstance<T>() 36             };37         }38     }

    • XMLTool<T>类

       1publicclass XMLTool<T> 2     { 3publicstaticvoid XmlSerialize_Save(List<T> needSerializedList, string xmlDirPath, string xmlFileName) 4         { 5             RootCollection<T> collection = new RootCollection<T>(); 6             collection.ItemList = needSerializedList; 7if (!Directory.Exists(xmlDirPath)) 8                 Directory.CreateDirectory(xmlDirPath); 9using (System.IO.FileStream stream = new System.IO.FileStream(xmlFileName, System.IO.FileMode.Create))10             {11                 System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(collection.GetType());12                 serializer.Serialize(stream, collection);13             }14         }15     }

    • RootCollection<T>类:

       1     [Serializable] 2     public class RootCollection<T> 3     { 4         public RootCollection() 5         { 6             itemList = new List<T>(); 7         } 8  9         private List<T> itemList;10 11         public List<T> ItemList12         {13             get { return itemList; }14             set { itemList = value; }15         }16     }

  • MockClassLib工程:提供BaseEntityAppleCatPerson
    • BaseEntity类:抽象类,负责初始化类成员

       1     public abstract class BaseEntity 2     { 3         public BaseEntity() 4         { 5             InitiaWithNull(); 6         } 7 8         private void InitiaWithNull() 9         {10             Type type = this.GetType();11             PropertyInfo[] properties = type.GetProperties();12             string[] PropNames = new string[properties.Length];13             Dictionary<string, PropertyInfo> PropNameToInfo = new Dictionary<string, PropertyInfo>();14             for (int i = 0; i < properties.Length; i++)15             {16                 PropNames[i] = properties[i].Name;17                 PropNameToInfo.Add(PropNames[i], properties[i]);18             }1920             foreach (string propname in PropNames)21             {22                 string proptype = PropNameToInfo[propname].PropertyType.Name;2324                 object value = null;25                 if (NullValue.Keys.Contains(proptype))26                     value = NullValue[proptype];2728                 type.GetProperty(propname).SetValue(this, value, null);29             }30         }3132         private static readonly Dictionary<string, object> NullValue = new Dictionary<string, object>() 33             { 34                 { "String", String.Empty }, 35                 { "DateTime", DateTime.MinValue},36                 { "Decimal", Decimal.MinValue}37             };38     }

    • AppleCatPerson类:测试类,继承于BaseEntity

       1     public class Apple : BaseEntity 2     { 3        public string Color { get; set; } 4     } 5 6     public class Cat : BaseEntity 7     { 8        public string Type { get; set; } 9     }1011     public class Person : BaseEntity12     {13        public int ID { get; set; }14        public string Name { get; set; }15     }

Main工程的Program的Main方法中,一般情况下,调用Worker的泛型方法来处理测试类的话,可以写为:

Worker worker = new Worker();

worker.DoWork<Apple>();

worker.DoWork<Cat>();

worker.DoWork<Person>();

但是,如果MockClassLib中需要处理的类型非常多时,这样显示调用必然是不灵活的,应当怎样向泛型方法DoWork<T>()的尖括号中动态传入类型呢?

考虑代码:

            //Load assembly            Assembly mockAssembly = Assembly.LoadFrom("MockClassLibrary.dll");            Type[] typeArray = mockAssembly.GetTypes();

//Create instance of Worker                      Worker worker = new Worker();            foreach(Type curType in typeArray)            {                  worker.DoWork<curType>();   //Error            }

可以看到,Type类型的实例是无法直接传入泛型方法的尖括号中的,T要求显式指明类型名。

下面通过反射方式来获取泛型方法,并创建特定类型的泛型方法。

  • 对于非静态方法:public void DoWork<T>()

对于非静态方法,调用MethodInfo.Invoke(object, object[])时,第一个参数需要指明泛型方法的所有者(即这里创建的worker对象),第二个参数为泛

型方法的参数列表,DoWork<T>()没有输入参数,所以设为null

//Create an instance of WorkerWorker worker = new Worker();       

//Get type of WorkerType workerType = typeof(Worker);

//Get Generic MethodMethodInfo doWorkMethod = workerType.GetMethod("DoWork");

//Invoke DoWork<T> with different Typeforeach (Type curType in typeArray){    if (curType.IsClass && !curType.IsAbstract)//Filter BaseEntity    {        MethodInfo curMethod = doWorkMethod.MakeGenericMethod(curType);        curMethod.Invoke(worker, null);//Member method,use instance    }}

  • 对于静态方法:public static void StaticDoWork<T>()

不同于非静态方法,这里直接反射的类静态方法,所以Invoke()的第一个参数设为null

//Get type of WorkerWorker worker = new Worker();

//Get Generic MethodMethodInfo staticDoWorkMethod = workerType.GetMethod("StaticDoWork");

//Invoke StaticDoWork<T>foreach (Type curType in typeArray){    if (curType.IsClass && !curType.IsAbstract)    {        MethodInfo curMethod = staticDoWorkMethod.MakeGenericMethod(curType);        curMethod.Invoke(null, null);//Static method    }}

  • 对于有返回值的非静态方法:public List<T> GetList()

如同动态调用DoWork<T>()方法一样,只是在处理返回值时,可以使用下面的方法

1 IList tempList = (IList)curMethod.Invoke(worker, null);2 //Or3 IEnumerable tempList = (IEnumerable)curMethod.Invoke(worker, null);
  • 对于泛型类:XMLTool<T>

下面要使用泛型类XMLTool<T>的静态方法public static void XmlSerialize_Save(List<T> list, string dirPath, string fileName)方法。

首先应通过反射构造出指定类型的泛型类XMLTool<T>,再反射出其中的XmlSerialize_Save方法并使用。

 1 //Use Generic Class 2 Type xmlToolType = typeof(XMLTool<>).MakeGenericType(curType); 3  4 //Get method 5 MethodInfo saveMethod = xmlToolType.GetMethod("XmlSerialize_Save"); 6  7 //Invoke 8 saveMethod.Invoke 9 (10     null, //Static method11     new object[] { resultList, @"c:\", @"c:\Test_" + curType.Name + ".xml" }

12 );

Program-->Main()方法的全部代码:

 1 namespace RetrieveUnknownClass 2 { 3     class Program 4     { 5         static void Main(string[] args) 6         { 7             //Load assembly 8             Assembly mockAssembly = Assembly.LoadFrom("MockClassLibrary.dll"); 9             Type[] typeArray = mockAssembly.GetTypes();10 11             //Create instance of Worker          12             Type workerType = typeof(Worker);13             Worker worker = new Worker();14 15             #region Member method16 17             Console.WriteLine(">>>>>>>>>Use Generic Method:");18             MethodInfo doWorkMethod = workerType.GetMethod("DoWork");19 20             //Invoke DoWork<T>21             foreach (Type curType in typeArray)22             {23                 if (curType.IsClass && !curType.IsAbstract)24                 {25                     MethodInfo curMethod = doWorkMethod.MakeGenericMethod(curType);26                     curMethod.Invoke(worker, null);//Member method,use instance27                 }28             }29 30             #endregion31 32             #region Static method33 34             Console.WriteLine("\r\n>>>>>>>>>Use Static Generic Method:");35             MethodInfo staticDoWorkMethod = workerType.GetMethod("StaticDoWork");36 37             //Invoke StaticDoWork<T>38             foreach (Type curType in typeArray)39             {40                 if (curType.IsClass && !curType.IsAbstract)41                 {42                     MethodInfo curMethod = staticDoWorkMethod.MakeGenericMethod(curType);43                     curMethod.Invoke(null, null);//Static method44                 }45             }46 47             #endregion48 49             #region Get A List & Serialize It to Xml File With Generic 50 51             Console.WriteLine("\r\n>>>>>>>>>Get List By Generic Method:");52             MethodInfo getListMethod = workerType.GetMethod("GetList");53 54             foreach (Type curType in typeArray)55             {56                 if (curType.IsClass && !curType.IsAbstract)57                 {58                     MethodInfo curMethod = getListMethod.MakeGenericMethod(curType);59                     //Generate List60                     IList resultList = (IList)curMethod.Invoke(worker, null);61                     //Show List62                     ShowList(resultList);63                     //Use Generic Class64                     Type xmlToolType = typeof(XMLTool<>).MakeGenericType(curType);65                     MethodInfo saveMethod = xmlToolType.GetMethod("XmlSerialize_Save");66 67                     saveMethod.Invoke68                         (69                             null, //Static method70                             new object[] { resultList, @"c:\", @"c:\Test_" + curType.Name + ".xml" }71                         );72                 }73             }74             75             Console.WriteLine("Serialization Completed...\r\n");76             #endregion77         }78 79         public static void ShowList(IList list)80         {81             Console.WriteLine("Type of list: {0}\r\nCount of current list: {1}\r\nType of item in list: {2}\r\n", 82                 list.GetType(), 83                 list.Count, 84                 list[0].GetType());85         }86     }87 }

原文地址:https://www.cnblogs.com/smiler/p/10177356.html

时间: 2024-10-09 23:31:51

C#动态调用泛型类、泛型方法的相关文章

C#中Winform动态调用Webservice的方法(转)

一般情况下winform调用webservice时步骤 1添加服务引用---高级----添加web引用------填写url--添加web引用即可完成对webservice的引用 让VS.NET环境来为我们生成服务代理,然后调用对应的Web服务. 如果需要动态调用WebService,要实现这样的功能: publicstaticobjectInvokeWebService(stringurl,  stringmethodname,object[] args) 其中,url是Web服务的地址,me

winform 动态调用webservice

一般情况下winform调用webservice时步骤 1添加服务引用---高级----添加web引用------填写url--添加web引用即可完成对webservice的引用 让VS.NET环境来为我们生成服务代理,然后调用对应的Web服务. 如果需要动态调用WebService,要实现这样的功能: publicstaticobjectInvokeWebService(stringurl,  stringmethodname,object[] args) 其中,url是Web服务的地址,me

struts2.5新配置动态调用

开启动态调用: <constant name="struts.enable.DynamicMethodInvocation" value="true"/> action标签method属性开启{1}: strict-method-invocation="false" 开启全局动态方法调用通配符: <global-allowed-methods>*</global-allowed-methods> 开启局部动态方

Struts2-学习笔记系列(6)-动态调用action

动态调用之前需要配置: <!--动态方法调用--> <constant name="struts.enable.DynamicMethodInvocation" value="true"></constant> 配置struts 1 <package name="zcx.controller" namespace="/" extends="struts-default&quo

C# 动态调用WebService

Reference from : http://blog.csdn.net/chuxiamuxiang/article/details/5731988 在C#程序中,若要调用WebService,一般是采用"添加Web引用"的方式来实现的.但如果此WebService的URL是在程序运行过程中才能获得的,那怎么办呢?那就必须是"动态"调用这个WebService了. 网上有不少关于这方面的例子,总结了一下,主要有两种:(1)每次都动态调用,(2)将WebServic

Java父类对象调用子类实体:方法重写与动态调用

众所周知Java的handle和C++的ponter而不是object对应,我们很熟悉C++的父类pointer调用子类实体的例子,那么对于Java的handle是不是也可以这样呢? 这里我先给一个例子 class Father{ public void announce(){ System.out.println("Father"); } } class Child extends Father{ @Override public void announce(){ System.ou

动态调用服务

利用动态调用服务,实现.net下类似Dubbo的玩法. 分布式微服务现在成为了很多公司架构首先项,据我了解,很多java公司架构都是 Maven+Dubbo+Zookeeper基础上扩展的. Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合).从服务模型的角度来看,Dubbo采用的是一种非常简单的模型,要么是提供方提供服务,要么是消费方消费服务,所以基于这一点可以抽象出服务提供方(Provider)和服务

动态调用webservice

public static class WebserviceHelper { /// <summary> /// 动态调用WebService /// </summary> /// <param name="url">WebService地址</param> /// <param name="methodname">方法名(模块名)</param> /// <param name=&quo

[转]Net 下采用GET/POST/SOAP方式动态调用WebService C#实现

本文转自:http://www.cnblogs.com/splendidme/archive/2011/10/05/2199501.html 一直以来,我们都为动态调用WebService方法而烦恼.在.Net环境下,最常用的方法就是采用代理类来调用WebService,可以通过改变代理类的Url属性来实现动态调用,但当xmlns改变时就会出错,似乎要重新绑定Webservice并重新编译后才能再次运行.我无意中通过百度搜索找了一个采用GET/POST/SOAP方式动态调用WebService的