C#表达式目录树系列之2 --常见的表达式目录树的实例

概要

本文主要列举出一些常用的表达式目录树实例,便于以此为基础,构建更复杂的表达式目录树,以满足各种多变的业务场景。

表达式目录树的构建,除了使用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)));

代码执行流程为:

  1. 构建Lambda表达式中的变量s
  2. 构建表达式目录树s.FirstName
  3. 调用LambdaExpression的Lambda方法生成表达式: s => s.FirstName
  4. 调用LambdaExpression的Compile方法生成委托对象
  5. 委托对象调用Invoke方法,执行 s.FirstName代码。

访问嵌套对象属性

构建目标 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;
	}
}

表达式目录树系列全部文章

  • C#表达式目录树系列之1 – 表达式目录树基本概念
  • C#表达式目录树系列之2 – 常见的表达式目录树的实例
  • C#表达式目录树系列之3 – 为EF查询实现动态OrderBy
  • C#表达式目录树系列之4 – 解决C#泛型约束与无法创建带参数的泛型实例的矛盾
  • C#表达式目录树系列之5 – 动态创建查询表达式

你可能感兴趣的:(.Net,Core,C#基础,c#,后端)