powered by simpleCommunicator - 2.0.56     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Конвертация выражений (expressions) и делегатов
7 сообщений из 7, страница 1 из 1
Конвертация выражений (expressions) и делегатов
    #38532783
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Интересуют два конкретных примера:

1) Expression<Func<T, TResult>> в Expression<Func<T, T>>

2) Func<T, TResult> в Func<T, T>.

Зачем мне это надо? - У меня есть готовая функция, работающая с Expression<Func<T, TResult>> (это тип параметра). Штука в том, что нужный результат можно получить с абсолютно тем же телом этой функции, но работающей с Expression<Func<T>>. Так вот, хочу повторно использовать эту функцию, имея Expression<Func<T>> и передав её в качестве параметра Expression<Func<T, TResult>>, полученный из исходного Expression<Func<T>>. Ну и то же самое для Func - смотря с чем легче получится, с выражениями или с чисто делегатами.

Ну и вообще, стоит ли это делать? Может, проще (хотя, конечно, однозначно проще!) скопипастить тело одной функции в другую и дело с концом? У меня сейчас именно что скопипастено.


Кто абстрактно не может, могу совсем прямо конкретный пример привести, где это мне нужно. Вот та самая функция:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
public static string GetMemberName<TResult>(Expression<Func<T, TResult>> expression, ExpressionType expressionType)
{
    switch (expressionType)
    {
        case ExpressionType.MemberAccess:
            var memberExpression = (MemberExpression)expression.Body;
            if (memberExpression == null)
            {
                throw new InvalidOperationException("Expression must be of member access.");
            }
            return memberExpression.Member.Name;
            
        ...
    }
}



Вот как я её использую в расширяющих методах:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
public static string MemberName<T, TResult>(this T obj, Expression<Func<T, TResult>> expression, ExpressionType expressionType)
{
    return MembersOf<T>.GetMemberName<TResult>(expression, expressionType);
}

public static string OwnName<T>(this T obj, Expression<Func<T>> expression)
{
    var node = expression.Body as MemberExpression;
    if (node == null)
    {
        throw new InvalidOperationException("Expression must be of the object itself.");
    }
    return node.Member.Name;
}



Как видите, OwnName содерижт тот же код, что и GetMemberName, но не может просто взять и вызвать GetMemberName, как это делает MemberName, из-за несовпадения типов делегатов, с которыми работают их выражения. А хочется просто взять и вызвать готовый метод с конверсией выражения (желательно, в одну строчку - коротко и красиво чтобы было).
...
Рейтинг: 0 / 0
Конвертация выражений (expressions) и делегатов
    #38532787
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Могу добавить только, что с MemberName работаю так:

myClassObject.MemberName(obj => obj.PropertyOfMyClassObject)

а с OwnName так:

myClassObject.OwnName(() => myClassObject)
...
Рейтинг: 0 / 0
Конвертация выражений (expressions) и делегатов
    #38532806
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я же на днях давал ссылку . Зря ты её не захотел смотреть. :-)

Типизация под разные входные выражения:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
        public static string GetPropertyPath(Expression<Func<object>> expression) 
        { 
            return GetPropertyPath(expression.Body); 
        } 
  
        public static string GetPropertyPath<T>(Expression<Func<T, object>> expression) 
        { 
            return GetPropertyPath(expression.Body); 
        } 


Один парсер для разных типов:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
        static string GetPropertyPath(Expression expression) 
        { 
            var firstMember = expression as MemberExpression; 
  
            if (firstMember == null) 
                firstMember = (MemberExpression)((UnaryExpression)expression).Operand; 
  
            var members = EnumerableHelper 
                .GetLinkedList(firstMember, v => v.Expression as MemberExpression) 
                .Reverse() 
                .Select(v => v.Member.Name); 
  
            return string.Join(".", members); 
        } 
...
Рейтинг: 0 / 0
Конвертация выражений (expressions) и делегатов
    #38532986
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КЯ же на днях давал ссылку . Зря ты её не захотел смотреть. :-)

Типизация под разные входные выражения:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
        public static string GetPropertyPath(Expression<Func<object>> expression) 
        { 
            return GetPropertyPath(expression.Body); 
        } 
  
        public static string GetPropertyPath<T>(Expression<Func<T, object>> expression) 
        { 
            return GetPropertyPath(expression.Body); 
        } 


Один парсер для разных типов:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
        static string GetPropertyPath(Expression expression) 
        { 
            var firstMember = expression as MemberExpression; 
  
            if (firstMember == null) 
                firstMember = (MemberExpression)((UnaryExpression)expression).Operand; 
  
            var members = EnumerableHelper 
                .GetLinkedList(firstMember, v => v.Expression as MemberExpression) 
                .Reverse() 
                .Select(v => v.Member.Name); 
  
            return string.Join(".", members); 
        } 


Т. е. ключевая идея здесь, как я понял - привести входное выражение к простейшему выражению (которым вы выбрали UnaryExpression) и вытаскивание единственного члена этого выражения? Или UnaryExpression выбрал не случайно и другие не подойдут?

И другой вопрос. Ваш код подходит только для полей и свойств. Для вытаскивания названий методов вы бы также что-то вроде switch городили в вашем методе GetPropertyPath?
...
Рейтинг: 0 / 0
Конвертация выражений (expressions) и делегатов
    #38532998
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320Т. е. ключевая идея здесь...Ключевая идея здесь в том, что Expression<Func<object>> , Expression<Func<T, object>> , Expression<Любой Делегат> имеют свойство Body типа Expression , по которому можно обобщить доступ к этим выражениям.

А на сам парсер можешь не смотреть, он решает чисто мои задачи.
...
Рейтинг: 0 / 0
Конвертация выражений (expressions) и делегатов
    #38533101
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей Кuser7320Т. е. ключевая идея здесь...Ключевая идея здесь в том, что Expression<Func<object>> , Expression<Func<T, object>> , Expression<Любой Делегат> имеют свойство Body типа Expression , по которому можно обобщить доступ к этим выражениям.

А на сам парсер можешь не смотреть, он решает чисто мои задачи.
Короче, я насмотрелся на всякие извращения по конверсии выражений и делегатов. Вы правильно подметили - все эти штуки имеют свойство Body, и даже если использовать эти конверсии - так или иначе вытаскиваешь Body. Но раз уж вытащил - зачем конвертировать? Сразу вытаскиваем имя. Т. е. ну и что, что копипаст - зато без извращений. Вобщем, я оставил свой старый вариант. А ещё я могу вытащить имя любой локальной переменной даже чисто со своим MemberName, который был задуман мной для классов. Просто в качестве входного параметра можно любой объект передать - он всё равно не будет использоваться - а выражение сделать из одной этой локальной переменной. Например:

Код: c#
1.
2.
int i = 5;
string iName = MemberName(casualObject => i);



И даже, вроде, особых накладных расходов на это нет никаких.

Я теперь вспомнил, что я раньше так и делал. Но потом зачем-то захотел отдельный метод для имён локальных переменных ввести. Дело в том, что пользователь моего метода может знать о том, что вот можно его использовать для вытаскивания имён локальных переменных, только если знает как этот метод устроен внутри - т. е. что он тупо с Body работает. Поэтому и подумал, что надо отдельный метод, само название которого будет говорить, для чего он.

Вобщем, оставил у себя всё как было.
...
Рейтинг: 0 / 0
Конвертация выражений (expressions) и делегатов
    #38533107
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторint i = 5;
string iName = MemberName(casualObject => i);
Может, даже

int i = 5;
string iName = MemberName(i => i);

Не проверял, правда.
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Конвертация выражений (expressions) и делегатов
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]