C#中合并两个lambda表达式
生活随笔
收集整理的這篇文章主要介紹了
C#中合并两个lambda表达式
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
在LINQ中如何查詢條件不固定,如何合并兩個lambda表達式?其中一個方式是LINQ.Dynamic,關于LINQ.Dynamic的簡單使用可以參考這篇文章,還有一種方法是利用Expression表達式樹,有關表達式樹的介紹,可以看這篇文章。
測試代碼如下:
public class Phone {public string Country { get; set; }public string City { get; set; }public string Name { get; set; } } public class Person {public string Name { get; set; }public string Gender { get; set; }public int Age { get; set; }public List<Phone> Phones { get; set; }} static void Main(string[] args) {List<Person> PersonLists = new List<Person>(){new Person { Name = "張三",Age = 20,Gender = "男",Phones = new List<Phone> {new Phone { Country = "中國", City = "北京", Name = "小米" },new Phone { Country = "中國",City = "北京",Name = "華為"},new Phone { Country = "中國",City = "北京",Name = "聯想"},new Phone { Country = "中國",City = "臺北",Name = "魅族"},}},new Person { Name = "松下",Age = 30,Gender = "男",Phones = new List<Phone> {new Phone { Country = "日本",City = "東京",Name = "索尼"},new Phone { Country = "日本",City = "大阪",Name = "夏普"},new Phone { Country = "日本",City = "東京",Name = "松下"},}},new Person { Name = "克里斯",Age = 40,Gender = "男",Phones = new List<Phone> {new Phone { Country = "美國",City = "加州",Name = "蘋果"},new Phone { Country = "美國",City = "華盛頓",Name = "三星"},new Phone { Country = "美國",City = "華盛頓",Name = "HTC"}}}};Expression<Func<Person, bool>> lambdaone = ex => ex.Name.Equals("張三");Expression<Func<Person, bool>> lambdatwo = ex => ex.Age == 30;ParameterExpression pa = Expression.Parameter(typeof(Person), "ex");Expression<Func<Person,bool>> newEx = Expression.Lambda<Func<Person,bool>>(Expression.Or(lambdaone.Body, lambdatwo.Body), pa);var Lists = PersonLists.Where(newEx.Compile());Console.WriteLine();Console.Read(); }?在上述代碼中,我要構建一個滿足兩個條件的過濾查詢:名字叫張三或者年齡是30。運行結果如下:
結果報錯了,說明沒有想象的那么簡單。原因是即便我的命名是相同的,都是ex,但是兩個表達式本質并不是相同的參數ex ,我只是引用了兩個不同parameter的lambda表達式的body,然后將這兩個body強行給了另一個parameter,具體信息可以這篇文藏
這時候我們需要重寫ExpressionVisitor,代碼如下:
public class MyExpressionVisitor : ExpressionVisitor{public ParameterExpression _Parameter { get; set; }public MyExpressionVisitor(ParameterExpression Parameter){_Parameter = Parameter;}protected override Expression VisitParameter(ParameterExpression p){return _Parameter;}public override Expression Visit(Expression node){return base.Visit(node);//Visit會根據VisitParameter()方法返回的Expression修改這里的node變量}}修改調試代碼如下:
Expression<Func<Person, bool>> lambdaone = ex => ex.Name.Equals("張三"); Expression<Func<Person, bool>> lambdatwo = ex => ex.Age == 30; ParameterExpression pa = Expression.Parameter(typeof(Person), "ex"); MyExpressionVisitor visitor = new MyExpressionVisitor(pa);//統一參數類型 Expression bodyone = visitor.Visit(lambdaone.Body); Expression bodytwo = visitor.Visit(lambdatwo.Body); Expression<Func<Person, bool>> newEx = Expression.Lambda<Func<Person, bool>>(Expression.Or(bodyone, bodytwo), pa); var Lists = PersonLists.Where(newEx.Compile()); foreach (var List in Lists) {Console.WriteLine(List.Name); } Console.Read();從運行結果來看,是沒問題的
?
第二種方式是利用Expression.Invoke() ,代碼如下:
Expression<Func<Person, bool>> lambdaone = ex => ex.Name.Equals("張三"); Expression<Func<Person, bool>> lambdatwo = ex => ex.Age == 30; // 創建參數表達式 InvocationExpression invocation = Expression.Invoke(lambdaone, lambdatwo.Parameters.Cast<Expression>()); // 創建or運算 BinaryExpression binary = Expression.Or(lambdatwo.Body, invocation); // 生成lambda表達式 var exp = Expression.Lambda<Func<Person, bool>>(binary, lambdatwo.Parameters); var Lists = PersonLists.Where(exp.Compile()); foreach (var List in Lists) {Console.WriteLine(List.Name); } Console.Read();運行結果相同:
?
總結
以上是生活随笔為你收集整理的C#中合并两个lambda表达式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HashMap的put方法(Java7)
- 下一篇: 大工17秋《计算机文化基础》在线测试1,