System.Linq.Expressions 命名空间
System.Linq.Expressions 命名空间包含一些类、接口和枚举,它们使语言级别的代码表达式能够表示为表达式目录树形式的对象。
抽象类 Expression 可提供用于对表达式目录树进行建模的类层次结构的根目录。
从 Expression 派生的此命名空间中的类(例如 MemberExpression 和 ParameterExpression)用于表示表达式目录树中的节点。Expression 类包含 static(在 Visual Basic 中为 Shared)工厂方法,可创建各种类型的表达式目录树节点。
枚举类型 ExpressionType (Add, and, Call 等表示表达式的动作类型)指定唯一节点类型。
常用的类
BinaryExpression | 表示包含二元运算符的表达式。 | |
ConditionalExpression | 表示包含条件运算符的表达式。 | |
ConstantExpression | 表示具有常量值的表达式。 | |
abstract | Expression | 提供一种基类,表示表达式树节点的类派生自该基类。它还包含用来创建各种节点类型的 static(在 Visual Basic 中为 Shared)工厂方法 |
MemberExpression | 表示访问字段或属性。 | |
MethodCallExpression | 表示对静态方法或实例方法的调用。 | |
NewExpression | 表示构造函数调用。 | |
UnaryExpression | 表示包含一元运算符的表达式。 | |
ParameterExpression | 变量, 参数表达式 |
3 //常数表达式
a //变量或参数表达式
!a //一元逻辑非表达式
a + b //二元加法表达式
Math.Sin(a) //方法调用表达式
new StringBuilder() //new 表达式
public class MyExpression
{
public string _str;
public int _int;
public string Name { get; set; }
public MyExpression() { }
public MyExpression(string str) {
_str = str;
}
/// <summary>
/// 创建 a+2+3表达式.
///分解动作. (a+2)+3. ==> (变量 二元操作符+ 常量) 二元操作符+ 常量.
/// </summary>
/// <returns></returns>
public static Func<int, int> Expression1()
{
ParameterExpression param = System.Linq.Expressions.Expression.Parameter(typeof(System.Int32), "a");
//这样
BinaryExpression plus1 = Expression.MakeBinary(ExpressionType.Add, param,
Expression.Constant(2));
BinaryExpression plus2 = Expression.MakeBinary(ExpressionType.Add, plus1,
Expression.Constant(3));
//或者这样
//ConstantExpression con1 = Expression.Constant(2);
//ConstantExpression con2 = Expression.Constant(3);
//BinaryExpression plus1 = Expression.Add(param, con1);
//BinaryExpression plus2 = Expression.Add(plus1, con2);
//编译成委托
Expression<Func<int, int>> lam = Expression.Lambda<Func<int, int>>(plus2, param);
return lam.Compile(); ;
}
public static int ToDouble(int Number) {
return Number * Number;
}
public int ToDouble_Instance(int Number)
{
return Number * Number;
}
/// <summary>
/// 调用静态方法MyExpression.ToDouble方法
/// </summary>
/// <returns></returns>
public static Func<int, int> Expression2() {
//创建参数
ParameterExpression param = Expression.Parameter(typeof(int),"number");
//调用方法
MethodCallExpression method = Expression.Call(typeof(MyExpression).GetMethod("ToDouble"), param);
return Expression.Lambda<Func<int, int>>(method, param).Compile(); ;
}
/// <summary>
/// 调用动态方法MyExpression.ToDouble方法
/// </summary>
/// <returns></returns>
public static Func<int, int> Expression3()
{
//创建参数
ParameterExpression param = Expression.Parameter(typeof(int), "number");
//调用方法
MethodCallExpression method = Expression.Call(typeof(MyExpression).GetMethod("ToDouble_Instance"), param);
return Expression.Lambda<Func<int, int>>(method, param).Compile(); ;
}
/// <summary>
/// 实例化
/// </summary>
/// <returns></returns>
public static Func<string,T> CreateInstance<T>() where T: class {
//创建参数
ParameterExpression param = Expression.Parameter(typeof(string), "str");
//调用方法
var exp = Expression.New(typeof(T).GetConstructor(new Type[] { typeof(string) }), param);
return Expression.Lambda<Func<string, T>>(exp, param).Compile();
}
/// <summary>
/// 创建new int[] { a, b, a + b}数组
/// </summary>
/// <returns></returns>
public static Func<int, int, int[]> createIntArray()
{
ParameterExpression a = Expression.Parameter(typeof(int), "a");
ParameterExpression b = Expression.Parameter(typeof(int), "b");
BinaryExpression aPlusb = Expression.MakeBinary(ExpressionType.Add, a, b);
var exp = Expression.NewArrayInit(typeof(int), a, b, aPlusb);
ParameterExpression[] parm = { a,b};
return Expression.Lambda<Func<int, int, int[]>>(exp, parm).Compile();
}
/// <summary>
/// a.Length>3 | b>0
/// </summary>
/// <returns></returns>
public static Func<string, int, bool> createBool() {
ParameterExpression a = Expression.Parameter(typeof(string), "a");
var property = Expression.PropertyOrField(a, "Length");
var exp1 = Expression.MakeBinary(ExpressionType.GreaterThan, property, Expression.Constant(3));
ParameterExpression b = Expression.Parameter(typeof(int), "b");
var exp2 = Expression.MakeBinary(ExpressionType.GreaterThan, b, Expression.Constant(0));
var or = Expression.MakeBinary(ExpressionType.Or, exp1, exp2);
return Expression.Lambda<Func<string, int, bool>>(or,a,b).Compile();
}
public static IQueryable<T> Order<T>(IQueryable<T> query, string field)
{
ParameterExpression x = Expression.Parameter(typeof(T), "x");
var property = Expression.Property(x, field);
PropertyInfo pi = typeof(T).GetProperty(field);
Type[] types = new Type[2];
types[0] = typeof(T);
types[1] = pi.PropertyType;
var lambda = Expression.Lambda(property, x);
var exp = query.AsQueryable().Expression;
MethodCallExpression call = Expression.Call(typeof(Queryable), "OrderBy", types,exp, lambda);
return query.AsQueryable().Provider.CreateQuery<T>(call);
}
/// <summary>
/// 实例化2
/// </summary>
/// <returns></returns>
public static Func<object> CreateInstance(string classpath)
{
//调用方法
var exp = Expression.New(Type.GetType(classpath).GetConstructor(Type.EmptyTypes));
return Expression.Lambda<Func<object>>(exp).Compile();
}
}
特别需要注意的是, linq动态查询, 最后call方法, 需要加上原有的表达式, 这个暂时不理解
static void Main(string[] args)
{
Expression<Func<int, int, int>> expression = (a, b) => a + b;
var per=MyExpression.Expression2();
Console.WriteLine("调用静态方法:" + per(5));
Console.WriteLine("调用动态方法:" + MyExpression.Expression2()(10));
MyExpression exp = MyExpression.CreateInstance<MyExpression>()("jianjialin");
Console.WriteLine("创建对象:" + exp._str + " " + MyExpression.CreateInstance<MyExpression>().ToString());
Console.WriteLine("创建数组:" + MyExpression.createIntArray()(2,3)[2]);
Console.WriteLine("a.Length>3 | b>0的表达式"+MyExpression.createBool()("abcd",-2));
IList<Student> lst = new List<Student> {
new Student{ Name="刘备",Age=40},
new Student{ Name="张飞",Age=20},
new Student{ Name="关羽",Age=30}
};
Console.ReadKey();
}