C # Comment convertir une expression > à une expression >

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

Question

J'ai déjà utilisé des expressions C # basées sur lamdas, mais je n'ai aucune expérience de leur composition manuelle. Étant donné une Expression<Func<SomeType, bool>> originalPredicate , je souhaite créer une Expression<Func<OtherType, bool>> translatedPredicate .

Dans ce cas, SomeType et OtherType ont les mêmes champs, mais ils ne sont pas liés (pas d'héritage et ne sont pas basés sur une interface commune).

Contexte: J'ai une implémentation de référentiel basée sur LINQ to SQL. Je projette les entités LINQ to SQL sur mes entités Model afin de conserver mon modèle dans POCO. Je souhaite transmettre des expressions au référentiel (sous forme de spécifications), mais elles doivent être basées sur les entités du modèle. Mais je ne peux pas transmettre ces expressions au contexte de données, car il attend des expressions basées sur les entités LINQ to SQL.

Réponse acceptée

Avec Expression , le moyen le plus simple consiste à utiliser une expression de conversion:

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

Notez cependant que cela sera pris en charge différemment par différents fournisseurs. EF pourrait ne pas l’aimer, par exemple, même si LINQ-to-SQL l’aimait.

L’autre option consiste à reconstruire complètement l’ arbre d’expression en utilisant la réflexion pour rechercher les membres correspondants. Beaucoup plus complexe.


Réponse populaire

J'ai trouvé un autre moyen, qui consiste également à emballer votre délégué d'origine.

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


Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow