Как получить ссылку на объект из ExpressionTree?
От: Codealot  
Дата: 10.12.19 18:54
Оценка:
    class Program
    {
        static void Main(string[] args)
        {
            var data = new DataClass();
            var info = ExpressionUtil.GetMember(() => data.Field1);
        }
    }

    class DataClass
    {
        public string Field1 = "Field1";
    }

    static class ExpressionUtil
    {
        public static MemberInfo GetMember<TResult>(Expression<Func<TResult>> expression)
        {
            var res = ((MemberExpression)expression.Body).Member;
            return res;
        }
    }


Как в этом случае получить кроме MemberInfo еще и указатель на объект data, к которому этот MemberInfo относится?
Re: Как получить ссылку на объект из ExpressionTree?
От: Jack128  
Дата: 10.12.19 19:07
Оценка:
Здравствуйте, Codealot, Вы писали:

C>
C>    class Program
C>    {
C>        static void Main(string[] args)
C>        {
C>            var data = new DataClass();
C>            var info = ExpressionUtil.GetMember(() => data.Field1);
C>        }
C>    }

C>    class DataClass
C>    {
C>        public string Field1 = "Field1";
C>    }

C>    static class ExpressionUtil
C>    {
C>        public static MemberInfo GetMember<TResult>(Expression<Func<TResult>> expression)
C>        {
C>            var res = ((MemberExpression)expression.Body).Member;
C>            return res;
C>        }
C>    }
C>


C>Как в этом случае получить кроме MemberInfo еще и указатель на объект data, к которому этот MemberInfo относится?


Пишу без компилятора под рукой, но по доке что типа такого:
((ConstantExpression)(((MemberExpression)expression.Body).Expression)).Value
Re: Как получить ссылку на объект из ExpressionTree?
От: vorona  
Дата: 10.12.19 19:08
Оценка:
Здравствуйте, Codealot, Вы писали:

C>Как в этом случае получить кроме MemberInfo еще и указатель на объект data, к которому этот MemberInfo относится?


Expression
Re[2]: Как получить ссылку на объект из ExpressionTree?
От: Codealot  
Дата: 10.12.19 20:35
Оценка:
Здравствуйте, Jack128, Вы писали:

J>Пишу без компилятора под рукой, но по доке что типа такого:

J>
J>((ConstantExpression)(((MemberExpression)expression.Body).Expression)).Value
J>


Вероятно, ты имел в виду
var tmp = ((ConstantExpression)((MemberExpression)((MemberExpression)expression.Body).Expression).Expression).Value;

Но оно возвращает ссылку на объект замыкания лямбда-функции, а не data.
Re: Как получить ссылку на объект из ExpressionTree?
От: Danchik Украина  
Дата: 10.12.19 23:08
Оценка: +1
Здравствуйте, Codealot, Вы писали:

C>
C>    class Program
C>    {
C>        static void Main(string[] args)
C>        {
C>            var data = new DataClass();
C>            var info = ExpressionUtil.GetMember(() => data.Field1);
C>        }
C>    }

C>    class DataClass
C>    {
C>        public string Field1 = "Field1";
C>    }

C>    static class ExpressionUtil
C>    {
C>        public static MemberInfo GetMember<TResult>(Expression<Func<TResult>> expression)
C>        {
C>            var res = ((MemberExpression)expression.Body).Member;
C>            return res;
C>        }
C>    }
C>


C>Как в этом случае получить кроме MemberInfo еще и указатель на объект data, к которому этот MemberInfo относится?


Вот такую функцию применить к свойству Expression.:
https://github.com/linq2db/linq2db/blob/6c1769216af70b972ca167edbc37a69404c48326/Source/LinqToDB/Expressions/InternalExtensions.cs#L1143

Думаю труда не составит выдернуть.
Re: Как получить ссылку на объект из ExpressionTree?
От: okon  
Дата: 11.12.19 07:42
Оценка:
Здравствуйте, Codealot, Вы писали:



C>Как в этом случае получить кроме MemberInfo еще и указатель на объект data, к которому этот MemberInfo относится?


А должна быть ссылка ? ведь экспрешен он не привязан к инстансу и по идее строится без инстанса. в твоем примере может быть не быть инстанса, экспрешен при этом создасться.
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Re[2]: Как получить ссылку на объект из ExpressionTree?
От: Sinclair Россия http://corp.ingrammicro.com/Solutions/Cloud.aspx
Дата: 11.12.19 07:54
Оценка:
Здравствуйте, okon, Вы писали:

