本文主要列举出一些常用的表达式目录树实例,便于以此为基础,构建更复杂的表达式目录树,以满足各种多变的业务场景。
表达式目录树的构建,除了使用Expression类提供的静态方法外,一般还需要同反射结合在一起。例如通过反射找到类中具体定义的方法,通过反射找到类中的构造函数等。
Student类的定义详见附录。
构建目标 s => s.FirstName s是Student类型
代码如下:
ParameterExpression sParameter = Expression.Parameter(typeof(Student), "s");
MemberExpression firstNameExpression = Expression.Property(sParameter,typeof(Student).GetProperty("FirstName"));
LambdaExpression lengthLambdaExpression = Expression.Lambda<Func<Student,string>>(firstNameExpression,sParameter);
Console.WriteLine(lengthLambdaExpression);
var lengthDelegate = (Func<Student,string>) lengthLambdaExpression.Compile();
Console.WriteLine(lengthDelegate.Invoke(new Student("Tom","Green",14)));
代码执行流程为:
构建目标 s => s.FirstName.Length s是Student类型
ParameterExpression sParameter = Expression.Parameter(typeof(Student), "s");
MemberExpression firstNameExpression = Expression.Property(sParameter,typeof(Student).GetProperty("FirstName"));
MemberExpression lengthExpression = Expression.Property(firstNameExpression,typeof(string).GetProperty("Length"));
LambdaExpression lengthLambdaExpression = Expression.Lambda<Func<Student,int>>(lengthExpression,sParameter);
Console.WriteLine(lengthLambdaExpression);
var lengthDelegate = (Func<Student,int>) lengthLambdaExpression.Compile();
Console.WriteLine(lengthDelegate.Invoke(new Student("Tom","Green",14)));
构建目标: s => s.GetFullName() s是Student类型
ParameterExpression sParameter = Expression.Parameter(typeof(Student),"s");
MethodCallExpression getFullNameMethod = Expression.Call(
sParameter,
typeof(Student).GetMethod("GetFullName",new Type[]{}), // method
new Expression[] // Work method's parameter
{
}
);
LambdaExpression lambdaGetFullNameMethod = Expression.Lambda<Func<Student,string>>(getFullNameMethod,sParameter);
Console.WriteLine(lambdaGetFullNameMethod);
var lambdaGetFullNameDelegate = (Func<Student,string>) lambdaGetFullNameMethod.Compile();
Console.WriteLine(lambdaGetFullNameDelegate.Invoke(new Student("Tom", "Green", 13)));
构建目标:m => m.GetFullName(“Mr”) m是Student类型
ParameterExpression mParameter = Expression.Parameter(typeof(Student),"m");
string prefix = "Mr";
MethodCallExpression getFullNameMethod = Expression.Call(
mParameter,
typeof(Student).GetMethod("GetFullName", new Type[]{typeof(string)}), // method
new Expression[] // Work method's parameter
{
Expression.Constant(prefix)
}
);
LambdaExpression lambdaGetFullNameMethod = Expression.Lambda<Func<Student,string>>(getFullNameMethod,mParameter);
Console.WriteLine(lambdaGetFullNameMethod);
var lambdaGetFullNameDelegate = (Func<Student,string>) lambdaGetFullNameMethod.Compile();
Console.WriteLine(lambdaGetFullNameDelegate.Invoke(new Student("Tom", "Green", 13)));
调用string类的Concat方法实现字符串拼接。
构建目标:c => Concat(c.FirstName, c.LastName) c是Student类型
ParameterExpression cParameter = Expression.Parameter(typeof(Student),"c");
MemberExpression firstNameExpression = Expression.Property(cParameter, typeof(Student).GetProperty("FirstName"));
MemberExpression lastNameExpression = Expression.Property(cParameter, typeof(Student).GetProperty("LastName"));
MethodCallExpression ConcatMethod = Expression.Call(
typeof(string).GetMethod("Concat", BindingFlags.Public | BindingFlags.Static, null, CallingConventions.Any, new Type[]{typeof(string),typeof(string)}, null), // method
new Expression[] // Work method's parameter
{
firstNameExpression,
lastNameExpression
}
);
LambdaExpression lambdaConcatMethod = Expression.Lambda<Func<Student,string>>(ConcatMethod,cParameter);
Console.WriteLine(lambdaConcatMethod);
var lambdaConcatDelegate = (Func<Student,string>) lambdaConcatMethod.Compile();
Console.WriteLine(lambdaConcatDelegate.Invoke(new Student("Tom", "Green", 13)));
构建目标:(n, l, m) => new Student(n, l, m)
n,l为string类型,m是int类型
ParameterExpression n = Expression.Parameter(typeof(string),"n");
ParameterExpression l = Expression.Parameter(typeof(string),"l");
ParameterExpression m = Expression.Parameter(typeof(int),"m");
ConstructorInfo ctor = typeof(Student).GetConstructor(
BindingFlags.Instance | BindingFlags.Public,
null,
CallingConventions.HasThis,
new[] { typeof(string),typeof(string), typeof(int) }, new ParameterModifier[] {}
);
var expressionNew = Expression.New(ctor,new Expression[]{n,l,m});
LambdaExpression newLambda = Expression.Lambda<Func<string,string,int,Student>>(expressionNew, new ParameterExpression[]{n,l,m});
Console.WriteLine(newLambda);
var newDelegate = (Func<string,string,int,Student>) newLambda.Compile();
Console.WriteLine(newDelegate.Invoke("Tom","Green",13).GetFullName());
调用Student类的无参构造函数创建实例,并将已有Student实例中的属性值赋值给新创建的实例。
构建目标:r => new Student() {FirstName = r.FirstName, LastName = r.LastName, Age = r.Age} r为Student类型
Student stuResource = new Student("Jack", "Green",12);
ParameterExpression r = Expression.Parameter(typeof(Student),"r");
ConstructorInfo ctor = typeof(Student).GetConstructor(
BindingFlags.Instance | BindingFlags.Public,
null,
CallingConventions.HasThis,
new Type [] { }, new ParameterModifier[] {}
);
List<MemberBinding> bindings = new List<MemberBinding>();
foreach(PropertyInfo info in typeof(Student).GetProperties()){
MemberExpression rMember = Expression.Property(r,typeof(Student).GetProperty(info.Name));
MemberBinding binding = Expression.Bind(info,rMember);
bindings.Add(binding);
}
MemberInitExpression memberInitExpression = MemberInitExpression memberInitExpression = Expression.MemberInit( Expression.New(ctor, Array.Empty<Expression>()), bindings.ToArray());
LambdaExpression lambdaStudentNewExpression = Expression.Lambda<Func<Student,Student>>(memberInitExpression,r);
Console.WriteLine(lambdaStudentNewExpression);
var lambdaStudentNewDelegate = (Func<Student,Student>) lambdaStudentNewExpression.Compile();
Console.WriteLine(lambdaStudentNewDelegate.Invoke(stuResource).GetFullName());
构建目标: c => Concat(c.GetFullName(), c.LastName) c为Student类型
ParameterExpression cParameter = Expression.Parameter(typeof(Student),"c");
MethodCallExpression getFullNameMethod = Expression.Call(
cParameter,
typeof(Student).GetMethod("GetFullName", new Type[]{}, null), // method
new Expression[] // Work method's parameter
{
}
);
MemberExpression lastNameExpression = Expression.Property(cParameter, typeof(Student).GetProperty("LastName"));
MethodCallExpression ConcatMethod = Expression.Call(
typeof(string).GetMethod("Concat", BindingFlags.Public | BindingFlags.Static, null, CallingConventions.Any, new Type[]{typeof(string),typeof(string)}, null), // method
new Expression[] // Work method's parameter
{
getFullNameMethod,
lastNameExpression
}
);
LambdaExpression lambdaConcatMethod = Expression.Lambda<Func<Student,string>>(ConcatMethod, cParameter);
Console.WriteLine(lambdaConcatMethod);
var lambdaConcatDelegate = (Func<Student,string>) lambdaConcatMethod.Compile();
Console.WriteLine(lambdaConcatDelegate.Invoke(new Student("Tom", "Green", 13)));
public class Student {
public Student(string firstName, string lastName, int age){
this.FirstName = firstName;
this.LastName = lastName;
this.Age = age;
}
public Student(){
}
public string FirstName {get;set;}
public string LastName {get;set;}
public int Age {get;set;}
public string GetFullName(){
return FirstName + ", " + LastName;
}
public string GetFullName(string prefix){
return prefix + " " + FirstName + ", " + LastName;
}
}