Деревья выражений - полезная функция, но каково ее практическое применение? Могут ли они использоваться для генерации кода, метапрограммирования или чего-то подобного?





Вы можете использовать их для создания собственного поставщика linq для веб-сайта, такого как Google, Flickr или Amazon, вашего собственного веб-сайта или другого поставщика данных.
Марк Гравелл использовал их с большим эффектом в MiscUtil для реализации общие операторы.
Черт побери меня к этому ;-p
Реализация поставщиков LINQ в основном выполняется путем обработки деревьев выражений. Я также использую их для удаления буквальных строк из моего кода:
Как отмечает Джон, я использую их для предоставления общие операторы в .NET 3.5. Я также использую их (снова в MiscUtil) для обеспечения быстрого доступа к конструкторам, отличным от стандартных (вы не можете использовать Delegate.CreateDelegate с конструкторами, но Expression работает нормально).
Другое использование созданных вручную деревьев выражений:
Но на самом деле Expression - это очень универсальный способ написания любого динамического кода. Намного проще, чем Reflection.Emit, и, за мои деньги, проще для понимания, чем CodeDOM. А в .NET 4.0 у вас есть еще больше возможностей. Я показываю основы написания кода через Expressionв моем блоге.
Спасибо. блог не появляется !!!
@pixparker Я только что проверил: работает нормально
Я использую их для создания динамических запросов, будь то сортировка или фильтрация данных. В качестве примера:
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));
Первоначально Джомо Фишер, Густаво Герра опубликовал исправленную версию статический строковый словарь.
Где через деревья выражений, динамическое выражение, которое предоставляет действительно (читай: смехотворно) Словарь.
Реализация создает динамическое дерево решений, которое выбирает соответствующее значение в соответствии с длиной входной строки, затем по первой букве, затем по второй букве и так далее.
В конечном итоге это работает намного быстрее, чем эквивалентный словарь.
Я только что создал общую функцию фильтра, используя дерево выражений, которым хочу поделиться с вами, ребята ...
Начинать
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();
}
Я знаю, что это также можно сделать с помощью отражения, но это очень быстро или, я могу сказать, эквивалентно лямбде после первой компиляции. Самая первая итерация занимает в среднем 10 миллисекунд. Итак, это магия Дерева выражений. Просто и фантастично (я думаю)!
Хороший! Спасибо за примеры.
Может быть, я неправильно это читаю, но работает ли GetPropertyName только для свойств первого порядка? Найдет ли он имя Baz, если я дам ему GetPropertyName ((Foo f) => f.Bar.Baz); ?
@JoshGust .. Думаю, да ... вы получите Bar.Baz как string
@Moumit, в таком случае простое изменение string.Join(".", body.Split('.').Last() поможет, не так ли?
@JoshGust ... это пример ... вы можете настроить в соответствии с вашими потребностями ....
возможный дубликат В каких случаях деревья выражений могут быть полезны?