经过同样的缓存优化后,JSON解释器在性能上要比微软自带的XML解释器慢10倍左右[XML为0.15ms,JSON为1.56ms],不过由于JSON的返回结果要比XML小一些,相对于网络IO的性能,这个1毫秒级别的性能差距也就可以忽略不计了 |
/// <summary> /// TOP API响应解释器接口。响应格式可以是XML, JSON等等。 /// </summary> /// <typeparam name="T">领域对象</typeparam> public interface ITopParser<T> { /// <summary> /// 把响应字符串解释成相应的领域对象。 /// </summary> /// <param name="body">响应字符串</param> /// <returns>领域对象</returns> T Parse(string body); }
public delegate object DTopConvert(ITopReader reader, Type type);
/// <summary> /// TOP API响应读取器接口。响应格式可以是XML, JSON等等。 /// </summary> public interface ITopReader { /// <summary> /// 判断响应中是否包含指定的属性。 /// </summary> /// <param name="name">属性名称</param> /// <returns>true/false</returns> bool HasReturnField(object name); /// <summary> /// 获取值类型属性的值。 /// </summary> /// <param name="name">属性名称</param> /// <returns>值对象</returns> object GetPrimitiveObject(object name); /// <summary> /// 获取引用类型的值。 /// </summary> /// <param name="name">属性名称</param> /// <param name="type">引用类型</param> /// <param name="convert">转换器</param> /// <returns>引用对象</returns> object GetReferenceObject(object name, Type type, DTopConvert convert); /// <summary> /// 获取列表类型的值。 /// </summary> /// <param name="listName">列表属性名称</param> /// <param name="itemName">列表项名称</param> /// <param name="type">引用类型</param> /// <param name="convert">转换器</param> /// <returns>列表对象</returns> IList GetListObjects(string listName, string itemName, Type type, DTopConvert convert); }
public class TopAttribute { public string ItemName { get; set; } public Type ItemType { get; set; } public string ListName { get; set; } public Type ListType { get; set; } public MethodInfo Method { get; set; } }
/// <summary> /// TOP JSON响应通用读取器。 /// </summary> public class TopJsonReader : ITopReader { private IDictionary json; public TopJsonReader(IDictionary json) { this.json = json; } public bool HasReturnField(object name) { return json.Contains(name); } public object GetPrimitiveObject(object name) { return json[name]; } public object GetReferenceObject(object name, Type type, DTopConvert convert) { IDictionary dict = json[name] as IDictionary; if (dict != null && dict.Count > 0) { return convert(new TopJsonReader(dict), type); } else { return null; } } public IList GetListObjects(string listName, string itemName, Type type, DTopConvert convert) { IList listObjs = null; IDictionary jsonMap = json[listName] as IDictionary; if (jsonMap != null && jsonMap.Count > 0) { IList jsonList = jsonMap[itemName] as IList; if (jsonList != null && jsonList.Count > 0) { Type listType = typeof(List<>).MakeGenericType(new Type[] { type }); listObjs = Activator.CreateInstance(listType) as IList; foreach (object item in jsonList) { if (typeof(IDictionary).IsAssignableFrom(item.GetType())) // object { IDictionary subMap = item as IDictionary; object subObj = convert(new TopJsonReader(subMap), type); if (subObj != null) { listObjs.Add(subObj); } } else if (typeof(IList).IsAssignableFrom(item.GetType())) // list/array { // TODO not support yet } else // boolean, long, double, string, null { listObjs.Add(item); } } } } return listObjs; } }
/// <summary> /// TOP JSON响应通用解释器。 /// </summary> public class TopJsonParser<T> : ITopParser<T> where T : TopResponse { private static Hashtable attrs = Hashtable.Synchronized(new Hashtable()); public T Parse(string body) { T rsp = null; IDictionary json = JsonConvert.Import(body) as IDictionary; if (json != null) { IDictionary data = null; // 忽略根节点的名称 foreach (object key in json.Keys) { data = json[key] as IDictionary; break; } if (data != null) { ITopReader reader = new TopJsonReader(data); rsp = (T)TopJsonConvert(reader, typeof(T)); } } if (rsp == null) { rsp = Activator.CreateInstance<T>(); } if (rsp != null) { rsp.Body = body; } return rsp; } private static Dictionary<string, TopAttribute> GetTopAttributes(Type type) { Dictionary<string, TopAttribute> tas = attrs[type.FullName] as Dictionary<string, TopAttribute>; if (tas != null) // 从缓存中获取类属性元数据 { return tas; } else // 创建新的类属性元数据缓存 { tas = new Dictionary<string, TopAttribute>(); } PropertyInfo[] pis = type.GetProperties(); foreach (PropertyInfo pi in pis) { TopAttribute ta = new TopAttribute(); ta.Method = pi.GetSetMethod(); // 获取对象属性名称 XmlElementAttribute[] xeas = pi.GetCustomAttributes(typeof(XmlElementAttribute), true) as XmlElementAttribute[]; if (xeas != null && xeas.Length > 0) { ta.ItemName = xeas[0].ElementName; } // 获取列表属性名称 if (ta.ItemName == null) { XmlArrayItemAttribute[] xaias = pi.GetCustomAttributes(typeof(XmlArrayItemAttribute), true) as XmlArrayItemAttribute[]; if (xaias != null && xaias.Length > 0) { ta.ItemName = xaias[0].ElementName; } XmlArrayAttribute[] xaas = pi.GetCustomAttributes(typeof(XmlArrayAttribute), true) as XmlArrayAttribute[]; if (xaas != null && xaas.Length > 0) { ta.ListName = xaas[0].ElementName; } if (ta.ListName == null) { continue; } } // 获取属性类型 if (pi.PropertyType.IsGenericType) { Type[] types = pi.PropertyType.GetGenericArguments(); ta.ListType = types[0]; } else { ta.ItemType = pi.PropertyType; } tas.Add(pi.Name, ta); } if (!attrs.ContainsKey(type.FullName)) { attrs.Add(type.FullName, tas); } return tas; } protected static readonly DTopConvert TopJsonConvert = delegate(ITopReader reader, Type type) { object rsp = null; Dictionary<string, TopAttribute> pas = GetTopAttributes(type); Dictionary<string, TopAttribute>.Enumerator em = pas.GetEnumerator(); while (em.MoveNext()) { KeyValuePair<string, TopAttribute> kvp = em.Current; TopAttribute ta = kvp.Value; string itemName = ta.ItemName; string listName = ta.ListName; if (!reader.HasReturnField(itemName) && (string.IsNullOrEmpty(listName) || !reader.HasReturnField(listName))) { continue; } object value = null; if (ta.ListType != null) { value = reader.GetListObjects(listName, itemName, ta.ListType, TopJsonConvert); } else { if (typeof(string) == ta.ItemType) { object tmp = reader.GetPrimitiveObject(itemName); if (tmp != null) { value = tmp.ToString(); } } else if (typeof(long) == ta.ItemType) { object tmp = reader.GetPrimitiveObject(itemName); if (tmp != null) { if (typeof(string) == tmp.GetType()) { long num = 0L; long.TryParse(tmp.ToString(), out num); value = num; } else { value = ((IConvertible)tmp).ToInt64(null); } } } else if (typeof(bool) == ta.ItemType) { value = reader.GetPrimitiveObject(itemName); } else { value = reader.GetReferenceObject(itemName, ta.ItemType, TopJsonConvert); } } if (value != null) { if (rsp == null) { rsp = Activator.CreateInstance(type); } ta.Method.Invoke(rsp, new object[] { value }); } } return rsp; }; }