Получить BindingFlags из PropertyInfo

У меня есть объект, полученный с помощью вызова Type.GetProperty(), и я хотел бы знать комбинацию флагов привязки, используемую для его получения.

Когда я проверяю объект в отладчике, я вижу, что это System.Reflection.RuntimePropertyInfo со свойством BindingFlags, содержащим нужное мне значение. Однако кажется, что это внутренний тип, потому что компилятор не распознает его как допустимый тип данных. Вместо этого он рассматривает значение, возвращаемое Type.GetProperty(), как System.Reflection.PropertyInfo, которое, как ни странно, не содержит свойства BindingFlags.

Может ли кто-нибудь предложить ссылку, которую я мог бы добавить в проект, чтобы компилятор понял тип System.Reflection.RuntimePropertyInfo, или, может быть, альтернативный способ получить значение BindingFlags? Я полагаю, что мог бы сохранить значение, которое я использую в вызове Type.GetProperty(), и нести его вместе с объектом [Runtime]PropertyInfo, куда бы он ни пошел, но это выглядит некрасиво.

Я (все еще!) использую .NET framework 3.5, если это поможет. Спасибо!

РЕДАКТИРОВАТЬ:

Контекстом всего этого является простой решатель выражений, который дает моим пользователям доступ к ограниченному набору глобальных объектов и некоторым их свойствам для создания настраиваемых уведомлений с переменной информацией, поступающей из базы данных. Во время разработки мои пользователи определяют что-то вроде "Hello, [=Shipment.Recipient.Name]. Your order [=Shipment.Id] is ready for delivery.", а позже, когда уведомление отображается, система выводит "Здравствуйте, Боб. Ваш заказ 12345 готов к доставке".

Я рассматривал возможность использования классов CodeProvider, предоставляемых .NET Framework, но мне нужно, чтобы мой код работал в среде со средним уровнем доверия без установленной Visual Studio, и я также не хочу раскрывать слишком много функций, поскольку существует вероятность того, что третьи стороны будет иметь доступ к конструктору уведомлений, и я не хочу, чтобы кто-либо вводил какой-либо опасный код в уведомления.

Поэтому вместо этого я написал простой синтаксический анализатор/компилятор/интерпретатор выражений, который обеспечивает функциональность, которую я хочу предоставить, и не более того; то есть чтение свойств, конкатенация строк, основные арифметические операции и операции с датой/временем. Выражения анализируются на согласованность, проверяются типы и генерируется псевдоассемблерный код, который можно сериализовать и хранить в виде последовательности байтов для последующего воссоздания и выполнения на определенном наборе экземпляров объекта, чтобы получить окончательное выражение. результат.

Анализ/компиляция и выполнение происходят в разных контекстах, в разное время, с разными сеансами и, возможно, даже на разных машинах, поэтому мне нужно иметь возможность воссоздавать цепочки вызовов с нуля в виде серий объектов PropertyInfo из объекта базового типа, полученного через его полностью квалифицированное имя.

Пока что я изучаю только свойства BindingFlags.Public | BindingFlags.Instance при анализе цепочек вызовов, но я вижу, как в будущем я мог бы расширить реализацию, включив в нее такие вещи, как статические свойства или что-то еще. Поэтому я предпочитаю не использовать какой-либо конкретный набор флагов привязки и не хочу тратить время на его обнаружение во время выполнения выражения, поскольку я знаю его значение во время компиляции; Я бы предпочел сохранить его в сериализованной программе, чтобы я мог передать его непосредственно Type.GetProperty(), когда реконструирую цепочку вызовов.

Но код, в котором я сериализую скомпилированное выражение, определенно не находится в той же локальной области, что и код, в котором я проверяю, является ли какой-либо фрагмент текста, введенный пользователем, допустимым свойством в текущей цепочке вызовов, поэтому к тому времени, когда мне нужно значение Я давно забыл параметры, переданные в функцию Type.GetProperties(), которую я вызывал при анализе. Вот как я обнаружил, что RuntimePropertyInfo содержит значение, которое я хочу сохранить, но не могу его получить, потому что компилятор .NET считает, что это экземпляр его базового класса PropertyInfo, который не содержит свойства BindingFlags. Очень расстраивает.

