表达式树是一个不错的功能,但它的实际用途是什么?它们可以用于某种代码生成或元编程等吗?
7 回答
正如 Jon 所说,我使用它们为.NET 3.5提供通用运算符。我还使用它们(再次在 MiscUtil 中)提供对非默认构造函数的快速访问(您不能Delegate.CreateDelegate
与构造函数一起使用,但Expression
工作正常)。
手动创建的表达式树的其他用途:
但实际上,Expression 是一种非常通用的编写任何动态代码的方式。比 CodeDOM简单得多Reflection.Emit
,而且对我来说,比 CodeDOM 更容易理解。在 .NET 4.0 中,您可以使用更多选项。Expression
我在我的博客上展示了编写代码的基础知识。
我刚刚使用我想与你们分享的表达式树创建了一个通用过滤器函数......
开始
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 毫秒。这就是表达式树的魔法。简单而奇妙(我认为)!
我使用它们来创建动态查询,无论是用于排序还是过滤数据。举个例子:
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));
您可以使用它们为 Google、Flickr 或 Amazon 等网站、您自己的网站或其他数据提供商构建您自己的 linq 提供商。
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.