C# 表达式树绑定

发布于 2024-12-09 11:25:03 字数 1451 浏览 0 评论 0原文

所以我想做的是使用表达式树将谓词应用于集合中的每个值(读取 map 或 list.All(predicate))。看来我没有获得绑定到 All 提供的值的谓词的输入参数,而且我有点卡住了。这是我正在使用的代码(使用 linqpad)::

public class SomeType
{
  public IEnumerable<bool> Collection { get; set; }
}

void Main()
{
  var list = new SomeType {
    Collection = new List<bool> { true, true, true }
  };
  var functor = Compiler((SomeType t) => t.Collection, (bool x) => x);
  functor(list).Dump();
}

MethodInfo FindMethod<TInput>(Type location, string name)
{
    var handle = location
        .GetMethods(BindingFlags.Static | BindingFlags.Public)
        .Where(method => method.Name == name).First();

    return handle.MakeGenericMethod(typeof(TInput));
}

Predicate<TObject> Compiler<TObject, TProperty>(
    Expression<Func<TObject, IEnumerable<TProperty>>> selector, 
    Expression<Predicate<TProperty>> predicate)
{
    var query = FindMethod<TProperty>(typeof(Enumerable), "All");
    var expression = Expression.Call(query,
        new Expression[] {
            Expression.Invoke(selector, selector.Parameters),
            Expression.Lambda<Func<TProperty, bool>>(predicate.Body,
                        Expression.Parameter(typeof(TProperty))),
        });         

    return Expression.Lambda<Predicate<TObject>>(expression,
        selector.Parameters).Compile();
}

如果在另一个问题中回答了这个问题(我看了一会儿),谢谢并抱歉。

So what I am trying to do is use expression trees to apply a predicate to each value in a collection (read map or list.All(predicate)). It appears that I am not getting the input parameter to the predicate bound to the value supplied by All, and I'm a little stuck. Here is the code (using linqpad) that I am working with::

public class SomeType
{
  public IEnumerable<bool> Collection { get; set; }
}

void Main()
{
  var list = new SomeType {
    Collection = new List<bool> { true, true, true }
  };
  var functor = Compiler((SomeType t) => t.Collection, (bool x) => x);
  functor(list).Dump();
}

MethodInfo FindMethod<TInput>(Type location, string name)
{
    var handle = location
        .GetMethods(BindingFlags.Static | BindingFlags.Public)
        .Where(method => method.Name == name).First();

    return handle.MakeGenericMethod(typeof(TInput));
}

Predicate<TObject> Compiler<TObject, TProperty>(
    Expression<Func<TObject, IEnumerable<TProperty>>> selector, 
    Expression<Predicate<TProperty>> predicate)
{
    var query = FindMethod<TProperty>(typeof(Enumerable), "All");
    var expression = Expression.Call(query,
        new Expression[] {
            Expression.Invoke(selector, selector.Parameters),
            Expression.Lambda<Func<TProperty, bool>>(predicate.Body,
                        Expression.Parameter(typeof(TProperty))),
        });         

    return Expression.Lambda<Predicate<TObject>>(expression,
        selector.Parameters).Compile();
}

Thanks and sorry if this was answered in another question (I looked for a while).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

何时共饮酒 2024-12-16 11:25:03

这确实有效,但我必须将 Predicate 更改为 Func。如果你愿意的话我可以尝试改回来。

static Predicate<TObject> Compiler<TObject, TProperty>(
    Expression<Func<TObject, IEnumerable<TProperty>>> selector,
    Expression<Func<TProperty, bool>> predicate)
{
    var query = FindMethod<TProperty>(typeof(Enumerable), "All");
    var expression = Expression.Call(
        query,
        Expression.Invoke(selector, selector.Parameters), 
        predicate);

    return Expression
        .Lambda<Predicate<TObject>>(expression, selector.Parameters)
        .Compile();
}

5 分钟后...如果您确实想使用 Predicate...

static Predicate<TObject> Compiler<TObject, TProperty>(
    Expression<Func<TObject, IEnumerable<TProperty>>> selector,
    Expression<Predicate<TProperty>> predicate)
{
    var query = FindMethod<TProperty>(typeof(Enumerable), "All");

    var predicateAsFunc = Expression.Lambda<Func<TProperty, bool>>(
        predicate.Body, 
        predicate.Parameters);

    var expression = Expression.Call(
        query,
        Expression.Invoke(selector, selector.Parameters), 
        predicateAsFunc);

    return Expression
        .Lambda<Predicate<TObject>>(expression, selector.Parameters)
        .Compile();
}

This does work, but I had to change the Predicate<TObject> to Func<TObject, bool>. If you want I can try to change it back.

static Predicate<TObject> Compiler<TObject, TProperty>(
    Expression<Func<TObject, IEnumerable<TProperty>>> selector,
    Expression<Func<TProperty, bool>> predicate)
{
    var query = FindMethod<TProperty>(typeof(Enumerable), "All");
    var expression = Expression.Call(
        query,
        Expression.Invoke(selector, selector.Parameters), 
        predicate);

    return Expression
        .Lambda<Predicate<TObject>>(expression, selector.Parameters)
        .Compile();
}

5 minutes later... And if you really want to use Predicate<TObject>...

static Predicate<TObject> Compiler<TObject, TProperty>(
    Expression<Func<TObject, IEnumerable<TProperty>>> selector,
    Expression<Predicate<TProperty>> predicate)
{
    var query = FindMethod<TProperty>(typeof(Enumerable), "All");

    var predicateAsFunc = Expression.Lambda<Func<TProperty, bool>>(
        predicate.Body, 
        predicate.Parameters);

    var expression = Expression.Call(
        query,
        Expression.Invoke(selector, selector.Parameters), 
        predicateAsFunc);

    return Expression
        .Lambda<Predicate<TObject>>(expression, selector.Parameters)
        .Compile();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文