3

次の形式の式があります。

Expression<Func<T, bool>> predicate = t => t.Value == "SomeValue";

この式の「部分的に適用された」バージョンを作成することは可能ですか:

Expression<Func<bool>> predicate = () => t.Value == "SomeValue";

注: この式は実際にコンパイルまたは呼び出されることはなく、SQL を生成するために検査されるだけです。

4

2 に答える 2

5

これは、カスタム ExpressionVisitor を作成し、パラメーターをクロージャーでキャプチャした定数式に置き換えることで簡単に実現できます。

public class Foo
{
    public string Value { get; set; }
}

public class ReplaceVisitor<T> : ExpressionVisitor
{
    private readonly T _instance;
    public ReplaceVisitor(T instance)
    {
        _instance = instance;
    }

    protected override Expression VisitParameter(ParameterExpression node)
    {
        return Expression.Constant(_instance);
    }
}

class Program
{
    static void Main()
    {
        Expression<Func<Foo, bool>> predicate = t => t.Value == "SomeValue";
        var foo = new Foo { Value = "SomeValue" };
        Expression<Func<bool>> result = Convert(predicate, foo);

        Console.WriteLine(result.Compile()());
    }

    static Expression<Func<bool>> Convert<T>(Expression<Func<T, bool>> expression, T instance)
    {
        return Expression.Lambda<Func<bool>>(
            new ReplaceVisitor<T>(instance).Visit(expression.Body)
        );
    }
}
于 2012-10-12T17:02:16.760 に答える
1

私はこれがうまくいくと思います:

Expression predicate2 = Expression.Invoke(predicate, Expression.Constant(new T() { Value = "SomeValue"}));
Expression<Func<bool>> predicate3 = Expression.Lambda<Func<bool>>(predicate2);

ただし、これがSQLを生成するために簡単に解析できるかどうかはわかりません(コンパイルすると機能します-試しました)。

于 2012-10-12T16:07:34.253 に答える