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?
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 Expression
sur mon blog .
Marc Gravell les a utilisés à bon escient dans MiscUtil pour implémenter opérateurs génériques .
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 ... !!!!!!!!
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));
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:
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 #
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.
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.