O>А должна быть ссылка ? ведь экспрешен он не привязан к инстансу и по идее строится без инстанса. в твоем примере может быть не быть инстанса, экспрешен при этом создасться.

Более того, она там есть.
Там устроено всё примерно так:
Body->FieldExpression:
  Member->{Field1};
  Expression-> FieldExpression:
    Member->data;
    Expression->ConstantExpression: 
      Value: <>

То есть реальное выражение имеет вид _.data.Field1; здесь _ — это экземпляр сгенерированного класса (замыкания), его полем и является data.
Поэтому в дереве два FieldExpression, идущих один за другим.
Чтобы получить значение того экземпляра, на котором вызывается интересующий нас FieldExpression .Field1, надо по-честному его вычислить.
Процитированный Danchik-ом код как раз занимается constant propagation, плюс динамическим вычислением.
В данном случае достаточно вычислить "_.data". В более сложных случаях потребуется динамический вызов:
()=>DateTime.Now.AddDays(10).Second

Тут по-прежнему в Body имеем MemberExpression, но его Expression в СonstantExpression не упирается. Чтобы получить значение DateTime.Now.AddDays(10), его надо честно выполнить.
Ну, и надо помнить, что никто не мешает построить MemberExpression вовсе без экземпляра:
()=>DateTime.Now
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
http://rsdn.org/File/5743/rsdnaddict.GIF
Re[2]: Как получить ссылку на объект из ExpressionTree?
От: Danchik Украина  
Дата: 11.12.19 10:04
Оценка: 140 (3)
И в догонку

Также если планируете плотно работать с деревьями выражений, обязательно поставьте себе это:
Readable Expressions
Re[3]: Как получить ссылку на объект из ExpressionTree?
От: okon  
Дата: 11.12.19 14:43
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, okon, Вы писали:


O>>А должна быть ссылка ? ведь экспрешен он не привязан к инстансу и по идее строится без инстанса. в твоем примере может быть не быть инстанса, экспрешен при этом создасться.

S>Более того, она там есть.
S>Там устроено всё примерно так:

Интересно,мне пока представлялось что экспрешен это описание как получить данные из определенного выражения,
причем экспрешен можно в последствии применять к конкретным инстансам и получать разные результаты.
Примерно как у рефлекшена FieldInfo дает информацию о том как получить значение поля из инстанса, но не содержит сам инстанс.
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Re[4]: Как получить ссылку на объект из ExpressionTree?
От: Sinclair Россия http://corp.ingrammicro.com/Solutions/Cloud.aspx
Дата: 11.12.19 17:49
Оценка:
Здравствуйте, okon, Вы писали:
O>Интересно,мне пока представлялось что экспрешен это описание как получить данные из определенного выражения,
O>причем экспрешен можно в последствии применять к конкретным инстансам и получать разные результаты.
O>Примерно как у рефлекшена FieldInfo дает информацию о том как получить значение поля из инстанса, но не содержит сам инстанс.
Нет, необязательно. Вы говорите о выражении с параметрами.
Если я сделаю так:
Expression<Func<DateTime, string>> f = (dt) => dt.Second.ToString();

То у меня получится выражение, которое можно будет применять к конкретным инстансам:
Console.WriteLine(f.Compile(DateTime.Now));

У этого выражения есть параметр dt, и оно описывает некоторое преобразование DateTime в строку.
А у ТС выражение просто возвращает строку; у него нет никаких параметров, и никакой инстанс в него передать нельзя.
Можно сказать, что Expression — это способ построить делегат. Вот как раз вызов Compile в примере выше превращает Expression в просто делегат, который можно вызвать.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
http://rsdn.org/File/5743/rsdnaddict.GIF
Re[2]: Как получить ссылку на объект из ExpressionTree?
От: Codealot  
Дата: 12.12.19 21:03
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Вот такую функцию применить к свойству Expression.:

D>https://github.com/linq2db/linq2db/blob/6c1769216af70b972ca167edbc37a69404c48326/Source/LinqToDB/Expressions/InternalExtensions.cs#L1143

D>Думаю труда не составит выдернуть.


Как-то слишком сложно. Пока у меня самое простое решение получилось такое:
            var memberExpr = (MemberExpression)expression.Body;

            var accessExpr = memberExpr.Expression;
            if (accessExpr != null)
            {
                var callExpr = Expression.Lambda(accessExpr);
                var func = (Func<DataClass>)callExpr.Compile();
                var obj = func.Invoke();
            }
