表达式简述:
表达式目录树以数据形式表示语言级别代码。数据存储在树形结构中。表达式目录树中的每个节点都表示一个表达式.(来自MSDN)
先用表API生成一个简单方法 : int add(int a,int b){return a+b);
ParameterExpression p1 = Expression.Parameter(typeof (int), "a"); ParameterExpression p2 = Expression.Parameter(typeof(int), "b"); BinaryExpression add = Expression.Add(p1, p2);
上面表达式的创建已经完成。
表达式的执行:
MSDN上讲 :只能执行表示 lambda 表达式的表达式树。 表示 lambda 表达式的表达式树属于 LambdaExpression 或 Expression<TDelegate> 类型。 若要执行这些表达式树,需要调用 Compile 方法来创建一个可执行委托,然后调用该委托。
如果表达式树不表示一个 lambda 表达式,则可以通过调用 Lambda<TDelegate>(Expression, IEnumerable<ParameterExpression>) 方法,创建一个以原始表达式树作为其主体的新 lambda 表达式。 然后,即可按照本节前面所述执行该 lambda 表达式。
Expression<Func<int, int, int>> excute = Expression.Lambda<Func<int, int, int>>(add,new ParameterExpression[]{p1,p2}); Func<int, int, int> fc=excute.Compile();
调用委托 既可以执行我们创建的表达式树。
方法调用:
对于下面此方法调用
class Program { public void MethodEx(int a, int b,int c) { } } NewExpression nty = Expression.New(typeof(Program)); List<ParameterExpression> p = new List<ParameterExpression> { Expression.Parameter(typeof(int),"a"), Expression.Parameter(typeof(int),"b"), Expression.Parameter(typeof(int),"c") }; MethodCallExpression mc = Expression.Call(nty, typeof(Program).GetMethod("MethodEx"), p); var sd = Expression.Lambda(mc, p); var s = sd.Compile();
更通用的方法调用:
public static Delegate CreateDelegate(MethodInfo methodInfo) { if (methodInfo == null) throw new ArgumentNullException("Error"); var parameters = methodInfo.GetParameters(); var paramExpressions = new List<ParameterExpression>(); int i = 0; foreach (var p in parameters) { paramExpressions.Add(Expression.Parameter(p.ParameterType, i.ToString())); ++i; } MethodCallExpression callExpression=null; if (methodInfo.IsStatic) { callExpression = Expression.Call(methodInfo, paramExpressions); } else { var instanceExpression = Expression.New(methodInfo.ReflectedType); callExpression = Expression.Call(instanceExpression, methodInfo, paramExpressions); } var lambdaExpression = Expression.Lambda(callExpression, paramExpressions); return lambdaExpression.Compile(); }
调用: var d = CreateDelegate(typeof(Program).GetMethod("MethodEx"));
对于方法的反射调用,可以使用上面表达式树替换