70

表达式树是一个不错的功能,但它的实际用途是什么?它们可以用于某种代码生成或元编程等吗?

4

7 回答 7

45

正如 Jon 所说,我使用它们为.NET 3.5提供通用运算符。我还使用它们(再次在 MiscUtil 中)提供对非默认构造函数的快速访问(您不能Delegate.CreateDelegate与构造函数一起使用,但Expression工作正常)。

手动创建的表达式树的其他用途:

但实际上,Expression 是一种非常通用的编写任何动态代码的方式。比 CodeDOM简单得多Reflection.Emit,而且对我来说,比 CodeDOM 更容易理解。在 .NET 4.0 中,您可以使用更多选项Expression 我在我的博客上展示了编写代码的基础知识。

于 2008-12-31T15:32:46.343 回答
22

Marc Gravell 在MiscUtil中使用它们实现了泛型运算符,效果非常好。

于 2008-12-31T14:48:48.023 回答
15

我刚刚使用我想与你们分享的表达式树创建了一个通用过滤器函数......

开始

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

多一个

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

使其更具扩展性

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

我知道它也可以使用反射来完成,但是这个速度非常快,或者,我可以说,相当于第一次编译后的 lambda。第一次迭代平均只需要 10 毫秒。这就是表达式树的魔法。简单而奇妙(我认为)!

于 2013-12-09T11:57:33.743 回答
12

我使用它们来创建动态查询,无论是用于排序还是过滤数据。举个例子:

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));
于 2008-12-31T15:38:08.437 回答
8

LINQ 提供程序的实现主要是通过处理表达式树来完成的。我还使用它们从我的代码中删除文字字符串:

于 2008-12-31T14:49:41.453 回答
4

您可以使用它们为 Google、Flickr 或 Amazon 等网站、您自己的网站或其他数据提供商构建您自己的 linq 提供商。

于 2008-12-31T14:47:17.230 回答
2

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.

于 2008-12-31T16:06:08.677 回答