C# 创建与LINQ到SQL兼容的表达式,该表达式通过属性名称访问属性

C# 创建与LINQ到SQL兼容的表达式,该表达式通过属性名称访问属性,c#,linq,reflection,linq-to-sql,C#,Linq,Reflection,Linq To Sql,我想知道你们中是否有人对如何解决这个问题有想法 假设有下面的类 public class Person { public string Description {get; set;} //... } 我想创建一个表达式,该表达式可以传递到LINQ to SQL中LINQ的Where方法中的LINQ的Where方法,例如: Expression<Func<Person, bool>> expression = x => x.Description.C

我想知道你们中是否有人对如何解决这个问题有想法

假设有下面的类

public class Person
{
    public string Description {get; set;}
    //...
}
我想创建一个表达式,该表达式可以传递到LINQ to SQL中LINQ的
Where
方法中的LINQ的
Where
方法,例如:

Expression<Func<Person, bool>> expression = x => x.Description.Contains("foo");
Expression=x=>x.Description.Contains(“foo”);

这里真正的问题是,在运行时之前,我不知道要检查哪个字段。属性的名称以字符串形式提供(在本例中,它将是“Description”,但可以是“Description2”,也可以是
Person
类的任何其他属性)。我不能直接在表达式本身中使用反射来获取属性值(通过使用
GetType
GetProperty
等),因为表达式在LINQ to SQL中传递到
Where
时无法工作,因为它无法转换为SQL代码。提前谢谢

看看这个最小的示例,所需的属性将被访问并与另一个字符串进行比较,结果是一个布尔值:

// GET: People
public ActionResult Index()
{
    var propertyName = "Description";
    var compareString = "abc";

    var parameter = Expression.Parameter(typeof(Person));
    var memberAccess = Expression.MakeMemberAccess(parameter, typeof(Person).GetProperty(propertyName));
    var compare = Expression.Constant(compareString);
    var contains = Expression.Call(memberAccess, typeof(string).GetMethod(nameof(string.Contains), new[] { typeof(string) }), compare);
    var expr = Expression.Lambda<Func<Person, bool>>(contains, new[] { parameter });

    return View(db.People.Where(expr).ToList());
}
//获取:人
公共行动结果索引()
{
var propertyName=“Description”;
var compareString=“abc”;
var参数=表达式参数(typeof(Person));
var memberAccess=Expression.MakeMemberAccess(参数,typeof(Person).GetProperty(propertyName));
var compare=表达式常数(compareString);
var contains=Expression.Call(memberAccess,typeof(string).GetMethod(nameof(string.contains),new[]{typeof(string)}),compare);
var expr=Expression.Lambda(contains,new[]{parameter});
返回视图(db.People.Where(expr.ToList());
}
当然,这会丢失所有检查、可能的选项、缓存等等。。。关键是,如果必须依赖运行时已知的类型,则必须自己创建表达式