web-dev-qa-db-fra.com

Utilisation pratique des arbres d'expression

Les arbres d'expression sont une fonctionnalité intéressante, mais quelles sont ses utilisations pratiques? Peuvent-ils être utilisés pour une sorte de génération de code ou de métaprogrammation ou autres?

66
Dmitri Nesteruk

Comme le note Jon, je les utilise pour fournir opérateurs génériques avec .NET 3.5. Je les utilise également (à nouveau dans MiscUtil) pour fournir un accès rapide aux constructeurs non par défaut (vous ne pouvez pas utiliser Delegate.CreateDelegate avec des constructeurs, mais Expression fonctionne très bien).

Autres utilisations des arborescences d'expression créées manuellement:

Mais vraiment, Expression est un moyen très polyvalent d'écrire n'importe quel code dynamique. Beaucoup plus simple que Reflection.Emit, et pour mon argent, plus simple à comprendre que CodeDOM. Et dans .NET 4.0, vous avez encore plus d'options disponibles. Je montre les principes fondamentaux de l'écriture de code via Expressionsur mon blog .

41
Marc Gravell

Marc Gravell les a utilisés à bon escient dans MiscUtil pour implémenter opérateurs génériques .

20
Jon Skeet

Je viens de créer un generic filter function en utilisant ExpressionTree .. Je veux share avec vous les gars ...

Start

var allFiltered= Filter(AllCustomer, "Name", "Moumit");

public static List<T> Filter<T>(this List<T> Filterable, string PropertyName, object ParameterValue)
{
    ConstantExpression c = Expression.Constant(ParameterValue);
    ParameterExpression p = Expression.Parameter(typeof(T), "xx");
    MemberExpression m = Expression.PropertyOrField(p, PropertyName);
    var Lambda = Expression.Lambda<Func<T, Boolean>>(Expression.Equal(c, m), new[] { p });
    Func<T, Boolean> func = Lambda.Compile();
    return Filterable.Where(func).ToList();
}

One More

string singlePropertyName=GetPropertyName((Property.Customer p) => p.Name);

public static string GetPropertyName<T, U>(Expression<Func<T, U>> expression)
{
        MemberExpression body = expression.Body as MemberExpression;
        // if expression is not a member expression
        if (body == null)
        {
            UnaryExpression ubody = (UnaryExpression)expression.Body;
            body = ubody.Operand as MemberExpression;
        }
        return string.Join(".", body.ToString().Split('.').Skip(1));
}

Make it more expandable

string multiCommaSeparatedPropertyNames=GetMultiplePropertyName<Property.Customer>(c => c.CustomerId, c => c.AuthorizationStatus)

public static string GetMultiplePropertyName<T>(params Expression<Func<T, object>>[] expressions)
{
        string[] propertyNames = new string[expressions.Count()];
        for (int i = 0; i < propertyNames.Length; i++)
        {
            propertyNames[i] = GetPropertyName(expressions[i]);
        }

        return propertyNames.Join();
}

....... Je sais que cela peut aussi être fait en utilisant Reflection ... mais celui-ci est extrêmement rapide ou je peux dire équivalent à Lambda après la première compilation ... Le très la première itération est juste une moyenne de 10 millisecondes lente ... C'est donc Expression Tree la magie. Simple et fantastique .... je pense ... !!!!!!!!

15
Moumit

Je les utilise pour créer des requêtes dynamiques, que ce soit pour trier ou filtrer les données. Par exemple:

IQueryable<Data.Task> query = ctx.DataContext.Tasks;

if (criteria.ProjectId != Guid.Empty)
      query = query.Where(row => row.ProjectId == criteria.ProjectId);

if (criteria.Status != TaskStatus.NotSet)
      query = query.Where(row => row.Status == (int)criteria.Status);

if (criteria.DueDate.DateFrom != DateTime.MinValue)
      query = query.Where(row => row.DueDate >= criteria.DueDate.DateFrom);

if (criteria.DueDate.DateTo != DateTime.MaxValue)
     query = query.Where(row => row.DueDate <= criteria.DueDate.DateTo);

if (criteria.OpenDate.DateFrom != DateTime.MinValue)
     query = query.Where(row => row.OpenDate >= criteria.OpenDate.DateFrom);

var data = query.Select(row => TaskInfo.FetchTaskInfo(row));
12
mattruma

L'implémentation des fournisseurs LINQ se fait principalement par le traitement d'arbres d'expression. Je les utilise également pour supprimer des chaînes littérales de mon code:

8
Mauricio Scheffer

J'ai utilisé l'arborescence d'expressions pour construire un évaluateur d'expressions mathématiques: Construire un évaluateur d'expression avec des arbres d'expression en C #

6
Giorgi

Vous pouvez les utiliser pour créer votre propre fournisseur linq pour un site Web comme Google ou Flickr ou Amazon, votre propre site Web ou un autre fournisseur de données.

4
tuinstoel

Initialement par Jomo Fisher , Gustavo Guerra a publié une version révisée du dictionnaire de chaînes statiques .

Où à travers les arbres d'expression, une expression dynamique qui fournit un dictionnaire vraiment (lire: ridiculement).

L'implémentation crée un arbre de décision dynamique qui sélectionne la valeur corrente en fonction de la longueur de la chaîne d'entrée, puis par la première lettre, puis la deuxième lettre et ainsi de suite.

Cela fonctionne finalement beaucoup plus rapidement que le dictionnaire équivalent.

2
damageboy