PageRenderTime 38ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/Senparc.Weixin.MP/Senparc.Weixin.MP/Helpers/EntityHelper.cs

https://github.com/mjhuangzk/WeiXinMPSDK
C# | 215 lines | 165 code | 8 blank | 42 comment | 19 complexity | 4012c441abbc6912275d9bd1aefcdb2f MD5 | raw file
Possible License(s): BSD-2-Clause, BSD-3-Clause
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reflection;
  5. using System.Text;
  6. using System.Xml.Linq;
  7. using Senparc.Weixin.MP.Entities;
  8. namespace Senparc.Weixin.MP.Helpers
  9. {
  10. public static class EntityHelper
  11. {
  12. /// <summary>
  13. /// 根据XML信息填充实实体
  14. /// </summary>
  15. /// <typeparam name="T">MessageBase为基类的类型,Response和Request都可以</typeparam>
  16. /// <param name="entity">实体</param>
  17. /// <param name="doc">XML</param>
  18. public static void FillEntityWithXml<T>(this T entity, XDocument doc) where T : /*MessageBase*/ class, new()
  19. {
  20. entity = entity ?? new T();
  21. var root = doc.Root;
  22. var props = entity.GetType().GetProperties();
  23. foreach (var prop in props)
  24. {
  25. var propName = prop.Name;
  26. if (root.Element(propName) != null)
  27. {
  28. switch (prop.PropertyType.Name)
  29. {
  30. //case "String":
  31. // goto default;
  32. case "DateTime":
  33. prop.SetValue(entity, DateTimeHelper.GetDateTimeFromXml(root.Element(propName).Value), null);
  34. break;
  35. case "Boolean":
  36. if (propName == "FuncFlag")
  37. {
  38. prop.SetValue(entity, root.Element(propName).Value == "1", null);
  39. }
  40. else
  41. {
  42. goto default;
  43. }
  44. break;
  45. case "Int32":
  46. prop.SetValue(entity, int.Parse(root.Element(propName).Value), null);
  47. break;
  48. case "Int64":
  49. prop.SetValue(entity, long.Parse(root.Element(propName).Value), null);
  50. break;
  51. case "Double":
  52. prop.SetValue(entity, double.Parse(root.Element(propName).Value), null);
  53. break;
  54. //以下为枚举类型
  55. case "RequestMsgType":
  56. //已设为只读
  57. //prop.SetValue(entity, MsgTypeHelper.GetRequestMsgType(root.Element(propName).Value), null);
  58. break;
  59. case "ResponseMsgType"://Response适用
  60. //已设为只读
  61. //prop.SetValue(entity, MsgTypeHelper.GetResponseMsgType(root.Element(propName).Value), null);
  62. break;
  63. case "Event":
  64. //已设为只读
  65. //prop.SetValue(entity, EventHelper.GetEventType(root.Element(propName).Value), null);
  66. break;
  67. //以下为实体类型
  68. case "List`1"://List<T>类型,ResponseMessageNews适用
  69. var genericArguments = prop.PropertyType.GetGenericArguments();
  70. if (genericArguments[0].Name == "Article")//Response适用
  71. {
  72. //文章下属节点item
  73. List<Article> articles = new List<Article>();
  74. foreach (var item in root.Element(propName).Elements("item"))
  75. {
  76. var article = new Article();
  77. FillEntityWithXml(article, new XDocument(item));
  78. articles.Add(article);
  79. }
  80. prop.SetValue(entity, articles, null);
  81. }
  82. break;
  83. case "Music"://ResponseMessageMusic适用
  84. Music music = new Music();
  85. FillEntityWithXml(music, new XDocument(root.Element(propName)));
  86. prop.SetValue(entity, music, null);
  87. break;
  88. default:
  89. prop.SetValue(entity, root.Element(propName).Value, null);
  90. break;
  91. }
  92. }
  93. }
  94. }
  95. /// <summary>
  96. /// 将实体转为XML
  97. /// </summary>
  98. /// <typeparam name="T">RequestMessage或ResponseMessage</typeparam>
  99. /// <param name="entity">实体</param>
  100. /// <returns></returns>
  101. public static XDocument ConvertEntityToXml<T>(this T entity) where T : class , new()
  102. {
  103. entity = entity ?? new T();
  104. var doc = new XDocument();
  105. doc.Add(new XElement("xml"));
  106. var root = doc.Root;
  107. /* 注意!
  108. * 经过测试,微信对字段排序有严格要求,这里对排序进行强制约束
  109. */
  110. var propNameOrder = new List<string>();
  111. //不同返回类型需要对应不同特殊格式的排序
  112. if (entity is ResponseMessageNews)
  113. {
  114. propNameOrder.AddRange(new[] { "ToUserName", "FromUserName", "CreateTime", "MsgType", "Content", "ArticleCount", "Articles", "FuncFlag",/*以下是Atricle属性*/ "Title ", "Description ", "PicUrl", "Url" });
  115. }
  116. else if (entity is ResponseMessageMusic)
  117. {
  118. propNameOrder.AddRange(new[] { "ToUserName", "FromUserName", "CreateTime", "MsgType", "Music", "FuncFlag",/*以下是Music属性*/ "Title ", "Description ", "MusicUrl", "HQMusicUrl" });
  119. }
  120. else
  121. {
  122. //如Text类型
  123. propNameOrder.AddRange(new[] { "ToUserName", "FromUserName", "CreateTime", "MsgType", "Content", "FuncFlag" });
  124. }
  125. Func<string, int> orderByPropName = propNameOrder.IndexOf;
  126. var props = entity.GetType().GetProperties().OrderBy(p => orderByPropName(p.Name)).ToList();
  127. foreach (var prop in props)
  128. {
  129. var propName = prop.Name;
  130. if (propName == "Articles")
  131. {
  132. //文章列表
  133. var atriclesElement = new XElement("Articles");
  134. var articales = prop.GetValue(entity, null) as List<Article>;
  135. foreach (var articale in articales)
  136. {
  137. var subNodes = ConvertEntityToXml(articale).Root.Elements();
  138. atriclesElement.Add(new XElement("item", subNodes));
  139. }
  140. root.Add(atriclesElement);
  141. }
  142. else if (propName == "Music")
  143. {
  144. //音乐格式
  145. var musicElement = new XElement("Music");
  146. var music = prop.GetValue(entity, null) as Music;
  147. var subNodes = ConvertEntityToXml(music).Root.Elements();
  148. musicElement.Add(subNodes);
  149. root.Add(musicElement);
  150. }
  151. else
  152. {
  153. switch (prop.PropertyType.Name)
  154. {
  155. case "String":
  156. root.Add(new XElement(propName,
  157. new XCData(prop.GetValue(entity, null) as string ?? "")));
  158. break;
  159. case "DateTime":
  160. root.Add(new XElement(propName, DateTimeHelper.GetWeixinDateTime((DateTime)prop.GetValue(entity, null))));
  161. break;
  162. case "Boolean":
  163. if (propName == "FuncFlag")
  164. {
  165. root.Add(new XElement(propName, (bool)prop.GetValue(entity, null) ? "1" : "0"));
  166. }
  167. else
  168. {
  169. goto default;
  170. }
  171. break;
  172. case "ResponseMsgType":
  173. root.Add(new XElement(propName, prop.GetValue(entity, null).ToString().ToLower()));
  174. break;
  175. case "Article":
  176. root.Add(new XElement(propName, prop.GetValue(entity, null).ToString().ToLower()));
  177. break;
  178. default:
  179. root.Add(new XElement(propName, prop.GetValue(entity, null)));
  180. break;
  181. }
  182. }
  183. }
  184. return doc;
  185. }
  186. /// <summary>
  187. /// 将实体转为XML字符串
  188. /// </summary>
  189. /// <typeparam name="T">RequestMessage或ResponseMessage</typeparam>
  190. /// <param name="entity">实体</param>
  191. /// <returns></returns>
  192. public static string ConvertEntityToXmlString<T>(this T entity) where T : class , new()
  193. {
  194. return entity.ConvertEntityToXml().ToString();
  195. }
  196. /// <summary>
  197. /// ResponseMessageBase.CreateFromRequestMessage<T>(requestMessage)的扩展方法
  198. /// </summary>
  199. /// <typeparam name="T">需要生成的ResponseMessage类型</typeparam>
  200. /// <param name="requestMessage">IRequestMessageBase接口下的接收信息类型</param>
  201. /// <returns></returns>
  202. public static T CreateResponseMessage<T>(this IRequestMessageBase requestMessage) where T : ResponseMessageBase
  203. {
  204. return ResponseMessageBase.CreateFromRequestMessage<T>(requestMessage);
  205. }
  206. }
  207. }