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 2

1 ответ:

Я не уверен, почему это было помечено performance , но самый простой способ, который я могу придумать, чтобы извлечь выражения-члены из дерева, - это подкласс ExpressionVisitor. Это должно быть намного проще, чем вручную писать логику для "расширения" различных типов выражений и ходить по дереву.

Вероятно, вам придется переопределить VisitMember метод таков, что:

  1. захватывается каждое выражение-член.
  2. его дети-это посетил.

Я думаю, что это будет выглядеть примерно так:

protected override Expression VisitMember(MemberExpression node)
{
    _myListOfMemberExpressions.Add(node);
    return base.VisitMember(node);
}

Я немного неясен относительно остальной части вашей задачи; похоже, что вы хотите переписать выражения параметров, в этом случае вы можете посмотреть на этот ответ от Марка Гравелла.