繁体   English   中英

使用 Expression.Lambda 制作 lambda 表达式时如何使用变量<func<> &gt;() </func<>

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM