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

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

  • 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> ItemList
      12 {
      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 }
      19
      20 foreach (string propname in PropNames)
      21 {
      22 string proptype = PropNameToInfo[propname].PropertyType.Name;
      23
      24 object value = null;
      25 if (NullValue.Keys.Contains(proptype))
      26 value = NullValue[proptype];
      27
      28 type.GetProperty(propname).SetValue(this, value, null);
      29 }
      30 }
      31
      32 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 }
      10
      11 public class Person : BaseEntity
      12 {
      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 Worker
Worker worker = new Worker(); //Get type of Worker
Type workerType = typeof(Worker); //Get Generic Method
MethodInfo doWorkMethod = workerType.GetMethod("DoWork"); //Invoke DoWork<T> with different Type
foreach (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 Worker
Worker worker = new Worker(); //Get Generic Method
MethodInfo 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 //Or
3 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 method
11 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 method
16
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 instance
27 }
28 }
29
30 #endregion
31
32 #region Static method
33
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 method
44 }
45 }
46
47 #endregion
48
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 List
60 IList resultList = (IList)curMethod.Invoke(worker, null);
61 //Show List
62 ShowList(resultList);
63 //Use Generic Class
64 Type xmlToolType = typeof(XMLTool<>).MakeGenericType(curType);
65 MethodInfo saveMethod = xmlToolType.GetMethod("XmlSerialize_Save");
66
67 saveMethod.Invoke
68 (
69 null, //Static method
70 new object[] { resultList, @"c:\", @"c:\Test_" + curType.Name + ".xml" }
71 );
72 }
73 }
74
75 Console.WriteLine("Serialization Completed...\r\n");
76 #endregion
77 }
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 }

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

  1. 采用异步来实现重新连接服务器或者重新启动服务 C#中类的属性的获取 SignalR2简易数据看板演示 C#动态调用泛型类、泛型方法 asp .net core Get raw request. 从壹开始前后端分离[.NetCore 不定期更新] 38 ║自动初始化数据库

    采用异步来实现重新连接服务器或者重新启动服务 开启异步监听,不会导致主线程的堵塞,在服务异常断开后一直检测重新连接服务,成功连接服务后通知各个注册的客户端! #region 检测断线并重连OPC服务 ...

  2. 动态调用WebService

    WebService内容 using Microsoft.CSharp;using System;using System.CodeDom;using System.CodeDom.Compiler; ...

  3. c# 动态调用WCF方法笔记!

    //动态调用wcf方法 string url = "http://localhost:54379/ServiceWCF.svc"; IDoubleService proxy = W ...

  4. C# 动态调用DLL库

    最近经常用到C#动态调用类库,简单的做下记录方便以后查询. 使用下面的几行代码就可以简单实现DLL类库的调用了 using System.Reflection; // 引入该命名空间 // 获取roc ...

  5. Atitit 动态调用webservice与客户端代理方式调用

    Atitit 动态调用webservice与客户端代理方式调用 方式1: 使用call.invoke  直接调用WSDL,缺点:麻烦,不推荐--特别是JAVA调用.NET的WS时,会有不少的问题需要解 ...

  6. StructureMap.dll 中的 GetInstance 重载 + 如何利用 反射动态创建泛型类

    public static T GetInstance<T>(ExplicitArguments args); // // Summary: // Creates a new instan ...

  7. C#动态调用WCF接口,两种方式任你选。

    写在前面 接触WCF还是它在最初诞生之处,一个分布式应用的巨作. 从开始接触到现在断断续续,真正使用的项目少之又少,更谈不上深入WCF内部实现机制和原理去研究,最近自己做一个项目时用到了WCF. 从这 ...

  8. 11月10日上午ajax基础知识、用ajax做登录页面、用ajax验证用户名是否可用、ajax动态调用数据库

    1.ajax的基础知识 ajax是结合了jquery.php等几种技术延伸出来的综合运用的技术,不是新的内容.ajax也是写在<script>标签里面的. 如果使用ajax一定是要有1个处 ...

  9. C# 调用WebService的3种方式 :直接调用、根据wsdl生成webservice的.cs文件及生成dll调用、动态调用

    1.直接调用 已知webservice路径,则可以直接 添加服务引用--高级--添加web引用 直接输入webservice URL.这个比较常见也很简单 即有完整的webservice文件目录如下图 ...

随机推荐

  1. 花生日记_花生日记APP下载_花生日记邀请码

    花生日记 国内领先的社交电商导购分享平台. 独创社交电商3+模式,社交+电商+社群,上线1个月注册用户超百万.合作商家涵括各个类目以及平台.为数万宝妈提供月收入3000以上兼职收入. 微信扫描下方二维 ...

  2. Python_sniffer(网络嗅探器)

    import socket import threading import time activeDegree=dict() flag=1 def main(): global activeDegre ...

  3. 如何使用 toml 配置 SpaceVim

    配置 SpaceVim 主要包括以下几个内容: 设置 SpaceVim 选项 启动/禁用模块 添加自定义插件 添加自定义按键映射以及插件配置 设置SpaceVim选项 原先,在 init.vim 文件 ...

  4. 【Service Fabric】小白入门记录 本地Service Fabric集群安装及设置

    本篇内容是自学自记,现在我还不知道Service Fabric究竟是怎么个入门法,反正按照入门教程先进行本地Service Fabric集群的安装,万里路始于足下,要学习总得先把环境装好了才能开始学习 ...

  5. File文件操作学习总结

    1.java.io.file用于表示文件(目录),也就是说程序员可以通过File类在程序中操作硬盘上的文件和目录, 2.File类只能用于表示文件(目录)的信息(名称和大小),不能对文件内容进行访问. ...

  6. USB/GPIO/SDIO

    通用串行总线(英语:Universal Serial Bus,缩写:USB)是连接计算机系统与外部设备的一种串口总线标准,也是一种输入输出接口的技术规范.它只有4根线,两个电源(5V,地线),两个数据 ...

  7. Maven install命令理解

    每一个构建都需要唯一的坐标来标识位置,我们根据坐标位置就能够下载构建至本地仓库.那么如果我们是内部项目,自定义的构建并不公开至网络上,项目成员又想依赖他怎么办呢?想想maven找寻构建的步骤. 先找寻 ...

  8. linux中~/cut/argus/

    1.Linux shell 截取字符变量的前8位 实现方法有如下几种: expr substr "$a" 1 8 echo $a|awk '{print substr(,1,8)} ...

  9. 关于TCP/IP,必知必会的十个经典问题[转]

    关于TCP/IP,必知必会的十个问题 原创 2018-01-25 Ruheng 技术特工队   本文整理了一些TCP/IP协议簇中需要必知必会的十大问题,既是面试高频问题,又是程序员必备基础素养. 一 ...

  10. RabbitMQ (五)主题(Topic)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/37706355 上一篇博客中,我们进步改良了我们的日志系统.我们使用direct类 ...