Если мне нужно сохранить параметры, используемые где-то еще, чтобы я мог получить их во время сериализации программы, я это сделаю. Но если бы я мог просто привести объект к экземпляру RuntimePropertyInfo и прочитать его свойство BindingFlags, моя жизнь была бы немного проще.


person Carvo Loco    schedule 11.11.2016    source источник
comment
Это не так, как это работает, BindingFlags имеет значение, когда вы создаете объект PropertyInfo. Получив его, вы можете использовать его члены, обычно GetValue(), возможно, SetValue(). Вы должны иметь некоторое представление о том, какой тип объекта или значения хранит свойство. Если вы этого не сделаете, вы не сможете правильно использовать Get/SetValue(). В противном случае отражение не является лазейкой для внутренних деталей реализации, которые недоступны или недокументированы.   -  person Hans Passant    schedule 11.11.2016
comment
Спасибо, Ганс. Да, я знаю, что значение имеет значение при создании объекта PropertyInfo, поэтому я хочу его получить. Я хочу сохранить его в другом месте, чтобы использовать его позже, когда я хочу воссоздать тот же объект PropertyInfo из другого экземпляра того же объекта Type. Любые идеи?   -  person Carvo Loco    schedule 11.11.2016
comment
Очень трудно догадаться, почему вы хотите получить его, если это ваш собственный код, указывающий BindingFlags. Или почему это важно. Другой экземпляр того же объекта Type также не имеет смысла, существует только один экземпляр объекта Type для определенного типа. Он описывает тип, а не объект. Единственный способ дать вам полезный ответ — это описать реальную проблему, которую вы пытаетесь решить. Вы только попытались описать подход, и это звучит совсем не кошерно.   -  person Hans Passant    schedule 11.11.2016
comment
PI будет вести себя одинаково независимо от того, какие BindingFlags использовались для его извлечения. Таким образом, вы можете повторно получить объект, просто сохранив его тип и имя.; Декомпиляция кода выглядит так, что член m_bindingFlags — это внутренняя оптимизация, помогающая при поиске в кеше. Похоже на хак, БФ надо хранить в кеше, а не в ИП.   -  person usr    schedule 11.11.2016
comment
Еще раз спасибо за ваши комментарии, @HansPassant. Я предоставил некоторый контекст относительно того, почему мне может понадобиться такая вещь.   -  person Carvo Loco    schedule 11.11.2016
comment
Вы тоже можете ответить на мой комментарий? Различные объекты PI с разными элементами BF будут вести себя одинаково. Вы можете всегда получить эквивалентный PI, просто указав его тип и (точное) имя.   -  person usr    schedule 11.11.2016
comment
Извините, @usr, я занят несколькими делами; большое спасибо за ваше понимание. Меня не так беспокоит то, что объекты PI ведут себя иначе, чем то, что функция Type.GetProperty() возвращает значение null из-за неправильной комбинации BindingFlags, но я попробую без флагов привязки, как вы предлагаете. В конце концов, возможно, я пытаюсь решить несуществующую проблему. Спасибо!   -  person Carvo Loco    schedule 11.11.2016
comment
Если вы просто укажете точное имя и Public|Private|Inst|Static, он найдет любое свойство. BF — это просто параметры поиска, вы можете просто разрешить все. Даже если это по какой-то причине не работает, вы можете пойти GetP(Public) ?? GetP(Private). Невозможно иметь несколько свойств с одним и тем же именем (за исключением индексаторов, я думаю...).   -  person usr    schedule 11.11.2016


Ответы (1)


person    schedule
comment
Спасибо! Но как это помогает? - person Carvo Loco; 19.04.2018
comment
Я имею в виду... проблема заключается не в том, чтобы получить некоторые частные BindingFlags вверх по иерархии классов из PropertyInfo, а в том, чтобы получить их из необъявленного класса, производного от PropertyInfo. - person Carvo Loco; 19.04.2018
comment
Извините, я неправильно понял вашу проблему. На самом деле это кажется довольно сложным. Лично я, насколько я понимаю, потенциально использовал бы Roslyn (я сделал это, чтобы включить макросы в свой собственный код). Это относительно легко теперь, когда Roslyn более стабилен (но требует довольно больших зависимостей). В противном случае я бы просто разобрал код, даже не компилируя его, а только интерпретировал бы его, что было бы медленнее, но безопаснее. Извините, я мало чем могу помочь. Удачи. - person Eric Ouellet; 19.04.2018