AopJsonParser.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Reflection;
  5. using System.Xml.Serialization;
  6. using Jayrock.Json.Conversion;
  7. using Aop.Api.Request;
  8. namespace Aop.Api.Parser
  9. {
  10. /// <summary>
  11. /// AOP JSON响应通用解释器。
  12. /// </summary>
  13. public class AopJsonParser<T> : IAopParser<T> where T : AopResponse
  14. {
  15. private static readonly Dictionary<string, Dictionary<string, AopAttribute>> attrs = new Dictionary<string, Dictionary<string, AopAttribute>>();
  16. #region IAopParser<T> Members
  17. public T Parse(string body,string charset)
  18. {
  19. T rsp = null;
  20. IDictionary json = JsonConvert.Import(body) as IDictionary;
  21. if (json != null)
  22. {
  23. IDictionary data = null;
  24. // 忽略根节点的名称
  25. foreach (object key in json.Keys)
  26. {
  27. data = json[key] as IDictionary;
  28. if (data != null && data.Count > 0)
  29. {
  30. break;
  31. }
  32. }
  33. if (data != null)
  34. {
  35. IAopReader reader = new AopJsonReader(data);
  36. rsp = (T)AopJsonConvert(reader, typeof(T));
  37. }
  38. }
  39. if (rsp == null)
  40. {
  41. rsp = Activator.CreateInstance<T>();
  42. }
  43. if (rsp != null)
  44. {
  45. rsp.Body = body;
  46. }
  47. return rsp;
  48. }
  49. public SignItem GetSignItem(IAopRequest<T> request, T response)
  50. {
  51. string body = response.Body;
  52. if (string.IsNullOrEmpty(body))
  53. {
  54. return null;
  55. }
  56. SignItem signItem = new SignItem();
  57. string sign = GetSign(body);
  58. signItem.Sign = sign;
  59. string signSourceData = GetSignSourceData(request, body);
  60. signItem.SignSourceDate = signSourceData;
  61. return signItem;
  62. }
  63. #endregion
  64. private static Dictionary<string, AopAttribute> GetAopAttributes(Type type)
  65. {
  66. Dictionary<string, AopAttribute> tas = null;
  67. bool inc = attrs.TryGetValue(type.FullName, out tas);
  68. if (inc && tas != null) // 从缓存中获取类属性元数据
  69. {
  70. return tas;
  71. }
  72. else // 创建新的类属性元数据缓存
  73. {
  74. tas = new Dictionary<string, AopAttribute>();
  75. }
  76. PropertyInfo[] pis = type.GetProperties();
  77. foreach (PropertyInfo pi in pis)
  78. {
  79. AopAttribute ta = new AopAttribute();
  80. ta.Method = pi.GetSetMethod();
  81. // 获取对象属性名称
  82. XmlElementAttribute[] xeas = pi.GetCustomAttributes(typeof(XmlElementAttribute), true) as XmlElementAttribute[];
  83. if (xeas != null && xeas.Length > 0)
  84. {
  85. ta.ItemName = xeas[0].ElementName;
  86. }
  87. // 获取列表属性名称
  88. if (ta.ItemName == null)
  89. {
  90. XmlArrayItemAttribute[] xaias = pi.GetCustomAttributes(typeof(XmlArrayItemAttribute), true) as XmlArrayItemAttribute[];
  91. if (xaias != null && xaias.Length > 0)
  92. {
  93. ta.ItemName = xaias[0].ElementName;
  94. }
  95. XmlArrayAttribute[] xaas = pi.GetCustomAttributes(typeof(XmlArrayAttribute), true) as XmlArrayAttribute[];
  96. if (xaas != null && xaas.Length > 0)
  97. {
  98. ta.ListName = xaas[0].ElementName;
  99. }
  100. if (ta.ListName == null)
  101. {
  102. continue;
  103. }
  104. }
  105. // 获取属性类型
  106. if (pi.PropertyType.IsGenericType)
  107. {
  108. Type[] types = pi.PropertyType.GetGenericArguments();
  109. ta.ListType = types[0];
  110. }
  111. else
  112. {
  113. ta.ItemType = pi.PropertyType;
  114. }
  115. tas.Add(pi.Name + ta.ItemType + ta.ListType, ta);
  116. }
  117. attrs[type.FullName] = tas;
  118. return tas;
  119. }
  120. protected static readonly DAopConvert AopJsonConvert = delegate(IAopReader reader, Type type)
  121. {
  122. object rsp = null;
  123. Dictionary<string, AopAttribute> pas = GetAopAttributes(type);
  124. Dictionary<string, AopAttribute>.Enumerator em = pas.GetEnumerator();
  125. while (em.MoveNext())
  126. {
  127. KeyValuePair<string, AopAttribute> kvp = em.Current;
  128. AopAttribute ta = kvp.Value;
  129. string itemName = ta.ItemName;
  130. string listName = ta.ListName;
  131. if (!reader.HasReturnField(itemName) && (string.IsNullOrEmpty(listName) || !reader.HasReturnField(listName)))
  132. {
  133. continue;
  134. }
  135. object value = null;
  136. if (ta.ListType != null)
  137. {
  138. value = reader.GetListObjects(listName, itemName, ta.ListType, AopJsonConvert);
  139. }
  140. else
  141. {
  142. if (typeof(string) == ta.ItemType)
  143. {
  144. object tmp = reader.GetPrimitiveObject(itemName);
  145. if (tmp != null)
  146. {
  147. value = tmp.ToString();
  148. }
  149. }
  150. else if (typeof(long) == ta.ItemType)
  151. {
  152. object tmp = reader.GetPrimitiveObject(itemName);
  153. if (tmp != null)
  154. {
  155. value = ((IConvertible)tmp).ToInt64(null);
  156. }
  157. }
  158. else if (typeof(bool) == ta.ItemType)
  159. {
  160. value = reader.GetPrimitiveObject(itemName);
  161. }
  162. else
  163. {
  164. value = reader.GetReferenceObject(itemName, ta.ItemType, AopJsonConvert);
  165. }
  166. }
  167. if (value != null)
  168. {
  169. if (rsp == null)
  170. {
  171. rsp = Activator.CreateInstance(type);
  172. }
  173. ta.Method.Invoke(rsp, new object[] { value });
  174. }
  175. }
  176. return rsp;
  177. };
  178. private static string GetSign(string body)
  179. {
  180. IDictionary json = JsonConvert.Import(body) as IDictionary;
  181. //Console.WriteLine(json);
  182. return (string)json["sign"];
  183. }
  184. private static string GetSignSourceData(IAopRequest<T> request, string body)
  185. {
  186. string rootNode = request.GetApiName().Replace(".", "_") + AlipayConstants.RESPONSE_SUFFIX;
  187. string errorRootNode = AlipayConstants.ERROR_RESPONSE;
  188. int indexOfRootNode = body.IndexOf(rootNode);
  189. int indexOfErrorRoot = body.IndexOf(errorRootNode);
  190. string result = null;
  191. if (indexOfRootNode > 0)
  192. {
  193. result = ParseSignSourceData(body, rootNode, indexOfRootNode);
  194. }
  195. else if (indexOfErrorRoot > 0)
  196. {
  197. result = ParseSignSourceData(body, errorRootNode, indexOfErrorRoot);
  198. }
  199. return result;
  200. }
  201. private static string ParseSignSourceData(string body, string rootNode, int indexOfRootNode)
  202. {
  203. int signDataStartIndex = indexOfRootNode + rootNode.Length + 2;
  204. int indexOfSign = body.IndexOf("\"" + AlipayConstants.SIGN + "\"");
  205. if (indexOfSign < 0)
  206. {
  207. return null;
  208. }
  209. int signDataEndIndex = indexOfSign - 1;
  210. int length = signDataEndIndex - signDataStartIndex;
  211. return body.Substring(signDataStartIndex, length);
  212. }
  213. }
  214. }