C#回顾 - 8.利用反射动态创建对象

时间:2021-06-06 19:25:03
 
拿微信消息返回的示例数据实验
  1. var data = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>1348831860</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[this is a test]]></Content><MsgId>1234567890123456</MsgId></xml>";  
 
创建一个消息枚举
  1. /// <summary>  
  2. /// 消息类型枚举  
  3. /// </summary>  
  4. public enum MsgType  
  5. {  
  6.     /// <summary>  
  7.     /// 文本消息  
  8.     /// </summary>  
  9.     TEXT,  
  10.     /// <summary>  
  11.     /// 图片消息  
  12.     /// </summary>  
  13.     IMAGE,  
  14.     /// <summary>  
  15.     /// 语音消息  
  16.     /// </summary>  
  17.     VOICE,  
  18.     /// <summary>  
  19.     /// 视频消息  
  20.     /// </summary>  
  21.     VIDEO,  
  22.     /// <summary>  
  23.     /// 小视频消息  
  24.     /// </summary>  
  25.     SHORTVIDEO,  
  26.     /// <summary>  
  27.     /// 地理位置消息  
  28.     /// </summary>  
  29.     LOCATION,  
  30.     /// <summary>  
  31.     /// 链接消息  
  32.     /// </summary>  
  33.     LINK,  
  34.     /// <summary>  
  35.     /// 事件类型  
  36.     /// </summary>  
  37.     EVENT  
  38. }  
 
因为消息类型的大多数属性都相同,创建一个基类
  1. public abstract class BaseMsg  
  2. {  
  3.     /// <summary>  
  4.     /// 开发者微信号  
  5.     /// </summary>  
  6.     public string ToUserName { getset; }  
  7.     /// <summary>  
  8.     /// 发送方帐号(一个OpenID)  
  9.     /// </summary>  
  10.     public string FromUserName { getset; }  
  11.     /// <summary>  
  12.     /// 消息创建时间 (整型)  
  13.     /// </summary>  
  14.     public string CreateTime { getset; }  
  15.     /// <summary>  
  16.     /// 消息类型  
  17.     /// </summary>  
  18.     public MsgType MsgType { getset; }  
  19.   
  20. }  
 
再创建相应缺少类的属性
  1. /// <summary>  
  2. /// 文本消息类型(例外)  
  3. /// </summary>  
  4. public class MsgText BaseMsg  
  5. {  
  6.     /// <summary>  
  7.     /// 文本消息内容  
  8.     /// </summary>  
  9.     public string Content { getset; }  
  10.     /// <summary>  
  11.     /// 消息Id,64位整型  
  12.     /// </summary>  
  13.     public string MsgId { getset; }  
  14. }  
  15.   
  16. /// <summary>  
  17. /// 图片消息类型(例外)  
  18. /// </summary>  
  19. public class MsgImage BaseMsg  
  20. {  
  21.     /// <summary>  
  22.     /// 图片链接  
  23.     /// </summary>  
  24.     public string PicUrl { getset; }  
  25.     /// <summary>  
  26.     /// 消息Id,64位整型  
  27.     /// </summary>  
  28.     public string MsgId { getset; }  
  29.     /// <summary>  
  30.     /// 图片消息媒体id,可以调用多媒体文件下载接口拉取数据。  
  31.     /// </summary>  
  32.     public string MediaId { getset; }  
  33. }  
  34.   
  35. /// <summary>  
  36. /// 语音消息类型(例外)  
  37. /// </summary>  
  38. public class MsgVoice BaseMsg  
  39. {  
  40.     /// <summary>  
  41.     /// 语音消息媒体id,可以调用多媒体文件下载接口拉取数据。  
  42.     /// </summary>  
  43.     public string MediaId { getset; }  
  44.     /// <summary>  
  45.     /// 语音格式,如amr,speex等  
  46.     /// </summary>  
  47.     public string Format { getset; }  
  48.     /// <summary>  
  49.     /// 消息id,64位整型  
  50.     /// </summary>  
  51.     public string MsgID { getset; }  
  52. }  
  53.   
  54. /// <summary>  
  55. /// 视频消息类型(例外)  
  56. /// </summary>  
  57. public class MsgVideo BaseMsg  
  58. {  
  59.     /// <summary>  
  60.     /// 视频消息媒体id,可以调用多媒体文件下载接口拉取数据  
  61.     /// </summary>  
  62.     public string MediaId { getset; }  
  63.     /// <summary>  
  64.     /// 视频消息缩略图的媒体id,可以调用多媒体文件下载接口拉取数据。  
  65.     /// </summary>  
  66.     public string ThumbMediaId { getset; }  
  67.     /// <summary>  
  68.     /// 消息id,64位整型  
  69.     /// </summary>  
  70.     public string MsgId { getset; }  
  71. }  
  72.   
  73. /// <summary>  
  74. /// 小视频消息类型(例外)  
  75. /// </summary>  
  76. public class MsgShortVideo : BaseMsg  
  77. {  
  78.     /// <summary>  
  79.     /// 视频消息媒体id,可以调用多媒体文件下载接口拉取数据  
  80.     /// </summary>  
  81.     public string MediaId { getset; }  
  82.     /// <summary>  
  83.     /// 视频消息缩略图的媒体id,可以调用多媒体文件下载接口拉取数据。  
  84.     /// </summary>  
  85.     public string ThumbMediaId { getset; }  
  86.     /// <summary>  
  87.     /// 消息id,64位整型  
  88.     /// </summary>  
  89.     public string MsgId { getset; }  
  90. }  
  91.   
  92. /// <summary>  
  93. /// 地理位置消息类型(例外)  
  94. /// </summary>  
  95. public class MsgLocation BaseMsg  
  96. {  
  97.     /// <summary>  
  98.     /// 地理位置维度  
  99.     /// </summary>  
  100.     public string Location_X { getset; }  
  101.     /// <summary>  
  102.     /// 地理位置经度  
  103.     /// </summary>  
  104.     public string Location_Y { getset; }  
  105.     /// <summary>  
  106.     /// 地图缩放大小  
  107.     /// </summary>  
  108.     public string Scale { getset; }  
  109.     /// <summary>  
  110.     /// 地理位置信息  
  111.     /// </summary>  
  112.     public string Label { getset; }  
  113.     /// <summary>  
  114.     /// 消息id,64位整型  
  115.     /// </summary>  
  116.     public string MsgId { getset; }  
  117. }  
  118.   
  119. /// <summary>  
  120. /// 链接消息类型(例外)  
  121. /// </summary>  
  122. public class MsgLink BaseMsg  
  123. {  
  124.     /// <summary>  
  125.     /// 消息标题  
  126.     /// </summary>  
  127.     public string Title { getset; }  
  128.     /// <summary>  
  129.     /// 消息描述  
  130.     /// </summary>  
  131.     public string Description { getset; }  
  132.     /// <summary>  
  133.     /// 消息链接  
  134.     /// </summary>  
  135.     public string Url { getset; }  
  136.     /// <summary>  
  137.     /// 消息id,64位整型  
  138.     /// </summary>  
  139.     public string MsgId { getset; }  
  140. }  
 
