Practical use of expression trees [closed]

2019-01-10 01:18发布

问题:

Expression trees are a nice feature, but what are its practical uses? Can they be used for some sort of code generation or metaprogramming or some such?

回答1:

As Jon notes, I use them to provide generic operators with .NET 3.5. I also use them (again in MiscUtil) to provide fast access to non-default constructors (you can't use Delegate.CreateDelegate with constructors, but Expression works fine).

Other uses of manually created expression trees:

  • object cloning
  • dynamic LINQ sorting
  • as a compiler

But really, Expression is a very versatile way of writing any dynamic code. Much simpler than Reflection.Emit, and for my money, simpler to understand than CodeDOM. And in .NET 4.0, you have even more options available. I show the fundamentals of writing code via Expression on my blog.



回答2:

Marc Gravell has used them to great effect in MiscUtil to implement generic operators.



回答3:

I just created a generic filter function using ExpressionTree .. I want to share with you guys...

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

....... I know it also can be done using Reflection ... but this one is tremendous fast or i can say equivalent to Lambda after first compilation ... The very first iteration is just an average 10 millisecond slow... So this is Expression Tree magic. Simple and fantastic....I think ...!!!!!!!!



回答4:

I use them to create dynamic queries, whether it be for sorting or filtering the data. As an example:

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


回答5:

Implementation of LINQ providers is mostly done by processing expression trees. I'm also using them to remove literal strings from my code:

  • Monorail
  • NHibernate


回答6:

I used expression tree to build a math expression evaluator: Building Expression Evaluator with Expression Trees in C#



回答7:

You can use them to build your own linq provider for a website like Google or Flickr or Amazon, your own website or another data provider.



回答8:

Originally by Jomo Fisher, Gustavo Guerra published a revised version of the static string dictionary.

Where through Expression trees, a dynamic expression that provides a really (read: ridiculously) Dictionary.

The implementation creates a dynamic decision tree that select the corrent value according to the length of the input string, then by the first letter, then the second letter and so on.

This ultimately runs much faster than the equivalent Dictionary.