在学习LINQ的时候碰到了解析表达式树的问题,书上的例子中入口参数为一个单一变量,这个在MSDN中给出了示例代码:
MSDN官方示例:
// Add the following using directive to your code file:
// using System.Linq.Expressions;
// Create an expression tree.
Expression<Func<int, bool>> exprTree = num => num <5;
// Decompose the expression tree.
ParameterExpression param = (ParameterExpression)exprTree.Parameters[0];
BinaryExpression operation = (BinaryExpression)exprTree.Body;
ParameterExpression left = (ParameterExpression)operation.Left;
ConstantExpression right = (ConstantExpression)operation.Right;
Console.WriteLine("Decomposed expression: {0} => {1} {2} {3}",
param.Name, left.Name, operation.NodeType, right.Value);
// This code produces the following output:
// Decomposed expression: num => num LessThan 5
// using System.Linq.Expressions;
// Create an expression tree.
Expression<Func<int, bool>> exprTree = num => num <5;
// Decompose the expression tree.
ParameterExpression param = (ParameterExpression)exprTree.Parameters[0];
BinaryExpression operation = (BinaryExpression)exprTree.Body;
ParameterExpression left = (ParameterExpression)operation.Left;
ConstantExpression right = (ConstantExpression)operation.Right;
Console.WriteLine("Decomposed expression: {0} => {1} {2} {3}",
param.Name, left.Name, operation.NodeType, right.Value);
// This code produces the following output:
// Decomposed expression: num => num LessThan 5
这里表达式的入口参数是一个int型的变量,表达式左边就是这个参数本身,右边是一个常量,因此用
ParameterExpression left = (ParameterExpression)operation.Left;
ConstantExpression right = (ConstantExpression)operation.Right;
来解析即可,但如果入口是一个实体呢,这种情况很常见,应该怎么解析呢,通过向高人请教,最后用编译表达式树终于解决了这个问题:
//实体类
public class T
{
public int ID { get; set; }
public string Name { get; set; }
}
//解析表达式树类
public class Test
{
public void ExpressionTest(Expression<Func<T, bool>> exprTree)
{
ParameterExpression param = (ParameterExpression)exprTree.Parameters[0];
BinaryExpression operation = (BinaryExpression)exprTree.Body;
MemberExpression left = (MemberExpression)operation.Left;
MemberExpression right = (MemberExpression)operation.Right;
var result=Expression.Lambda(right).Compile().DynamicInvoke();
Console.WriteLine("Decomposed expression:{0}=>{1} {2} {3}",
param.Name,left.Member.Name,operation.NodeType,result.ToString());
}
}
//调用
public class Program
{
static void Main(string[] args)
{
Test test = new Test();
T t = new T() { ID = 1, Name = "abc" };
test.ExpressionTest(o => o.ID == t.ID);
test.ExpressionTest(o => o.Name == t.Name);
Console.Read();
}
}
public class T
{
public int ID { get; set; }
public string Name { get; set; }
}
//解析表达式树类
public class Test
{
public void ExpressionTest(Expression<Func<T, bool>> exprTree)
{
ParameterExpression param = (ParameterExpression)exprTree.Parameters[0];
BinaryExpression operation = (BinaryExpression)exprTree.Body;
MemberExpression left = (MemberExpression)operation.Left;
MemberExpression right = (MemberExpression)operation.Right;
var result=Expression.Lambda(right).Compile().DynamicInvoke();
Console.WriteLine("Decomposed expression:{0}=>{1} {2} {3}",
param.Name,left.Member.Name,operation.NodeType,result.ToString());
}
}
//调用
public class Program
{
static void Main(string[] args)
{
Test test = new Test();
T t = new T() { ID = 1, Name = "abc" };
test.ExpressionTest(o => o.ID == t.ID);
test.ExpressionTest(o => o.Name == t.Name);
Console.Read();
}
}
运行结果如下:
园子中有位朋友提供了另外一种方法(http://home.cnblogs.com/q/22976/),不过那个方法有一定缺陷,要依赖于实体类型,如果像上面代码中那样把表达式做为一个参数就无能为力了。