MemberExpression к MemberExpression[]
Задача состоит в том, чтобы получить массив MemberExpressions из двух лямбда-выражений. Первый преобразуется в MethodCallExpression, который возвращает экземпляр объекта (Expression<Func<T>>
). Второе лямбда-выражение будет принимать результат скомпилированного первого выражения и возвращать вложенный член (Expression<Func<T,TMember>>
). Можно предположить, что второе лямбда-выражение будет выполнять только вызовы вложенных свойств, но может выполнять и несколько таких вызовов.
Итак, сигнатура метода, который я пытаюсь чтобы создать это:
MemberExpression[] GetMemberExpressionArray<T,TValue>(Expression<Func<T>> instanceExpression, Expression<Func<T,TValue>> nestedMemberExpression)
Где nestedMemberExpression
предполагается принять аргумент вида
parent => parent.ChildProperty.GrandChildProperty
И результирующий массив представляет MemberAccess от parent
до ChildProperty
и от значения ChildProperty
до GrandChildProperty
.
Я уже вернул последний MemberExpression
, используя следующий метод расширения.
public static MemberExpression GetMemberExpression<T, TValue>(Expression<Func<T, TValue>> expression)
{
if (expression == null)
{
return null;
}
if (expression.Body is MemberExpression)
{
return (MemberExpression)expression.Body;
}
if (expression.Body is UnaryExpression)
{
var operand = ((UnaryExpression)expression.Body).Operand;
if (operand is MemberExpression)
{
return (MemberExpression)operand;
}
if (operand is MethodCallExpression)
{
return ((MethodCallExpression)operand).Object as MemberExpression;
}
}
return null;
}
Теперь я знаю, что есть несколько способов сделать это. Самым непосредственным интуитивным для меня было бы сделать петлю через .Expression
свойство, чтобы получить первое выражение и захватить ссылки на каждое MemberExpression по пути. Это может быть лучшим способом сделать это, но может и не быть. Я не очень хорошо знаком с затратами на производительность, которые я получаю от использования таких выражений. Я знаю, что MemberExpression имеет MemberInfo, и это отражение должно повредить производительности.
Я пытался найти информацию о выражениях, но мои ресурсы были очень ограничены в том, что я нашел.
I был бы признателен за любые советы о том, как выполнить эту задачу (и этот тип задачи, в целом) с оптимальной производительностью и надежностью.
1 ответ:
Я не уверен, почему это было помечено performance , но самый простой способ, который я могу придумать, чтобы извлечь выражения-члены из дерева, - это подкласс
ExpressionVisitor
. Это должно быть намного проще, чем вручную писать логику для "расширения" различных типов выражений и ходить по дереву.Вероятно, вам придется переопределить
VisitMember
метод таков, что:
- захватывается каждое выражение-член.
- его дети-это посетил.
Я думаю, что это будет выглядеть примерно так:
protected override Expression VisitMember(MemberExpression node) { _myListOfMemberExpressions.Add(node); return base.VisitMember(node); }
Я немного неясен относительно остальной части вашей задачи; похоже, что вы хотите переписать выражения параметров, в этом случае вы можете посмотреть на этот ответ от Марка Гравелла.