[英]How can I put a property to linq expression at runtime?
我需要通過字符串參數“ propertyName”將屬性名稱傳遞給“ GetClientsByFilter()”方法,並在LINQ表達式中使用此屬性。
假定需要使用反射。
您是否知道我必須在下面使用帶注釋“ // pseudo code”的字符串代替什么? 謝謝。
public class Client
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
internal class DataLayer
{
public static List<Client> GetClientsByFilter(string search, string propertyName)
{
//it's Entity Framework context
using (var dbContext = new LibDbContext())
{
List<Client> clients;
clients = dbContext.Clients
.Where(item => item.[propertyName].Contains(search)) // pseudo code
.ToList();
}
return clients;
}
}
您可以傳遞另一個獲取屬性值的lambda而不是屬性:
public static List<Client> GetClientsByFilter(string search,
Func<Client, string> propertyGetter)
{
//it's Entity Framework context
using (var dbContext = new LibDbContext())
{
List<Client> clients;
clients = dbContext.Clients
.Where(item => propertyGetter(item).Contains(search))
.ToList();
}
return clients;
}
不幸的是,當您從“外部”獲取屬性名稱時,無法使用此方法,並且無法構建適當的lambda來獲取值。 在這種情況下,您可以為每個屬性名稱准備一個lambda字典。
如果要使用反射,請在此處查看答案
我已經解決了這樣的問題:
public static List<Client> GetClientsByFilter(string search, string propertyName)
{
using (var dbContext = new LibDbContext())
{
List<Client> clients;
switch (propertyName)
{
case "LastName":
clients = dbContext.Clients
.Where(item => item.LastName.Contains(search))
.ToList();
break;
case "FirstName":
clients = dbContext.Clients
.Where(item => item.FirstName.Contains(search))
.ToList();
break;
}
return clients;
}
但是我想重寫這段代碼,並且無需復制/粘貼即可使其更加清晰
這是一個幾乎重復的問題,“ 如何在C#中創建一個表達式樹來表示'String.Contains(“ term”)'?” 。 Marc的答案提供了以下代碼來構建表達式,這就是您要查找的內容:
static Expression<Func<T, bool>> GetExpression<T>(string propertyName, string propertyValue)
{
var parameterExp = Expression.Parameter(typeof(T), "type");
var propertyExp = Expression.Property(parameterExp, propertyName);
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
var someValue = Expression.Constant(propertyValue, typeof(string));
var containsMethodExp = Expression.Call(propertyExp, method, someValue);
return Expression.Lambda<Func<T, bool>>(containsMethodExp, parameterExp);
}
...現在從您的方法中使用它:
public static List<Client> GetClientsByFilter(string search, string propertyName)
{
//it's Entity Framework context
using (var dbContext = new LibDbContext())
{
List<Client> clients;
clients = dbContext.Clients
.Where(GetExpression<Client>(propertyName, search)) // Now using Marc's method
.ToList();
}
return clients;
}
由於“ GetExpression”是通用的,因此除了Client
之外,您還可以輕松地將其重用於其他類型。 考慮重命名該方法,因為“ GetExpression”並不能說明您的意圖,例如“ GetPropertyContainsExpression”之類的東西。 如果propertyName中的值不是該類型上的有效屬性,並且當指定的屬性不是string
類型(可能沒有采用字符串的Contains
方法)時,您也可以考慮對該方法添加一些錯誤處理。 從表達式構建器在運行時可能引發的異常中,可能很難弄清這些錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.