加载消息,转换成对象
  1. public static BaseMsg LoadMsg()  
  2.  {  
  3.   
  4.      var data = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>1348831860</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[this is a test]]></Content><MsgId>1234567890123456</MsgId></xml>";  
  5.   
  6.      var doc = XElement.Parse(data);  
  7.   
  8.      MsgType msgtype = (MsgType)Enum.Parse(typeof(MsgType), doc.Element("MsgType").Value.ToUpper());  
  9.      //MsgType msgtype = (MsgType)Enum.Parse(typeof(MsgType), "TEXT");  
  10.      switch (msgtype)  
  11.      {  
  12.          case MsgType.IMAGE:  
  13.              return ConvertObj<MsgImage>(data);  
  14.          case MsgType.LINK:  
  15.              return ConvertObj<MsgLink>(data);  
  16.          case MsgType.LOCATION:  
  17.              return ConvertObj<MsgLocation>(data);  
  18.          case MsgType.VIDEO:  
  19.              return ConvertObj<MsgVideo>(data);  
  20.          case MsgType.SHORTVIDEO:  
  21.              return ConvertObj<MsgShortVideo>(data);  
  22.          case MsgType.TEXT:  
  23.              return ConvertObj<MsgText>(data);  
  24.          case MsgType.EVENT:  
  25.              return null;  
  26.          default:  
  27.              return ConvertObj<BaseMsg>(data);  
  28.      }  
  29.  }  
 
利用反射
  1. public static T ConvertObj<T>(string xmlstr)  
  2.  {  
  3.      try  
  4.      {  
  5.          var xml = XElement.Parse(xmlstr);  
  6.          var type = typeof(T);  
  7.          var t = Activator.CreateInstance<T>(); //动态创建实例,相当于 new T()  
  8.   
  9.          var tousername = type.GetProperty("ToUserName");//搜索具有指定名称的公共属性  
  10.           //PropertyInfo.SetValue(object obj, object value, object[] index)
  11.          tousername.SetValue(t, Convert.ChangeType(xml.Element("ToUserName").Value, tousername.PropertyType), null);  
  12.          xml.Element("ToUserName").Remove();  
  13.   
  14.          var fromusername = type.GetProperty("FromUserName");  
  15.          fromusername.SetValue(t,  
  16.          Convert.ChangeType(xml.Element("FromUserName").Value, fromusername.PropertyType), null);  
  17.          xml.Element("FromUserName").Remove();  
  18.   
  19.          var createtime = type.GetProperty("CreateTime");  
  20.          createtime.SetValue(t, Convert.ChangeType(xml.Element("CreateTime").Value, createtime.PropertyType), null);  
  21.          xml.Element("CreateTime").Remove();  
  22.   
  23.          var msgType = type.GetProperty("MsgType");  
  24.          var msgtype = xml.Element("MsgType").Value;  
  25.          //msgType.SetValue()  是枚举,参数要改变
  26.          msgType.SetValue(t, (MsgType)Enum.Parse(typeof(MsgType), msgtype.ToUpper()), null);  
  27.          xml.Element("MsgType").Remove();  
  28.          foreach (var element in xml.Elements())  
  29.          {  
  30.              var pr = type.GetProperty(element.Name.ToString());  
  31.              pr.SetValue(t, Convert.ChangeType(element.Value, pr.PropertyType), null);  
  32.          }  
  33.          return t;  
  34.      }  
  35.      catch (Exception)  
  36.      {  
  37.          return default(T);  
  38.          throw;  
  39.      }  
  40.  }  
 
C#回顾 - 8.利用反射动态创建对象