[英]How can I put a property to linq expression at runtime?
I need to pass property name to the "GetClientsByFilter()" method via string parameter "propertyName" and use this property in LINQ expression. 我需要通过字符串参数“ propertyName”将属性名称传递给“ GetClientsByFilter()”方法,并在LINQ表达式中使用此属性。
It is assumed that there is need to use reflection. 假定需要使用反射。
Do you have any idea what I have to use instead string that with comment "//pseudo code" below? 您是否知道我必须在下面使用带注释“ // pseudo code”的字符串代替什么? Thanks. 谢谢。
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;
}
}
You can pass instead of property yet another lambda which gets the property value: 您可以传递另一个获取属性值的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;
}
Unfortunately, this approach cannot be used when you get the property name from "outside" and cannot build the proper lambda for getting the value. 不幸的是,当您从“外部”获取属性名称时,无法使用此方法,并且无法构建适当的lambda来获取值。 In such case you can prepare a dictionary of lambdas for each property name. 在这种情况下,您可以为每个属性名称准备一个lambda字典。
If you want to use reflection, please see the answer here 如果要使用反射,请在此处查看答案
I have solved this problem like this: 我已经解决了这样的问题:
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;
}
But I want to rewrite this code and will make it more clearly without copy/paste 但是我想重写这段代码,并且无需复制/粘贴即可使其更加清晰
This is an almost-duplicate question of " How do I create an expression tree to represent 'String.Contains("term")' in C#? ." 这是一个几乎重复的问题,“ 如何在C#中创建一个表达式树来表示'String.Contains(“ term”)'?” 。 Marc's answer provides this bit of code to build an expression, which is what you are looking for: 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);
}
...and now using it from your method: ...现在从您的方法中使用它:
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;
} }
Since "GetExpression" is generic, you can easily reuse this for other types besides just Client
. 由于“ GetExpression”是通用的,因此除了Client
之外,您还可以轻松地将其重用于其他类型。 Consider renaming the method since "GetExpression" doesn't spell out your intent - maybe something like "GetPropertyContainsExpression". 考虑重命名该方法,因为“ GetExpression”并不能说明您的意图,例如“ GetPropertyContainsExpression”之类的东西。 You might also consider adding some error handling to that method in case the value in propertyName is not a valid property on the type and when the property specified isn't of type string
which probably wouldn't have a Contains
method that takes a string. 如果propertyName中的值不是该类型上的有效属性,并且当指定的属性不是string
类型(可能没有采用字符串的Contains
方法)时,您也可以考虑对该方法添加一些错误处理。 These sorts of errors might be hard to figure out from the exceptions the expression builder might throw at run time. 从表达式构建器在运行时可能引发的异常中,可能很难弄清这些错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.