Re[3]: Как получить ссылку на объект из ExpressionTree?
От: Danchik Украина  
Дата: 13.12.19 07:05
Оценка: +1
Здравствуйте, Codealot, Вы писали:

C>Здравствуйте, Danchik, Вы писали:


D>>Вот такую функцию применить к свойству Expression.:

D>>https://github.com/linq2db/linq2db/blob/6c1769216af70b972ca167edbc37a69404c48326/Source/LinqToDB/Expressions/InternalExtensions.cs#L1143

D>>Думаю труда не составит выдернуть.


C>Как-то слишком сложно. Пока у меня самое простое решение получилось такое:


[проскипано]

Тоесть вы считаете что постоянная компиляция дерева выражений это есть гуд? Ну ок, зря я напрягался писал эту функцию. Конечно же здесь нужен бенчмарк, но что-то мне подсказывает что и по скорости и по ресурсам ваш простой вариант сольет в чистую в часто употребимых случаях.
Re[4]: Как получить ссылку на объект из ExpressionTree?
От: Codealot  
Дата: 13.12.19 16:21
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Тоесть вы считаете что постоянная компиляция дерева выражений это есть гуд? Ну ок, зря я напрягался писал эту функцию. Конечно же здесь нужен бенчмарк, но что-то мне подсказывает что и по скорости и по ресурсам ваш простой вариант сольет в чистую в часто употребимых случаях.


А кто сказал, что код надо вызывать часто?
В любом случае, на самом деле, самая затратная часть — это построение выражения.
Re[5]: Как получить ссылку на объект из ExpressionTree?
От: Danchik Украина  
Дата: 13.12.19 17:40
Оценка:
Здравствуйте, Codealot, Вы писали:

C>Здравствуйте, Danchik, Вы писали:


D>>Тоесть вы считаете что постоянная компиляция дерева выражений это есть гуд? Ну ок, зря я напрягался писал эту функцию. Конечно же здесь нужен бенчмарк, но что-то мне подсказывает что и по скорости и по ресурсам ваш простой вариант сольет в чистую в часто употребимых случаях.


C>А кто сказал, что код надо вызывать часто?

C>В любом случае, на самом деле, самая затратная часть — это построение выражения.

Даю подсказку, самое затратное — это компиляция лямбда выражения.
Была приведена нормальная функция делающая что надо и как можно эффективней, до чего я дотянулся. Вы же показали наихудшее решение.
Re[6]: Как получить ссылку на объект из ExpressionTree?
От: Codealot  
Дата: 13.12.19 20:57
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Даю подсказку, самое затратное — это компиляция лямбда выражения.


А парсинг кода делегата и генерация дерева выражения ничего не стоит?
Re[6]: Как получить ссылку на объект из ExpressionTree?
От: Codealot  
Дата: 13.12.19 23:39
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Даю подсказку, самое затратное — это компиляция лямбда выражения.


Кстати, раз пошла такая пьянка — а есть ли способ сравнить два дерева на эквивалентность? Ну, кроме очевидного — всё врукопашную?
Re[7]: Как получить ссылку на объект из ExpressionTree?
От: Danchik Украина  
Дата: 14.12.19 11:33
Оценка:
Здравствуйте, Codealot, Вы писали:

C>Здравствуйте, Danchik, Вы писали:


D>>Даю подсказку, самое затратное — это компиляция лямбда выражения.


C>Кстати, раз пошла такая пьянка — а есть ли способ сравнить два дерева на эквивалентность? Ну, кроме очевидного — всё врукопашную?


Эквивалентность относительна
Но да врукопашную. В EF есть comparer, в linq2db есть функция сравнения.
Re[7]: Как получить ссылку на объект из ExpressionTree?
От: Danchik Украина  
Дата: 14.12.19 11:42
Оценка:
Здравствуйте, Codealot, Вы писали:

C>Здравствуйте, Danchik, Вы писали:


D>>Даю подсказку, самое затратное — это компиляция лямбда выражения.


C>А парсинг кода делегата и генерация дерева выражения ничего не стоит?


Тут ваша мысль до меня не дошла. Что с чем сравниваем?
Re[8]: Как получить ссылку на объект из ExpressionTree?
От: Ночной Смотрящий Россия  
Дата: 15.12.19 08:46
Оценка:
Здравствуйте, Danchik, Вы писали:

C>>А парсинг кода делегата и генерация дерева выражения ничего не стоит?

D>Тут ваша мысль до меня не дошла. Что с чем сравниваем?

Возможно он не в курсе, что парсит выражение компилятор.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.