16

プロジェクトでラムダ式を使用してサードパーティのクエリ API にマッピングしようとしています。そのため、式ツリーを手動で解析しています。

次のようなラムダ式を渡すと:

p => p.Title == "title"

すべてが機能します。

ただし、ラムダ式が次のようになっている場合:

p => p.Title == myaspdropdown.SelectedValue

.NET デバッガーを使用しても、その関数の実際の値はわかりません。代わりに、次のようなものが表示されます。

p => p.Title = (value(ASP.usercontrols_myaspusercontrol_ascx).myaspdropdown.SelectedValue)

何を与える?式の右側を文字列として取得しようとすると(value(ASP.usercontrols_myaspusercontrol_ascx).myaspdropdown.SelectedValue)、実際の値ではなく取得されます。実際の値を取得するにはどうすればよいですか?

4

4 に答える 4

21

ラムダ式を式ツリーとして扱っている場合、実行可能なコードがないことに注意してください。むしろ、記述した式を構成する式要素のツリーがあります。

Charlie Calvert には、これについて詳しく説明している良い記事があります。式のデバッグに式ビジュアライザーを使用する例が含まれています。

あなたの場合、等式の右辺の値を取得するには、新しいラムダ式を作成し、コンパイルしてから呼び出す必要があります。

私はこれの簡単な例をハックしました - それがあなたが必要とするものを提供することを願っています.

public class Class1
{
    public string Selection { get; set; }

    public void Sample()
    {
        Selection = "Example";
        Example<Book, bool>(p => p.Title == Selection);
    }

    public void Example<T,TResult>(Expression<Func<T,TResult>> exp)
    {
        BinaryExpression equality = (BinaryExpression)exp.Body;
        Debug.Assert(equality.NodeType == ExpressionType.Equal);

        // Note that you need to know the type of the rhs of the equality
        var accessorExpression = Expression.Lambda<Func<string>>(equality.Right);
        Func<string> accessor = accessorExpression.Compile();
        var value = accessor();
        Debug.Assert(value == Selection);
    }
}

public class Book
{
    public string Title { get; set; }
}
于 2008-10-27T08:53:00.873 に答える
1

実際の値を取得するには、取得したコンテキストに式ツリーのロジックを適用する必要があります。

式ツリーの要点は、式を評価するのではなく、ロジックをデータとして表現することです。ラムダ式の真の意味を理解する必要があります。これは、ローカル データに対してその一部を評価することを意味する場合があります。それは自分で判断する必要があります。式ツリーは非常に強力ですが、解析して使用するのは簡単なことではありません。(LINQ プロバイダーを作成したことがある人に聞いてください。Frans Bouma は、この難しさを何度か嘆いています。)

于 2008-10-26T19:46:31.007 に答える
0

まったく同じ問題に苦しんでいます、Bevan に感謝します。拡張機能では、値を抽出するために使用できる一般的なパターンを次に示します (クエリ エンジンでこれを使用します)。

    [TestFixture]
public class TestClass
{
    [Test]
    public void TEst()
    {
        var user = new User {Id = 123};
        var idToSearch = user.Id;
        var query = Creator.CreateQuery<User>()
            .Where(x => x.Id == idToSearch);
    }
}

public class Query<T>
{
    public Query<T> Where(Expression<Func<T, object>> filter)
    {
        var rightValue = GenericHelper.GetVariableValue(((BinaryExpression)((UnaryExpression)filter.Body).Operand).Right.Type, ((BinaryExpression)((UnaryExpression)filter.Body).Operand).Right);
        Console.WriteLine(rightValue);
        return this;
    }
}

internal class GenericHelper
{
    internal static object GetVariableValue(Type variableType, Expression expression)
    {
        var targetMethodInfo = typeof(InvokeGeneric).GetMethod("GetVariableValue");
        var genericTargetCall = targetMethodInfo.MakeGenericMethod(variableType);
        return genericTargetCall.Invoke(new InvokeGeneric(), new[] { expression });
    }
}

internal class InvokeGeneric
{
    public T GetVariableValue<T>(Expression expression) where T : class
    {
        var accessorExpression = Expression.Lambda<Func<T>>(expression);
        var accessor = accessorExpression.Compile();
        return accessor();
    }
}
于 2010-09-16T12:20:28.627 に答える
-1

私は上手く理解できていない気がします。あなたはそれをどこで「見ている」のですか?それは設計時ですか、それとも実行時ですか?ラムダ式は本質的に匿名デリゲートと考えることができ、遅延実行で動作します。したがって、実行がその行を通過するまで、割り当てられた値が表示されるとは思わないでください。
それが本当にあなたの言いたいことだとは思いませんが...質問を少し明確にすれば、私が助けることができるかもしれません:)

于 2008-10-26T18:42:45.223 に答える