zoukankan      html  css  js  c++  java
  • 动态编译

     


    玩转动态编译:一、初识中,我们已经学会了最简单的使用动态编译。今天直接由实战入手,看看真实情况下的动态编译能为我们来带什么。

    今天要演示的实例是一个在实际开发中经常遇到的情况,对象转Json。

    我将会使用2种方式分别做一个转json字符串的实例,1:反射;2:动态编译

    • 分析问题

     分析C#对象在json中的映射。总体来说json对象只有几种情况

    1. 键值对对象,由多组键对象+值对象构成,最外面是一对花括号包裹,键值对对象同时也可作为“值对象”使用
    2. 数组对象,由多个值对象构成,最外面是一对中括号包裹,数组对象同时也可作为“值对象”使用
    3. 键对象,由一个字符串构成,在键值对对象组成中担任“键”
    4. 一般值对象,由一个单独的值构成,可以是string,int,bool等,在键值对对象或者数组对象中担任“值”
    5. 特殊值对象,键值对对象或数组对象,本身也可以作为值对象使用

    这4中对象分别对应了C#中的:

    键值对对象 -> 任何有公开属性的对象,或者实现了IDictionary的对象,或者同时拥有Key和Value枚举的对象

    数组对象 -> 实现了IEnumerator或者IEnumerable接口的对象

    键对象 -> string对象

    一般值对象 -> System命名空间下的简单值类型,包括int,bool,float,DateTime等,外加一个string

    • 编写基类

    为了满足所有类型的转换需求,首先要建立一个抽象基类JsonConverter

     JsonConverter View Code

    这个类完成大部分基础类型的转换工作,只有一个方法等待实现

    • 反射实现
     JsonConverter_Reflection View Code
    • 动态编译实现

    动态编译的逻辑是这样的:因为在程序运行中,每个类型的相对应属性不可能发生更变,所以可以针对每个类型生成一个方法,

    比如User对象

    复制代码
    class User
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public bool Sex { get; set; }
    }
    复制代码

    我们可以为User对象生成一个方法,例如这个

    public static string ToJson(User user)
    {
        return "{ "Name":"" + user.Name + "","Age":" + user.Age + ","Sex","" + (user.Sex ? "" : "") + ""}";
    }

    这个方法如果自己写实在是太蛋疼了,但是我们可以在程序中构造,由于动态编译来完成,然后把方法委托缓存起来,下次就可以直接使用了

    整个方法是这样的

     JsonConverter_Dyncmp View Code
    • 测试调用
    复制代码
    namespace blqw
    {
        public static class Json
        {
            public static JsonConverter Converter1 = new JsonConverter_Reflection();
            public static JsonConverter Converter2 = new JsonConverter_Dyncmp();
            
    
            public static string ToJson_1(object obj)
            {
                return Converter1.ToJson(obj);
            }
    
            public static string ToJson_2(object obj)
            {
                return Converter2.ToJson(obj);
            }
        }
    }
    复制代码
    ToJson_1就是反射方式
    ToJson_2是动态编译的方式
    再附上测试代码
    一个非常复杂的对象
     User View Code
    复制代码
    static User GetUser()
    {//这里我尽量构造一个看上去很复杂的对象,并且这个对象几乎涵盖了所有常用的类型
        User user = new User();
        user.UID = Guid.NewGuid();
        user.Birthday = new DateTime(1986, 10, 29, 18, 00, 00);
        user.IsDeleted = false;
        user.Name = "blqw";
        user.Sex = UserSex.Male;
        user.LoginHistory = new List<DateTime>();
        user.LoginHistory.Add(DateTime.Today.Add(new TimeSpan(8, 00, 00)));
        user.LoginHistory.Add(DateTime.Today.Add(new TimeSpan(10, 10, 10)));
        user.LoginHistory.Add(DateTime.Today.Add(new TimeSpan(12, 33, 56)));
        user.LoginHistory.Add(DateTime.Today.Add(new TimeSpan(17, 25, 18)));
        user.LoginHistory.Add(DateTime.Today.Add(new TimeSpan(23, 06, 59)));
        user.Info = new UserInfo();
        user.Info.Address = "广东省广州市";
        user.Info.ZipCode = 510000;
        user.Info.Phone = new Dictionary<string, string>();
        user.Info.Phone.Add("手机", "18688888888");
        user.Info.Phone.Add("电话", "82580000");
        user.Info.Phone.Add("短号", "10086");
        user.Info.Phone.Add("QQ", "21979018");
        return user;
    }
    复制代码
    测试用代码:
    复制代码
    static void Main(string[] args)
    {
        var = GetUser();
        Stopwatch sw = new Stopwatch();
        sw.Restart();
        for (int i = 0; i < 10000; i++)
        {
            Json.ToJson_1(user);
        }
        sw.Stop();
        Console.WriteLine(sw.ElapsedMilliseconds + "ms");
        sw.Restart();
        for (int i = 0; i < 10000; i++)
        {
            Json.ToJson_2(user);
        }
        sw.Stop();
        Console.WriteLine(sw.ElapsedMilliseconds + "ms");
    
        Console.WriteLine();
        Console.WriteLine(Json.ToJson_1(user));
    
        Console.WriteLine();
        Console.WriteLine(Json.ToJson_2(user));
    }
    复制代码
    • 查看结果

    • 小结
    看到结论,可能有人要开始说了:貌似第二个动态编译的方法性能还不如反射的好啊~~
    目前的情况来看呢,确实是这样的.不过动态编译当然不止如此,
    性能上的问题是一定要解决的

    欲知后事如何,且听下回分解

  • 相关阅读:
    C++11并发——多线程std::thread (一)
    css属性操作
    mustache使用
    layer常用方法代码
    layer使用
    java后台获取和js拼接展示信息
    生成二维码
    循环体中去除一部分特定的数据
    eclipse工具maven项目打包文件不是最新修改的
    sql server数据库备份单个表的结构和数据生成脚本
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3245308.html
Copyright © 2011-2022 走看看