C # Wie konvertiert man einen Ausdruck? <Func<SomeType> &gt; zu einem Ausdruck <Func<OtherType> &gt;

c# expression-trees lambda linq-to-sql repository-pattern

Frage

Ich habe C # -Ausdrücke zuvor basierend auf Lamdas verwendet, aber ich habe keine Erfahrung darin, sie von Hand zu komponieren. Bei einem Expression<Func<SomeType, bool>> originalPredicate möchte ich einen Expression<Func<OtherType, bool>> translatedPredicate erstellen Expression<Func<OtherType, bool>> translatedPredicate .

In diesem Fall haben SomeType und OtherType die gleichen Felder, aber sie sind nicht verwandt (keine Vererbung und keine gemeinsame Schnittstelle).

Hintergrund: Ich habe eine Repository-Implementierung basierend auf LINQ to SQL. Ich projiziere die LINQ to SQL-Entitäten zu meinen Model-Entitäten, um mein Modell in POCO zu behalten. Ich möchte Ausdrücke an das Repository übergeben (als eine Form von Spezifikationen), aber sie sollten auf den Modell-Entitäten basieren. Aber ich kann diese Ausdrücke nicht an den Datenkontext übergeben, da er Ausdrücke erwartet, die auf den LINQ to SQL-Entitäten basieren.

Akzeptierte Antwort

Mit Expression ist der einfachste Weg , um mit einem Umsatz Ausdruck:

class Foo {
    public int Value { get; set; }
}
class Bar {
    public int Value { get; set; }
}
static class Program {
    static void Main() {
        Expression<Func<Foo, bool>> predicate =
            x => x.Value % 2 == 0;
        Expression<Func<Bar, Foo>> convert =
            bar => new Foo { Value = bar.Value };

        var param = Expression.Parameter(typeof(Bar), "bar");
        var body = Expression.Invoke(predicate,
              Expression.Invoke(convert, param));
        var lambda = Expression.Lambda<Func<Bar, bool>>(body, param);

        // test with LINQ-to-Objects for simplicity
        var func = lambda.Compile();
        bool withOdd = func(new Bar { Value = 7 }),
             withEven = func(new Bar { Value = 12 });
    }
}

Beachten Sie jedoch, dass dies von verschiedenen Anbietern unterschiedlich unterstützt wird. EF mag es beispielsweise nicht mögen, selbst wenn LINQ-to-SQL dies tut.

Die andere Option besteht darin, den Ausdrucksbaum vollständig neu zu erstellen, indem Sie mithilfe von Reflektion die entsprechenden Elemente finden. Viel komplexer.


Beliebte Antwort

Es gibt einen anderen Weg, den ich gefunden habe, der auch einschließt, Ihren ursprünglichen Delegierten einzuwickeln.

Func<T, object> ExpressionConversion<U>(Expression<Func<T, U>> expression)
{
    Expression<Func<T, object>> g = obj => expression.Compile().Invoke(obj);
    return g.Compile();
}



Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum