質問

プロジェクトでLambda Expressionsを使用して、サードパーティのクエリ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)が返されます。 実際の値を取得するにはどうすればよいですか

役に立ちましたか?

解決

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

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; }
}

他のヒント

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

式ツリーの重要な点は、式を評価するのではなく、データとして logic を表すことです。ラムダ式の真の意味を理解する必要があります。それは、ローカルデータに対してその一部を評価することを意味する場合があります-あなた自身でそれを決める必要があります。式ツリーは非常に強力ですが、それらを解析して使用するのは簡単なことではありません。 (LINQプロバイダーを書いた人に尋ねてください... Frans Boumaは何度も困難を嘆きました。)

まったく同じ問題に苦労していました、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();
    }
}

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top