using FastJSON;
|
using System;
|
using System.Collections;
|
using System.Collections.Generic;
|
using System.Reflection;
|
using System.Threading;
|
using System.Xml.Serialization;
|
|
namespace Top.Api.Parser
|
{
|
/// <summary>
|
/// TOP JSON响应通用解释器。
|
/// </summary>
|
public class DingTalkJsonParser<T> : ITopParser<T> where T : TopResponse
|
{
|
private static readonly ReaderWriterLock rwLock = new ReaderWriterLock();
|
private static readonly Dictionary<string, Dictionary<string, TopAttribute>> attrs = new Dictionary<string, Dictionary<string, TopAttribute>>();
|
|
#region ITopParser Members
|
|
public virtual T Parse(string body)
|
{
|
return Parse(body, typeof(T));
|
}
|
|
public T Parse(string body, Type type)
|
{
|
T rsp = null;
|
|
IDictionary json = JSON.Parse(body) as IDictionary;
|
if (json != null)
|
{
|
IDictionary data = json;
|
|
if (data != null)
|
{
|
ITopReader reader = new TopSimplifyJsonReader(data);
|
rsp = (T)FromJson(reader, type);
|
}
|
}
|
|
if (rsp == null)
|
{
|
rsp = Activator.CreateInstance(type) as T;
|
}
|
|
if (rsp != null)
|
{
|
rsp.Body = body;
|
}
|
|
return rsp;
|
}
|
|
#endregion
|
|
private Dictionary<string, TopAttribute> GetTopAttributes(Type type)
|
{
|
Dictionary<string, TopAttribute> tas = null;
|
bool inc = false;
|
|
rwLock.AcquireReaderLock(50);
|
try
|
{
|
if (rwLock.IsReaderLockHeld)
|
{
|
inc = attrs.TryGetValue(type.FullName, out tas);
|
}
|
}
|
finally
|
{
|
if (rwLock.IsReaderLockHeld)
|
{
|
rwLock.ReleaseReaderLock();
|
}
|
}
|
|
if (inc && 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);
|
}
|
|
rwLock.AcquireWriterLock(50);
|
try
|
{
|
if (rwLock.IsWriterLockHeld)
|
{
|
attrs[type.FullName] = tas;
|
}
|
}
|
finally
|
{
|
if (rwLock.IsWriterLockHeld)
|
{
|
rwLock.ReleaseWriterLock();
|
}
|
}
|
return tas;
|
}
|
|
public object FromJson(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, FromJson);
|
}
|
else
|
{
|
if (typeof(string) == ta.ItemType)
|
{
|
object tmp = reader.GetPrimitiveObject(itemName);
|
if (typeof(string) == tmp.GetType())
|
{
|
value = tmp;
|
}
|
else
|
{
|
if (tmp != null)
|
{
|
value = JSON.ToJSON(tmp);
|
}
|
}
|
}
|
else if (typeof(long) == ta.ItemType)
|
{
|
object tmp = reader.GetPrimitiveObject(itemName);
|
if (typeof(long) == tmp.GetType())
|
{
|
value = tmp;
|
}
|
else
|
{
|
if (tmp != null)
|
{
|
value = long.Parse(tmp.ToString());
|
}
|
}
|
}
|
else if (typeof(bool) == ta.ItemType)
|
{
|
object tmp = reader.GetPrimitiveObject(itemName);
|
if (typeof(bool) == tmp.GetType())
|
{
|
value = tmp;
|
}
|
else
|
{
|
if (tmp != null)
|
{
|
value = bool.Parse(tmp.ToString());
|
}
|
}
|
}
|
else
|
{
|
value = reader.GetReferenceObject(itemName, ta.ItemType, FromJson);
|
}
|
}
|
|
if (value != null)
|
{
|
if (rsp == null)
|
{
|
rsp = Activator.CreateInstance(type);
|
}
|
ta.Method.Invoke(rsp, new object[] { value });
|
}
|
}
|
|
return rsp;
|
}
|
}
|
}
|