`
carver
  • 浏览: 49054 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

基于Xml Attribute与Jayrock的纯.NET 2.0 JSON解释器实现

    博客分类:
  • .NET
阅读更多
经过同样的缓存优化后,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;
        };
    }
分享到:
评论

相关推荐

    Migrate an ASP.NET 1.1 Web Page Using the CodeBehind Attribute to ASP.NET 2.0

    How to- Migrate an ASP.NET 1.1 Web Page Using the CodeBehind Attribute to ASP.NET 2.0

    .net中attribute实现方法调用拦截(就是aop)

    包含2篇attribute高级应用文章,以及相应的代码。 代码关键处,都有详细注释。 看过后,你会对attribute,context有更深刻的认识

    中美 IT 培训 C# Asp.net 全套笔记1

    (160课时) 系统讲授 ASP.Net2.0、ADO.Net2.0、 基于数据库的WEB应用程序、的开发;详细地讲授Web Service及其应用和相关的安全性问题、WSE(Web Services Enhancements)、SOAP、WSDL、UDDI、Windows Service、VSS...

    中美 IT 培训 C# Asp.net 笔记3

    (160课时) 系统讲授 ASP.Net2.0、ADO.Net2.0、 基于数据库的WEB应用程序、的开发;详细地讲授Web Service及其应用和相关的安全性问题、WSE(Web Services Enhancements)、SOAP、WSDL、UDDI、Windows Service、VSS...

    中美 IT 培训 C# Asp.net 笔记2

    (160课时) 系统讲授 ASP.Net2.0、ADO.Net2.0、 基于数据库的WEB应用程序、的开发;详细地讲授Web Service及其应用和相关的安全性问题、WSE(Web Services Enhancements)、SOAP、WSDL、UDDI、Windows Service、VSS...

    Asp.net Core 3.1基于AspectCore实现AOP实现事务、缓存拦截器功能

    最近想给我的框架加一种功能,就是比如给一个方法加一个事务的特性Attribute,那这个方法就会启用事务处理。给一个方法加一个缓存特性,那这个方法就会进行缓存。 这个也是网上说的面向切面编程AOP。 AOP的概念也很...

    Attribute在.net编程中的应用

    读了《Attribute在.net编程中的应用》,对Attribute的认识会加深,对编程很有帮助哦!

    Attribute在.net编程中的应用(全)

    此文档详细的介绍了.NET下 自定义Attribute的应用,对于理解.NET AOP下的技术实现非常有帮助

    xml-rpc.net.2.4.0.zip

    Version 2.4.0 has been released: xml-rpc.net.2.4.0.zip New feature and fixed issues: New StructParams property on XmlRpcMethodAttribute which provides supports for APIs which use a struct to ...

    Attribute在.net编程中的应用(全).doc

    Attribute在.net编程中的应用(全).doc ,.net的高级特性,类似JAVA中的标注。

    ASP.NET MVC5 新特性:Attribute路由使用详解

    此文档详细讲解了:ASP.NET MVC5 新特性:Attribute路由的使用,非常的详细,值得学习。

    Attribute在.NET中的应用

    详细介绍了Attribute属性在.NET中的应用 适合初级人员,

    值类型与引用类型理论内容.part01.rar

    第二阶段教学内容安排(400课时) 课程名称 课程内容 培训目的 ASP.Net2.0、ADO.Net2.0和Web 应用程序 (160课时) 系统讲授 ASP.Net2.0、ADO.Net2.0、 基于数据库的WEB应用程序、的开发;...

    值类型与引用类型理论内容.part05.rar

    第二阶段教学内容安排(400课时) 课程名称 课程内容 培训目的 ASP.Net2.0、ADO.Net2.0和Web 应用程序 (160课时) 系统讲授 ASP.Net2.0、ADO.Net2.0、 基于数据库的WEB应用程序、的开发;...

    亮剑.NET深入体验与实战精要2

    6.4 ADO.NET与XML 266 6.4.1 读XML文档到DataSet 266 6.4.2 DataSet转为XML文档 267 6.5 项目案例1:实现网站的RSS应用 267 6.6 项目案例2:在线实现RSS阅读器 270 本章常见技术面试题 275 常见面试技巧之经典问题...

    .net core 权限管理实现方案之一

    该示例代码是针对asp.net core mvc权限管理的一种实现方式,不一定是最好的,但是能满足权限的有效控制

    亮剑.NET深入体验与实战精要3

    6.4 ADO.NET与XML 266 6.4.1 读XML文档到DataSet 266 6.4.2 DataSet转为XML文档 267 6.5 项目案例1:实现网站的RSS应用 267 6.6 项目案例2:在线实现RSS阅读器 270 本章常见技术面试题 275 常见面试技巧之经典问题...

    ASP.NET MVC5项目实现增删改查,供新手学习

    ASP.NET MVC5增删改查,包含LINQ和ADO两种(ADO只实现了List Detail和Delete,Edit留给你自己思考了),LINQ版本实现了完整的CRUD,并且演示了MVC5 的新特性Attribute Route以及异步的修改、删除控制器。

    Corsolas: AOP Attributed Framework-开源

    Corsolas AOP Attributed Framework for .NET 2.0 是一种处理面向切面编程的创新方式,基于属性,无需外部语言,以简单而强大的方式做到最好...... by maxtuno。

Global site tag (gtag.js) - Google Analytics