gpt4 book ai didi

c# - 使用辅助方法创建动态 lambda

转载 作者:行者123 更新时间:2023-11-30 21:46:02 27 4
gpt4 key购买 nike

我有一个主要方法,可以为给定实体创建基础搜索条件。在这种方法中,我会在将其应用于查询之前检查默认值。

例如

        if (!string.IsNullOrEmpty(value))
qry = qry.Where(x => x.PropA.Contains(value));

if (!string.IsNullOrEmpty(anotherValue))
qry = qry.Where(x => x.PropB.Contains(anotherValue));

但是,我想重构它并改用辅助方法,但是由于我对表达式的知识和经验有限,所以我很难完成任务。

我有这个锅炉代码,我相信它说明了我正在努力完成的事情:

    IQueryable<T> Test<T, TV>(IQueryable<T> qry, Expression<Func<T, TV>> prop, TV value)
{
if (EqualityComparer<TV>.Default.Equals(value, default(TV)))
return qry;

var right = Expression.Constant(value);

var body = Expression.Equal(prop, right);
var lambda = Expression.Lambda<Func<T, bool>>(body);

return qry.Where(lambda);
}

这应该使我能够像这样调用电话:

qry = Test(qry, x=>PropA, value);
qry = Test(qry, x=>PropB, anotherValue);

然而,问题是 body 变量导致 BinaryExpression,而我完全不知道如何从这里开始。

最佳答案

您必须将方法转换为表达式,然后将其包含在 lambda 的主体中。

因此,从您的锅炉代码开始,经过上述更改后它应该看起来像

    IQueryable<T> Test<T, TV>(IQueryable<T> qry, Expression<Func<T, TV>> prop, string propertyValue)
{

MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
var someValue = Expression.Constant(propertyValue, typeof(string));
var body = Expression.Call(prop, method, someValue); // pseudocode, to be refined below

var lambda = Expression.Lambda<Func<T, bool>>(body);

return qry.Where(lambda);
}

现在让我使用字符串访问器重新表述

    static IQueryable<T>  Test<T>(IQueryable<T> qry, 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);
var lambda = Expression.Lambda<Func<T, bool>>(containsMethodExp, parameterExp);
return qry.Where(lambda);
}

最后是一个简单的用法示例

    class MyClass
{
public string Myname { get; set; }
}

static void Main(string[] args)
{
var check = new MyClass() { Myname = "11 aa 22" };
var check2 = new MyClass() { Myname = "11 bb 22" };
var x = new List<MyClass>();
x.Add(check);
x.Add(check2);
var q = x.AsQueryable();
var qry = Test(q, "Myname", "bb");
}

好吧,如果您更喜欢属性选择器,则助手将变为

    static IQueryable<T>  Test<T>(IQueryable<T> qry, Expression<Func<T, string>> selector, string propertyValue)
{
var parameterExp = Expression.Parameter(typeof(T), "type");

var memberExpression = (MemberExpression)selector.Body;
var parameterTProperty = (PropertyInfo)memberExpression.Member;
var propertyExp = Expression.Property(parameterExp, parameterTProperty);

MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
var someValue = Expression.Constant(propertyValue, typeof(string));
var containsMethodExp = Expression.Call(propertyExp, method, someValue);
var lambda = Expression.Lambda<Func<T, bool>>(containsMethodExp, parameterExp);
return qry.Where(lambda);
}

用作

        var qry = Test(q, z => z.Myname , "bb");

关于c# - 使用辅助方法创建动态 lambda,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39569130/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com