C#ORM中的对象映射

使用Linq.Expressions来动态生成映射方法

  1.我们先写个简单的类Test,包含一个ID和Name。

public class Test
{
   public int? ID { get; set; }
   public string Name { get; set; }
 }

  2.需要手工写简单映射代码,暂时不考虑大小写等问题,代码如下。

        /// <summary>
        /// 设置属性
        /// </summary>
        static void Set(Test t,string name,object value)
        {
            switch (name)
            {
                case "ID":t.ID = Convert.ToInt32(value);break;
                case "Name": t.Name = Convert.ToString(value); break;
            }
        }
        /// <summary>
        /// 获取属性
        /// </summary>
        static Object Get(Test t, string name)
        {
            switch (name)
            {
                case "ID": return t.ID;
                case "Name": return t.Name;
            }
            return null;
        }

  3.目标就是通过Expressions来自动产生上面2个方法,先定义Set方法的3个参数Test ,name,value(不了解Expressions点击

ParameterExpression val = Expression.Parameter(typeof(object));//value
ParameterExpression instance = Expression.Parameter(typeof(object));//Test 
ParameterExpression nameexp = Expression.Parameter(typeof(string));//name

   4.通过反射得到所有的属性集合,再根据属性集合产生case 语句,以下为Set方法的表达式

var ps = t.GetProperties();//t为typeof(Test)
List<SwitchCase> lt = new List<SwitchCase>();
foreach (var n in ps)
  {
     if (!n.CanWrite) { continue; }
     Expression tp = Expression.Convert(val, n.PropertyType); //类型转换,此为隐式转换。目前不考虑强行转换类型
     lt.Add(Expression.SwitchCase(Expression.Call(Expression.Convert(instance, t), n.GetSetMethod(), tp), Expression.Constant(n.Name)));
 }
 Expression p1 = Expression.Switch(nameexp, lt.ToArray());
LambdaExpression exp = Expression.Lambda(p1, instance, nameexp, val);//转换为LambdaExpression 后就可以编译了
Action<object, string, object> act = exp.Compile() as Action<object, string, object>;

  5.Get方法的表达式

var ps = t.GetProperties();
List<SwitchCase> lt = new List<SwitchCase>();
ParameterExpression instance = Expression.Parameter(typeof(object));
ParameterExpression nameexp = Expression.Parameter(typeof(string));
foreach (var n in ps)
  {
     if (!n.CanRead) { continue; }
     lt.Add(Expression.SwitchCase(Expression.Convert(Expression.Call(Expression.Convert(instance, t), n.GetGetMethod(), null), typeof(object)), Expression.Constant(n.Name)));
  }
Expression p1 = Expression.Switch(nameexp, Expression.Constant(null), lt.ToArray());
LambdaExpression exp = Expression.Lambda(p1, instance, nameexp);
Func<object, string, object> func = exp.Compile() as Func<object, string, object>;

  以上只是简单的案例代码,用于说明Expression来产生映射代码,查看完整代码,虽然更多人用Emit,但本质是一样。

原文地址:https://www.cnblogs.com/xuzhiqiang/p/9495213.html