码迷,mamicode.com
首页 > Web开发 > 详细

Reflection和Expression Tree解析泛型集合快速定制特殊格式的Json

时间:2015-12-02 14:19:53      阅读:214      评论:0      收藏:0      [点我收藏+]

标签:

  很多项目都会用到Json,而且大部分的Json都是格式固定,功能强大,转换简单等,标准的key,value集合字符串;直接JsonConvert.SerializeObject(List<T>)就可以搞定了,但凡事并非千篇一律,比如有的时候我们需要的Json可能只需要value,不需要key,并且前后可能还需要辅助信息等等,那该怎么办呢?我所能想到的可能有两种方案,1.自定义跟所需json格式一样的数据结构model,然后用JsonConvert.SerializeObject(model)直接得到;2.解析泛型集合再自定义拼接Json字符串。

  自定义Json格式:Json格式比较灵活,可以随意定义,也可以无限嵌套,这里只取两层,所有的data和id构成rows的集合,其中data只取T的value,并且在data之前加一个id,所以这里的Json就相当于只有rows嵌套了data。

技术分享

  构造泛型T的一个实例:既然是泛型,那就具有通用性,所以这里随便构造一个model,除了字段的多少和数据类型对本反射和Expression有一点点影响,其他的几乎可以忽略不计。

 1  public class Model1
 2     {
 3         public int Sales1 { get; set; }
 4         public int Title1 { get; set; }
 5         public double Sales { get; set; }
 6         public string Title { get; set; }
 7         public string Author { get; set; }
 8         public decimal Price { get; set; }
 9         public string Store { get; set; }
10         public string Shipping { get; set; }
11         public string Bestseller { get; set; }
12         public DateTime Publication { get; set; }
13     }

  Expression Tree核心代码:Expression解析T的成员变量,配合反射创建T的实例,用Expression动态创建Lambda表达式得到T的属性值。

技术分享
 1   private static Func<object, string, object> GenerateGetValue()
 2         {
 3             var type = typeof(T);
 4             var instance = Expression.Parameter(typeof(object), "instance");
 5             var memberName = Expression.Parameter(typeof(string), "memberName");
 6             var nameHash = Expression.Variable(typeof(int), "nameHash");
 7             var getHashCode = Expression.Assign(nameHash, Expression.Call(memberName, typeof(object).GetMethod("GetHashCode")));
 8             var switchEx = Expression.Switch(nameHash, Expression.Constant(null),
 9                 (from propertyInfo in type.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
10                  let property = Expression.Property(Expression.Convert(instance, typeof(T)), propertyInfo.Name)
11                  let propertyHash = Expression.Constant(propertyInfo.Name.GetHashCode(), typeof(int))
12                  select Expression.SwitchCase(Expression.Convert(property, typeof(object)), propertyHash)).ToArray());
13 
14             var methodBody = Expression.Block(typeof(object), new[] { nameHash }, getHashCode, switchEx);
15             return Expression.Lambda<Func<object, string, object>>(methodBody, instance, memberName).Compile();
16         }
View Code

  测试用例:用上面的泛型实例model1构造一个容量为10万个集合List<T>,至于T的属性值随便给他赛一些就可以了。

 1   public void TestMethod1()
 2         {
 3             var model = new List<Model1>();
 4             Stopwatch stopwatch = new Stopwatch();
 5             stopwatch.Start();
 6             for (int i = 0; i < 100000; i++)
 7             {
 8                 model.Add(new Model1
 9                 {
10                     Sales1 = 0,
11                     Title1 = 1,
12                     Sales = 33 + i,
13                     Title = "标题" + i,
14                     Shipping = "23",
15                     Author = "作者" + i,
16                     Store = "23",
17                     Bestseller = "0",
18                     Price = i,
19                     Publication = DateTime.Now
20                 });
21             }
22             stopwatch.Start();
23 
24             var json = JsonConvert.SerializeObject(model);
25             stopwatch.Stop();
26 
27             stopwatch.Stop();
28             Console.WriteLine(@"Json.NET按默认格式直接序列化100000个泛型对象耗时:" + stopwatch.ElapsedMilliseconds + @"毫秒");
29             stopwatch.Restart();
30             var reflectionJson = ListToJsonOfReflection<Model1>(model);
31             stopwatch.Stop();
32             Console.WriteLine(@"Reflection解析自定义拼接序列化100000个泛型对象耗时:" + stopwatch.ElapsedMilliseconds + @"毫秒");
33             stopwatch.Restart();
34             var expressionJson = ListToJsonOfExpression<Model1>(model);
35             stopwatch.Stop();
36             Console.WriteLine(@"Expression Tree解析自定义拼接序列化100000个泛型对象耗时:" + stopwatch.ElapsedMilliseconds + @"毫秒");
37          
38         }

  顺便做个性能测试,当然JsonConvert.SerializeObject(List<T>)得到的是key和value的集合字符串,比本文所需要的自定义拼接的字符串多了key,所以没有什么可比性,只是顺带列出来而已。纯反射解析List<T>拼接和Expression Tree解析List<T>拼接得到的Json格式一模一样。很明显Expression Tree 配合反射在执行大量动作时性能比纯反射还要高很多。

 技术分享

 

Reflection和Expression Tree解析泛型集合快速定制特殊格式的Json

标签:

原文地址:http://www.cnblogs.com/qinersky902/p/5012667.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!