Frage

Ich habe Ausdrücke C #, bevor sie auf lamdas Basis verwendet, aber ich habe keine Erfahrung sie mit der Hand zu komponieren. Bei einem gegebenen Expression<Func<SomeType, bool>> originalPredicate, möchte ich eine Expression<Func<OtherType, bool>> translatedPredicate erstellen.

In diesem Fall Sometype und haben OTHER die gleichen Felder, aber sie sind nicht verwandt (kein Erbe und nicht auf der Grundlage einer gemeinsamen Schnittstelle).

Hintergrund: Ich habe eine Repository Implementierung basierend auf LINQ to SQL. Ich projiziere die LINQ to SQL Entitäten meine Modell Entitäten, auf mein Modell in POCO zu halten. Ich mag Ausdrücke in das Repository zu übergeben (als eine Form von Spezifikationen), aber sie sollten auf den Modelleinheiten basieren. Aber ich kann nicht, diese Ausdrücke auf den Datenkontext übergeben, da es Ausdrücke erwartet auf der Grundlage der LINQ to SQL Einheiten.

War es hilfreich?

Lösung

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 diese von verschiedenen Anbietern unterschiedlich unterstützt werden. EF ist es vielleicht nicht mögen, zum Beispiel, auch wenn LINQ to SQL der Fall ist.

Die andere Option ist der Ausdrucksbaum für den Wiederaufbau vollständig , Reflexion über die entsprechenden Mitglieder zu finden. Viel komplexer.

Andere Tipps

Es gibt eine andere Art, wie ich gefunden habe, das schließt auch Ihren ursprünglichen Delegaten gewickelt wird.

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

Es gibt keine implizite Möglichkeit, die Übersetzung zu tun. Sie haben Ihre vorhandenen Delegaten in einem Lambda-wickeln, die einen neuen Typ aus dem Argumenttyp erstellt:

var translatedPredicate = x => originalPredicate(OtherTypeFromSomeType(x))

Wo OtherTypeFromSomeType die OtherType Instanz aus dem SomeType Argumente erstellt.

Ich hatte das gleiche Problem wie du und ich regelte es wie dies mit EF:

var viewModeValue = dbContext.Model.Select(m => new ViewModel{Field = m.Field}).Where(predicate) //predicate is an Expression<Func<ViewModel, bool>>

Entity Framework weiß, wie der richtigen SQL-Befehl zu bauen. die Expression Umwandlung ist viel komplizierter, weil es unveränderlich sein gebaut und könnte unerwünschte Laufzeitwirkungen verursacht, wenn Sie etwas falsch machen, und in meinem Fall zumindest ist es nicht erforderlich.

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