可重用的表达

伍特

给定带有Where子句的查询

CollectionA.Where(a => a.Prop1 == val1 && a.Prop2 == val2)

和具有类似Where子句但属性通过引用链接的另一个查询。

CollectionB.Where(b => b.Reference.Prop1 == val1 && b.Reference.Prop2 == val2)

对于功能,它确实起作用:

        Func<A, bool> f1 = a => a.Prop1 == val1 && a.Prop2 == val2;
        Func<B, bool> g1 = b => f1(b.Reference);

对于表达式,这不起作用:

        Expression<Func<A, bool>> f2 = a => a.Prop1 == val1 && a.Prop2 == val2;
        Expression<Func<B, bool>> g2 = b => f2(b.Reference); // <-- Method name expected.

我想在使用规范的查询中重用该表达式。

像这样:

Specification specification = new Specification(val1, val2)

CollectionA.Where(specification.ToExpression());

CollectionB.Where(specification.ToExpression(x => x.Reference));:


public class Specification 
{
    private readonly int val1;
    private readonly long val2;

    public Specification(int val1, long val2)
    {
        this.val1 = val1;
        this.val2 = val2;
    }

    public Expression<Func<A, bool>> ToExpression()
    {
        return x => x.Prop1 == val1 && x.Prop2 == val2;
    }

    public Expression<Func<B, bool>> ToExpression<B>(Expression<Func<B, A>> navigate)
    {
        // ?
    }
}

如何实现这种方法?

另外,我希望这不仅适用于二进制“和”表达式,而且适用于任何表达式(即任何组合深度和参数类型)。(例如a => a.Prop1 == val1 && a.Prop2.Prop2a == val2a && a.Prop2.Prop2a == val2a),但基本上它只是实现我尝试使用上述函数g2执行的操作。

威克

您不能直接调用其他表达式f2(b.Reference)创建一个可以编译和调用的表达式将是徒劳的f2

您实际上想要做的是组成表达式。制作一个新表达式,该表达式表示一个链接到另一个表达式的表达式。您所缺少的表达式实际上只是AB如下所示获取的参数选择器b => b.Reference;

这是一种方便的Compose方法(类似于方法),可帮助将它们链接在一起。

class A
{
    public int Prop1 = 1;
    public int Prop2 = 2;
}
class B
{
    public A Reference;
}

class Program
{
    static Expression<Func<A, C>> Compose<A, B, C>(
        Expression<Func<A, B>> fAB, Expression<Func<B, C>> fBC)
    {
        var arg = Expression.Parameter(typeof(A));
        return Expression.Lambda<Func<A, C>>(
            Expression.Invoke(fBC, Expression.Invoke(fAB, arg)), arg);
    }

    static void Main(string[] args)
    {
        int val1 = 1;
        int val2 = 2;

        Func<A, bool> f1 = a => a.Prop1 == val1 && a.Prop2 == val2;
        Func<B, bool> g1 = b => f1(b.Reference);

        Expression<Func<A, bool>> f2 = a => a.Prop1 == val1 && a.Prop2 == val2;
        Expression<Func<B, A>> argSelect = b => b.Reference;
        var g2 = Compose<B, A, bool>(argSelect, f2);    

        A objA = new A();
        B objB = new B() { Reference = objA };
        var g2Compiled = g2.Compile();
        Console.WriteLine(g2Compiled.Invoke(objB));

        // Demonstrate that it's connected to our local variable
        val2 = 3;
        Console.WriteLine(g2Compiled.Invoke(objB));
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

可重用的MVC代码:处理linq表达式中的值类型

来自分类Dev

实体框架Linq将Lambda表达式嵌入可重用函数中

来自分类Dev

将参数传递给实体框架中的可重用表达式

来自分类Dev

LINQ to Entities select子句中的可重用函数/表达式

来自分类Dev

LINQ to Entities select子句中的可重用函数/表达式

来自分类Dev

将参数传递给实体框架中的可重用表达式

来自分类Dev

iOS可重用组件

来自分类Dev

类的可重用代码

来自分类Dev

可重用的搜索方法

来自分类Dev

OptionalInt可重用吗?

来自分类Dev

可重用的对象文字

来自分类Dev

可重用的搜索方法

来自分类Dev

可重用的CustomControl模板

来自分类Dev

可重用的 Angularjs 代码

来自分类Dev

使我的功能可重用

来自分类Dev

Laravel 可重用的函数

来自分类Dev

可重用函数类型

来自分类Dev

如何将LINQ查询的一部分移至可重用的LINQ表达式树

来自分类Dev

phpunit中的可重用测试

来自分类Dev

如何创建可重用的库

来自分类Dev

对象文字可重用函数

来自分类Dev

文件中的可重用流

来自分类Dev

创建可重用的WINDOW控件

来自分类Dev

UICollectionView的可重用性问题

来自分类Dev

小票形式的可重用DropDownChoice

来自分类Dev

可重用的尝试/捕获块

来自分类Dev

React JS:可重用组件

来自分类Dev

AngularJS可重用工厂

来自分类Dev

如何创建可重用的UIAlertcontroller?