Frage

Ich versuche, Lambda-Ausdrücke in einem Projekt zu verwenden, um einen Dritten Abfrage API abzubilden. Also, ich bin mit der Hand des Expression Baum Parsen.

Wenn ich in einem Lambda-Ausdruck übergeben, wie:

p => p.Title == "title"

alles funktioniert.

Wenn jedoch mein Lambda-Ausdruck wie folgt aussieht:

p => p.Title == myaspdropdown.SelectedValue

.NET-Debugger verwenden, sehe ich nicht den tatsächlichen Wert dieser funciton. Stattdessen sehe ich so etwas wie:

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

Was soll das? Und wenn ich versuche, die rechte Seite des Ausdrucks als Zeichenkette zu greifen, bekomme ich statt des tatsächlichen Wertes (value(ASP.usercontrols_myaspusercontrol_ascx).myaspdropdown.SelectedValue). Wie erhalte ich den aktuellen Wert?

War es hilfreich?

Lösung

Beachten Sie, dass, wenn Sie mit dem Lambda-Ausdruck als Ausdruck Baum zu tun haben, müssen Sie nicht ausführbaren Code. Vielmehr haben Sie einen Baum Ausdruckselemente, die die Expression bilden Sie geschrieben haben.

Charlie Calvert hat einen guten Beitrag , die diskutiert diese im Detail. Eingeschlossen ist ein Beispiel für das Debuggen von Ausdrücken eines Ausdruck visualiser zu verwenden.

In Ihrem Fall den Wert der rechten Seite der Gleichheit Ausdruck zu erhalten, werden Sie einen neuen Lambda-Ausdruck erstellen müssen, es kompilieren und dann aufrufen.

Ich habe zusammen ein kurzes Beispiel dafür gehackt - hoffen, dass es hält, was Sie brauchen,

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

Andere Tipps

Um den tatsächlichen Wert zu erhalten, müssen Sie die Logik des Ausdrucksbaums anwenden, was auch immer Kontext Sie haben.

Der ganze Sinn des Ausdrucks Bäume ist, dass sie die Logik als Daten statt der Auswertung des Ausdrucks darstellen. Sie benötigen, um herauszufinden, was der Lambda-Ausdruck wirklich bedeutet. Das kann bedeuten, dass einige Teile davon gegen lokale Datenauswertung - Sie werden feststellen, dass selbst entscheiden müssen. Expression Bäume sind sehr leistungsfähig, aber es ist keine einfache Sache, sie zu analysieren und zu nutzen. (Fragen Sie jeden, der eine LINQ-Anbieter geschrieben ... Frans Bouma die Schwierigkeiten mehrmals beklagten hat.)

Just wurde mit genau dem gleichen Problem, dank Bevan kämpfen. Auf einer Verlängerung ist die folgende ein allgemeines Muster, das Sie den Wert zu extrahieren, verwenden können (mit diesem in meiner Abfrage-Engine).

    [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();
    }
}

Ich bin mir nicht sicher, ob ich verstehen. Wo sind Sie „sehen“ das? Ist das zur Entwurfszeit oder Laufzeit? Lambda-Ausdrücke kann im wesentlichen als anonymer Teilnehmer gedacht werden, und wird mit verzögerter Ausführung arbeiten. So erwarten Sie sollten nicht den Wert, bis zugewiesen zu sehen, nachdem die Ausführung dieser Linie bestanden hat, offensichtlich.
Ich glaube nicht, das ist wirklich das, was Sie aber meine ... wenn Sie die Frage ein bisschen vielleicht klären kann ich helfen:)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top