C# Expression表达式目录树

Expression就是表达式目录树,是以树形数据结构表示代码,其中每一个节点都是一种表达式。

用lambda表达式来创建一个简单的Expression

使用lambda表达式,编译器在生成IL时会帮我们拼装表达式目录树,示例:

Expression> expr = (a, b) => a * b + 3;

调试查看表达式的结构:

C# Expression表达式目录树_第1张图片

由图片可以看出,表达式目录树它是以优先级最低那个运算符为根节点,然后再分左右节点,这样子记录数据的。可以用一个二叉树的结构来表示一下:

C# Expression表达式目录树_第2张图片

手动拼装表达式目录树
ParameterExpression Left_a = Expression.Parameter(typeof(int), "a");//Left: ExpressionParameter
ParameterExpression Right_b = Expression.Parameter(typeof(int), "b");//Right: ExpressionParameter
var Right_3 = Expression.Constant(3);//Right:ExpressionConstant
var Left_mutiply = Expression.Multiply(Left_a, Right_b);//Left : ExpressionMultiply
var plus = Expression.Add(Left_mutiply, Right_3);//ExpressionAdd

Expression> expression = Expression.Lambda>(plus, new ParameterExpression[] { Left_a, Right_b });
int expr_Result = expression.Compile().Invoke(2, 3);
Console.WriteLine(expr_Result);

/* Output:
9
*/
表达式目录树的简单应用

最直接的应用就是把数据库实体转成一些业务实体。如果循环赋值,工作量大。想要减少写的代码量,这时可以用表达式目录树来,也可以用反射来做,但反射远比不上表达式目录树。

两个实体:

public class User
{
    public int Id { get; set; }
    public int Age { get; set; }
    public string Name { get; set; }
}

public class UserDTO
{
    public int Id { get; set; }
    public int Age { get; set; }
    public string Name { get; set; }

    public string Work { get; set; }

}

封装表达式目录树,传入一个TIn对象,返回一个新TOut对象

public class ExpressionGenericMapper
{
    private static Func _FUNC = null;
    static ExpressionGenericMapper()
    {
        ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
        List memberBindingList = new List();
        foreach (var item in typeof(TOut).GetProperties())
        {
            var v = typeof(TIn).GetProperty(item.Name);
            if (v == null)
                break;

            MemberExpression property = Expression.Property(parameterExpression, v);
            MemberBinding memberBinding = Expression.Bind(item, property);
            memberBindingList.Add(memberBinding);
        }
        MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray());
        Expression> lambda = Expression.Lambda>(memberInitExpression, new ParameterExpression[]
        {
                parameterExpression
        });
        _FUNC = lambda.Compile();//拼装是一次性的
    }
    public static TOut Trans(TIn t)
    {
        return _FUNC(t);
    }
}

使用:

User user = new User()
{
    Id = 1,
    Name = "User",
    Age = 11
};

UserDTO userDTO = ExpressionGenericMapper.Trans(user);
userDTO.Work = "Programmer";

你可能感兴趣的:(.Net学习笔记)