概要
本文主要列舉出一些常用的運算式目錄樹實體,便于以此為基礎,構建更復雜的運算式目錄樹,以滿足各種多變的業務場景,
運算式目錄樹的構建,除了使用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)));
代碼執行流程為:
- 構建Lambda運算式中的變數s
- 構建運算式目錄樹s.FirstName
- 呼叫LambdaExpression的Lambda方法生成運算式: s => s.FirstName
- 呼叫LambdaExpression的Compile方法生成委托物件
- 委托物件呼叫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 = Expression.MemberInit(Expression.New(typeof(Student)), 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#泛型約束與無法創建帶引數的泛型實體的矛盾
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/239650.html
標籤:其他
