C# 表达式树的实际使用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/403088/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 02:06:29  来源:igfitidea点击:

Practical use of expression trees

c#expression-trees

提问by Dmitri Nesteruk

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?

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

回答by tuinstoel

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.

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

回答by Jon Skeet

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

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

回答by Mauricio Scheffer

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

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

回答by Marc Gravell

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

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

Other uses of manually created expression trees:

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

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 optionsavailable. I show the fundamentals of writing code via Expressionon my blog.

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

回答by mattruma

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

回答by damageboy

Originally by Jomo Fisher, Gustavo Guerrapublished 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.

这最终比等效的 Dictionary 运行得快得多。

回答by Moumit

I just created a generic filter function using an Expression Tree that 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 tremendously fast or, I can say, equivalent to a lambda after first compilation. The very first iteration takes just an average of 10 milliseconds. So this is Expression Tree magic. Simple and fantastic (I think)!

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