[英]How Create programmaticaly Expression.Lambda<Func<TEntity, TProperty>> with variable Type?
[英]How to use a variable when making a lambda expression using Expression.Lambda<Func<>>()
我有一个 linq 查询,如下所示:
var query = _appDbContext.Persons
.Where(p => p.Id == 123)
.Select(lambda)
.ToList();
我使用 lambda 因为我的 select 语句中有一个变量。 lambda:
var wantedData = "Adress";
var x = Expression.Parameter(typeof(Person), "x");
var body = Expression.PropertyOrField(x, wantedData);
var lambda = Expression.Lambda<Func<Person, Adress>>(body, x);
该查询将返回 id 为 123 的人的地址。假设我希望接收此人的所有订阅,而不是地址。 由于 lambda 语句中的“地址”,仅设置wantedData = "Subscription"
将不起作用。 所以我正在寻找一种方法来使用变量来更改 lambda 语句中的“地址”。
我尝试了以下方法,这显然不起作用。
var lambda = Expression.Lambda<Func<Person, wantedData>>(body, x);
有没有办法做到这一点?
好的,我设法创建了一个以表达式为参数的通用查询方法。
编辑:这将收到一个字符串值,并将尝试将其与您的Person
class 上的现有属性匹配。
private IEnumerable<TResult> GetPersonData<TResult>(Expression<Func<Person, TResult>> selectExpression)
{
return _dbContext.Persons
// .Where(filter)
.Select(selectExpression)
.ToList();
}
public IEnumerable<object> GetData(string dataPropertyName)
{
switch(dataPropertyName) {
case nameof(Person.Address): return GetPersonData(p => p.Address);
case nameof(Person.Subscription): return GetPersonData(p => p.Subscription);
// other cases
default: throw new InvalidArgumentException("Invalid property name");
}
}
请注意,此代码只是当场编写的示例,它可能无法直接用于复制粘贴
我做了一些类似于OrderBy
的东西,并为你的 select 稍微调整了一下。 这仅在您知道返回类型时才有效。 您可以使用以下代码创建扩展方法:
public static IQueryable<TResult> Select<T,TResult>(this IQueryable<T> source, string propertyName)
{
var prop = typeof(T).GetProperties()
.FirstOrDefault(x => x.Name.ToUpper() == propertyName.ToUpper());
ParameterExpression pe = Expression.Parameter(typeof(T), "x");
MemberExpression body = Expression.Property(pe, prop.Name);
LambdaExpression lambda = Expression.Lambda(body, new ParameterExpression[] { pe });
MethodCallExpression selectCallExpression = Expression.Call(
typeof(Queryable),
"Select",
new Type[] { source.ElementType, prop.PropertyType },
source.Expression,
lambda);
return source.Provider.CreateQuery<TResult>(selectCallExpression);
}
这样,您可以像这样使用它:
var query = _appDbContext.Persons
.Where(p => p.Id == 123)
.Select<Person,string>(wantedData)
.ToList();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.