Я играю с API-интерфейсом C#. Я могу легко загрузить Type
информацию о классах, методах и т. Д. В сборке, однако теперь мне интересно, как я могу загрузить и прочитать код внутри метода?Могу ли я использовать отражение для проверки кода в методе?
ответ
Basic Ответ:
Вы не можете с отражением API (System.Reflection).
Причина в том, что отражение api предназначено для работы над метаданными (тип классов, имя и подпись методов, ...), но не на уровне данных (который сам по себе является потоком IL-потока).
Расширенный Ответ:
Вы можете излучать (но не прочитанные) IL с System.Reflection.Emit (например ILGenerator класс).
С помощью MethodInfo.GetMethodBody()
вы можете получить бинарный IL-поток для реализации метода. Но это обычно совершенно бесполезно само по себе.
Существуют внешние библиотеки (например, Cecil), которые вы можете использовать для чтения/изменения/добавления/удаления кода внутри метода.
Не можете ли вы обратиться к методу через делегат, а затем создать ExpressionTree из делегата и проверить дерево? –
@Matt Greer: Нет. Вы не можете «перепроектировать» тело метода делегата в дерево выражений. – LBushkin
@Matt: Это не даст вам код * внутри * метода, вы просто получите 'MethodCallExpression', который даст вам доступ к тому же' MethodInfo', который вы могли бы получить более непосредственно с API отражения. – Aaronaught
No
Это функция, предназначенная для следующей версии C#. Вы можете использовать CodeDom, чтобы получить больше информации, чем отражение, но вы еще не можете допросить дерево разбора.
Ну, всегда есть моно, в моно компилятор - это сервис, и вы можете получить деревья синтаксического анализа во время выполнения.
Лучший вопрос, почему вы хотите?
Да, должен быть способ достижения этого: это также делает инструмент .NET Reflector. Однако не могу сказать, как это делается.
Почему вы не отражаете отражатель;) – ntziolis
Рефлектор не использует отражение, по крайней мере, не в контексте концепции .NET. Он фактически анализирует файл PE и сбрасывает код IL из секции .TEXT. Затем выполняется очень умное и крутое сопоставление шаблонов для сопоставления/декомпиляции IL обратно на целевой язык. –
Если вам не нужно делать это в режиме реального времени, взгляните на Reflector. Вы можете разобрать любую сборку .NET (включая основные DLL-файлы MS) и посмотреть код на выбранном вами языке. Это может быть очень образовательных.
Обновление Кто-нибудь пытался использовать рефлектор на отражателе, чтобы выяснить, как это делается?
Обратите внимание, что это не де-оптимизирует код. Поэтому, если для IL был оптимизирован компилятор, он не возвращается к исходному источнику сборки, а к немного менее написанной на заказ оптимизированной версии.Его опрятный способ увидеть, что вы могли бы сделать наиболее эффективно. – DevelopingChris
Вы не можете использовать Reflector on Reflector. Попробуй и посмотри, у тебя получится приятный сюрприз. – Aaronaught
Рефлектор зашифрован таким образом, что он не может отразиться на себе, я думаю, что они использовали DotFuscator для этого. – DevelopingChris
Это зависит от того, что вы имеете в виду, прочитав код. Существует 4 формы кода.
1- Исходный код, например. оригинальный C# или VB.NET - Нет, вы не можете получить это с отражением
2- Символический IL кодом - Нет, вы не можете получить это с отражением
3- Код сборки JITed - Нет, вы не можете получить это с отражением
4- байты IL, фактические байты, которые ИЛ скомпилированы, это вы может получить.
Посмотрите на MethodBase.GetMethodBody(), например, вы можете получить байты IL, локальные переменные, кадры исключений и т. Д. http://msdn.microsoft.com/en-us/library/system.reflection.methodbase.getmethodbody.aspx
'GetMethodBody()' самый близкий, который вы можете получить, я думаю. – LBushkin
Вы вид может. Соответствующая функция - MethodBase.GetMethodBody.
Это не совсем полезный API. Вы можете получить некоторую базовую информацию о том, что находится внутри метода, и вы можете получить IL как массив байтов. Вот и все.
Там есть немного лучше API в Mono.Cecil библиотеки, которая выставляет на MethodDefinition
класс с его собственной MethodBody
реализации, которая содержит фактические Instructions
, так что вы не должны интерпретировать необработанные байты-код. Тем не менее, если вы хотите получить код C# из него à la Reflector, вы будете сильно разочарованы. Кроме того, Сесил не очень хорошо документирован.
Если вы все еще хотите попробовать, то удачи.
Есть теперь библиотеки/пакеты, которые позволяют проверить код метода и даже декомпилировать его Expression
:
Что это сценарий, который делает это полезным? Это ломает одного из основных арендаторов ОО, который является инкапсуляцией. Но, кроме того, код как ИЛ не совсем то же самое. – DevelopingChris
@DevelopingChris: Если вы пишете отладчик или инструмент анализа кода, может оказаться полезным загрузить сборку и проанализировать тело метода. Фактически, это такие инструменты, как FxCop. – LBushkin
Целевой аудиторией .NET являются корпорации США (и, во-вторых, возможно, некоторые малые предприятия). Если вы можете обойти .NET obfuscation, программное обеспечение (дорогое производство) может легко попасть в кончики пальцев конкурента. – micahhoover