zoukankan      html  css  js  c++  java
  • 学习笔记: Expression表达式目录树详解和扩展封装

    1. 表达式目录树:语法树,或者说是一种数据结构;可以被我们解析

    Func<int, int, int> func = (m, n) => m * n + 2;// new Func<int, int, int>((m, n) => m * n + 2);
    Expression<Func<int, int, int>> exp = (m, n) => m * n + 2;//lambda表达式声明表达式目录树
                                                               //Expression<Func<int, int, int>> exp1 = (m, n) =>//只能一行 不能有大括号
                                                               //    {
                                                               //        return m * n + 2;
                                                               //    };
                                                               //Queryable    //a=>a.Id>3

    //表达式目录树:语法树,或者说是一种数据结构;可以被我们解析
    int iResult1 = func.Invoke(12, 23);
    int iResult2 = exp.Compile().Invoke(12, 23);//可以转换过去

    编译后生成代码

    image

    即下面这段

    ParameterExpression parameterExpression = Expression.Parameter(typeof(int), "m");    //声明参数表达式
    ParameterExpression parameterExpression2 = Expression.Parameter(typeof(int), "n");
    var mutiply = Expression.Multiply(parameterExpression, parameterExpression2);  //乘法表达式 m*n
    var constant = Expression.Constant(2, typeof(int));             //常量表达式
    var add = Expression.Add(mutiply, constant);                  //加法表达式

    Expression<Func<int, int, int>> expression =   //组合
         Expression.Lambda<Func<int, int, int>>(add, new ParameterExpression[] {
         parameterExpression,
         parameterExpression2
    });

    给出一个表达式 Expression<Func<People, bool>> lambda = x => x.Id.ToString().Equals("5");

    自己拼装表达式目录树

    {

                    ParameterExpression parameterExpression = Expression.Parameter(typeof(People), "x");
                     var field = Expression.Field(parameterExpression, typeof(People).GetField("Id"));
                     var toString = typeof(People).GetMethod("ToString");
                     var toStringCall = Expression.Call(field, toString, new Expression[0]);
                     var equals = typeof(People).GetMethod("Equals");
                     var constant = Expression.Constant("5", typeof(string));
                     var equalsCall = Expression.Call(toStringCall, equals, new Expression[] { constant });
                     Expression<Func<People, bool>> expression =
                         Expression.Lambda<Func<People, bool>>(equalsCall, new ParameterExpression[]
                             {
                             parameterExpression
                             });

                    expression.Compile().Invoke(new People()
                     {
                         Id = 11,
                         Name = "Eleven",
                         Age = 31
                     });
                 }

    表达式目录树作用是什么呢

    可以用来代替 反射 下面是 类型转换 测试反射与表达式树性能

    image

    static void Main(string[] args)
    {
         try
         {

            {
                 Console.WriteLine("********************MapperTest********************");
                 ExpressionTest.MapperTest();
             }
         }
         catch (Exception ex)
         {
             Console.WriteLine(ex.Message);
         }
         Console.Read();
    }

    /// <summary>
    /// 认识/拼装 表达式目录树
    /// 拼装表达式
    /// 应用
    /// </summary>
    public class ExpressionTest
    {
         public static void MapperTest()
         {
             People people = new People()
             {
                 Id = 11,
                 Name = "Eleven",
                 Age = 31
             };

            long common = 0;
             long generic = 0;
             long cache = 0;
             long reflection = 0;
             long serialize = 0;
             {
                 Stopwatch watch = new Stopwatch();
                 watch.Start();
                 for (int i = 0; i < 1000000; i++)
                 {
                     PeopleCopy peopleCopy = new PeopleCopy()
                     {
                         Id = people.Id,
                         Name = people.Name,
                         Age = people.Age
                     };
                 }
                 watch.Stop();
                 common = watch.ElapsedMilliseconds;
             }
             {
                 Stopwatch watch = new Stopwatch();
                 watch.Start();
                 for (int i = 0; i < 1000000; i++)
                 {
                     PeopleCopy peopleCopy = ReflectionMapper.Trans<People, PeopleCopy>(people);
                 }
                 watch.Stop();
                 reflection = watch.ElapsedMilliseconds;
             }
             {
                 Stopwatch watch = new Stopwatch();
                 watch.Start();
                 for (int i = 0; i < 1000000; i++)
                 {
                     PeopleCopy peopleCopy = SerializeMapper.Trans<People, PeopleCopy>(people);
                 }
                 watch.Stop();
                 serialize = watch.ElapsedMilliseconds;
             }
             {
                 Stopwatch watch = new Stopwatch();
                 watch.Start();
                 for (int i = 0; i < 1000000; i++)
                 {
                     PeopleCopy peopleCopy = ExpressionMapper.Trans<People, PeopleCopy>(people);
                 }
                 watch.Stop();
                 cache = watch.ElapsedMilliseconds;
             }
             {
                 Stopwatch watch = new Stopwatch();
                 watch.Start();
                 for (int i = 0; i < 1000000; i++)
                 {
                     PeopleCopy peopleCopy = ExpressionGenericMapper<People, PeopleCopy>.Trans(people);
                 }
                 watch.Stop();
                 generic = watch.ElapsedMilliseconds;
             }

            Console.WriteLine($"common = { common} ms");
             Console.WriteLine($"reflection = { reflection} ms");
             Console.WriteLine($"serialize = { serialize} ms");
             Console.WriteLine($"cache = { cache} ms");
             Console.WriteLine($"generic = { generic} ms");

        }


    }

    public class ReflectionMapper
    {
         /// <summary>
         /// 反射
         /// </summary>
         /// <typeparam name="TIn"></typeparam>
         /// <typeparam name="TOut"></typeparam>
         /// <param name="tIn"></param>
         /// <returns></returns>
         public static TOut Trans<TIn, TOut>(TIn tIn)
         {
             TOut tOut = Activator.CreateInstance<TOut>();
             foreach (var itemOut in tOut.GetType().GetProperties())
             {
                 var propIn = tIn.GetType().GetProperty(itemOut.Name);
                 itemOut.SetValue(tOut, propIn.GetValue(tIn));
             }
             foreach (var itemOut in tOut.GetType().GetFields())
             {
                 var fieldIn = tIn.GetType().GetField(itemOut.Name);
                 itemOut.SetValue(tOut, fieldIn.GetValue(tIn));
             }
             return tOut;
         }

        public static TOut Trans1<TIn, TOut>(TIn tIn)
         {
             TOut tOut = Activator.CreateInstance<TOut>();
             foreach (var prop in typeof(TOut).GetProperties())
             {
                 var val = tIn.GetType().GetProperty(prop.Name).GetValue(tIn);
                 prop.SetValue(tOut, val);
             }
             foreach (var field in typeof(TOut).GetFields())
             {
                 var val = tIn.GetType().GetField(field.Name).GetValue(tIn);
                 field.SetValue(tOut, val);
             }
             return tOut;
         }

    }

    /// <summary>
    /// 使用第三方序列化反序列化工具
    ///
    /// 还有automapper
    /// </summary>
    public class SerializeMapper
    {
         /// <summary>
         /// 序列化反序列化方式
         /// </summary>
         /// <typeparam name="TIn"></typeparam>
         /// <typeparam name="TOut"></typeparam>
         public static TOut Trans<TIn, TOut>(TIn tIn)
         {
             return JsonConvert.DeserializeObject<TOut>(JsonConvert.SerializeObject(tIn));
         }
    }

    /// <summary>
    /// 生成表达式目录树 缓存
    /// </summary>
    public class ExpressionMapper
    {
         private static Dictionary<string, object> _Dic = new Dictionary<string, object>();

        /// <summary>
         /// 字典缓存表达式树
         /// </summary>
         /// <typeparam name="TIn"></typeparam>
         /// <typeparam name="TOut"></typeparam>
         /// <param name="tIn"></param>
         /// <returns></returns>
         public static TOut Trans<TIn, TOut>(TIn tIn)
         {
             string key = string.Format("funckey_{0}_{1}", typeof(TIn).FullName, typeof(TOut).FullName);
             if (!_Dic.ContainsKey(key))
             {
                 ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
                 List<MemberBinding> memberBindingList = new List<MemberBinding>();
                 foreach (var item in typeof(TOut).GetProperties())
                 {
                     MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));
                     MemberBinding memberBinding = Expression.Bind(item, property);
                     memberBindingList.Add(memberBinding);
                 }
                 foreach (var item in typeof(TOut).GetFields())
                 {
                     MemberExpression property = Expression.Field(parameterExpression, typeof(TIn).GetField(item.Name));
                     MemberBinding memberBinding = Expression.Bind(item, property);
                     memberBindingList.Add(memberBinding);
                 }
                 MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray());
                 Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[]
                 {
                     parameterExpression
                 });
                 Func<TIn, TOut> func = lambda.Compile();//拼装是一次性的
                 _Dic[key] = func;
             }
             return ((Func<TIn, TOut>)_Dic[key]).Invoke(tIn);
         }
    }

         /// <summary>
         /// 生成表达式目录树  泛型缓存
         /// </summary>
         /// <typeparam name="TIn"></typeparam>
         /// <typeparam name="TOut"></typeparam>
         public class ExpressionGenericMapper<TIn, TOut>//Mapper`2
         {
             private static Func<TIn, TOut> _FUNC = null;
             static ExpressionGenericMapper()
             {
                 ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
                 List<MemberBinding> memberBindingList = new List<MemberBinding>();
                 foreach (var item in typeof(TOut).GetProperties())
                 {
                     MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));
                     MemberBinding memberBinding = Expression.Bind(item, property);
                     memberBindingList.Add(memberBinding);
                 }
                 foreach (var item in typeof(TOut).GetFields())
                 {
                     MemberExpression property = Expression.Field(parameterExpression, typeof(TIn).GetField(item.Name));
                     MemberBinding memberBinding = Expression.Bind(item, property);
                     memberBindingList.Add(memberBinding);
                 }
                 MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray());
                 Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[]
                 {
                         parameterExpression
                 });
                 _FUNC = lambda.Compile();//拼装是一次性的
             }
             public static TOut Trans(TIn t)
             {
                 return _FUNC(t);
             }
         }


    /// <summary>
    /// 实体类
    /// </summary>
    public class People
    {
         public int Age { get; set; }
         public string Name { get; set; }

        public int Id;
    }

    /// <summary>
    /// 实体类Target
    /// </summary>
    public class PeopleCopy
    {
         public int Age { get; set; }
         public string Name { get; set; }//ShortName

        public int Id;
    }

    疑问点: 这个委托放在 静态字典 与  静态泛型缓存 为什么差了1个数量级

    Dictionary<TKey, TValue>维护一个哈希表。

    它的枚举器将遍历散列表中的存储桶,直到找到一个非空的存储桶,然后返回该存储桶中的值。
    一旦字典变大,这个操作变得昂贵。


    而 泛型缓存    private static Func<TIn, TOut> _FUNC = null;

    如果 TIn, TOut 类型有变动, 会导产生不同的副本.

    简单描述下: TIn, TOut 类型有变动, 因为是泛型类  ExpressionGenericMapper<TIn, TOut>,会重新生成一个类, 并调用静态构造 给泛型缓存赋值, 变动前的泛型类,静态泛型缓存仍存在

  • 相关阅读:
    jQuery中的一些操作
    laravel使用消息队列
    Laravel的开发环境Homestead的搭建与配置
    python爬虫学习
    配置文件
    sql根据时间差查询数据
    Oracle根据连接字符串获取库下的表列表、获取表结构
    Sql根据连接字符串获取库下的表列表、获取表结构
    判断网络连接
    线程锁,解决多线程并发问题
  • 原文地址:https://www.cnblogs.com/xtxtx/p/9162123.html
Copyright © 2011-2022 走看看