沒有指定MYTBL的類型,
所以我創建了只使用一個簡單的解決方案對象列表。
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;
namespace Test
{
class Program
{
static void Main(string[] args) {
var adresses = FilterByAddress("Address", new List<Person> { new Person { Address = "Address1" }, new Person { Address = "AAAAAA" } });
}
public static IEnumerable<Person> FilterByAddress(string strToCheck, List<Person> list) {
var listParam = Expression.Parameter(typeof(IEnumerable<Person>), "list");
Expression<Func<Person, bool>> contains = a => a.Address.Contains(strToCheck);
var select = typeof(Enumerable).GetMethods().Single(m => m.Name.Equals("Where") && m.GetParameters()[1].ParameterType.GetGenericArguments().Length == 2);
var genericMethod = select.MakeGenericMethod(new[] { typeof(Person) });
var call = Expression.Call(null, genericMethod, new Expression[] { listParam, contains });
var lambda = Expression.Lambda<Func<IEnumerable<Person>, IEnumerable<Person>>>(call, new[] { listParam });
return lambda.Compile().Invoke(list);
}
}
public class Person
{
public string Address { get; set; }
}
}
如果要通過謂詞使用過濾器可以傳遞一個Expresssion<Func<Person, bool>>
作爲參數(一行)
static void Main(string[] args) {
var strToCheck = "Address";
var list = new List<Person> { new Person { Address = "Address1" }, new Person { Address = "AAAAAA" } };
var adresses = FilterByAddress(list, p => p.Address.Contains(strToCheck));
}
public static IEnumerable<Person> FilterByAddress(List<Person> list, Expression<Func<Person, bool>> predicateEx) {
var listParam = Expression.Parameter(typeof(IEnumerable<Person>), "list");
var select = typeof(Enumerable).GetMethods().Single(m => m.Name.Equals("Where") && m.GetParameters()[1].ParameterType.GetGenericArguments().Length == 2);
var genericMethod = select.MakeGenericMethod(new[] { typeof(Person) });
var call = Expression.Call(null, genericMethod, new Expression[] { listParam, predicateEx });
var lambda = Expression.Lambda<Func<IEnumerable<Person>, IEnumerable<Person>>>(call, new[] { listParam });
return lambda.Compile().Invoke(list);
}
如果你有一個非常compilicated謂詞跨越到多行(一個表達式樹可以從一條線拉姆達進行評估),可以使用一個特技構建表達樹出謂詞的函數功能是這樣的:
static void Main(string[] args) {
var strToCheck = "Address";
Func<Person, bool> predicate = p => {
return p.Address.Contains(strToCheck);
};
var list = new List<Person> { new Person { Address = "Address1" }, new Person { Address = "AAAAAA" } };
var adresses = FilterByAddress(list, predicate);
}
public static IEnumerable<Person> FilterByAddress(List<Person> list, Func<Person, bool> predicate) {
var listParam = Expression.Parameter(typeof(IEnumerable<Person>), "list");
Expression<Func<Person, bool>> predicateEx = p => predicate(p);
var select = typeof(Enumerable).GetMethods().Single(m => m.Name.Equals("Where") && m.GetParameters()[1].ParameterType.GetGenericArguments().Length == 2);
var genericMethod = select.MakeGenericMethod(new[] { typeof(Person) });
var call = Expression.Call(null, genericMethod, new Expression[] { listParam, predicateEx });
var lambda = Expression.Lambda<Func<IEnumerable<Person>, IEnumerable<Person>>>(call, new[] { listParam });
return lambda.Compile().Invoke(list);
}
使用通用的方法,通過謂詞來篩選列表
static void Main(string[] args) {
var strToCheck = "Address";
Func<Person, bool> predicate = p => {
return p.Address.Contains(strToCheck);
};
var list = new List<Person> { new Person { Address = "Address1" }, new Person { Address = "AAAAAA" } };
var adresses = FilterBy<Person>(list, predicate);
}
public static IEnumerable<T> FilterBy<T>(List<T> list, Func<T, bool> predicate) {
var listParam = Expression.Parameter(typeof(IEnumerable<T>), "list");
Expression<Func<T, bool>> predicateEx = p => predicate(p);
var select = typeof(Enumerable).GetMethods().Single(m => m.Name.Equals("Where") && m.GetParameters()[1].ParameterType.GetGenericArguments().Length == 2);
var genericMethod = select.MakeGenericMethod(new[] { typeof(T) });
var call = Expression.Call(null, genericMethod, new Expression[] { listParam, predicateEx });
var lambda = Expression.Lambda<Func<IEnumerable<T>, IEnumerable<T>>>(call, new[] { listParam });
return lambda.Compile().Invoke(list);
}
}
是什麼轉換之間的區別' 。選擇()'到表達式樹和'.Contains()'到表達式樹?沒有。所以如果你知道如何轉換'Select',你應該知道如何轉換'Contains'。 –
謝謝。但我對錶達樹並不陌生,因此沒有多少資源。如果你知道答案,請幫我 – Arian
SO包含很多例子,如何編寫調用某種方法的表達式樹,例如'Any'' Where'等等。你可以查看幾個例子:[第一](https://stackoverflow.com/questions/45887790/access-childrenlist-related-property-in-expression-tree)和[second](https://stackoverflow.com/問題/ 45765350 /創建謂上帶有一個含binaryexpression- - 多參數)。主要思想是你從相應的'MethodInfo'創建'MethodCallExpression'。順便說一下,爲什麼你想將你的例子轉換成'ExpressionTree'? –