2010-04-22 5 views
33

Я играю с API-интерфейсом C#. Я могу легко загрузить Type информацию о классах, методах и т. Д. В сборке, однако теперь мне интересно, как я могу загрузить и прочитать код внутри метода?Могу ли я использовать отражение для проверки кода в методе?

+0

Что это сценарий, который делает это полезным? Это ломает одного из основных арендаторов ОО, который является инкапсуляцией. Но, кроме того, код как ИЛ не совсем то же самое. – DevelopingChris

+8

@DevelopingChris: Если вы пишете отладчик или инструмент анализа кода, может оказаться полезным загрузить сборку и проанализировать тело метода. Фактически, это такие инструменты, как FxCop. – LBushkin

+0

Целевой аудиторией .NET являются корпорации США (и, во-вторых, возможно, некоторые малые предприятия). Если вы можете обойти .NET obfuscation, программное обеспечение (дорогое производство) может легко попасть в кончики пальцев конкурента. – micahhoover

ответ

31

Basic Ответ:

Вы не можете с отражением API (System.Reflection).

Причина в том, что отражение api предназначено для работы над метаданными (тип классов, имя и подпись методов, ...), но не на уровне данных (который сам по себе является потоком IL-потока).

Расширенный Ответ:

Вы можете излучать (но не прочитанные) IL с System.Reflection.Emit (например ILGenerator класс).

С помощью MethodInfo.GetMethodBody() вы можете получить бинарный IL-поток для реализации метода. Но это обычно совершенно бесполезно само по себе.

Существуют внешние библиотеки (например, Cecil), которые вы можете использовать для чтения/изменения/добавления/удаления кода внутри метода.

+1

Не можете ли вы обратиться к методу через делегат, а затем создать ExpressionTree из делегата и проверить дерево? –

+1

@Matt Greer: Нет. Вы не можете «перепроектировать» тело метода делегата в дерево выражений. – LBushkin

+0

@Matt: Это не даст вам код * внутри * метода, вы просто получите 'MethodCallExpression', который даст вам доступ к тому же' MethodInfo', который вы могли бы получить более непосредственно с API отражения. – Aaronaught

1

No
Это функция, предназначенная для следующей версии C#. Вы можете использовать CodeDom, чтобы получить больше информации, чем отражение, но вы еще не можете допросить дерево разбора.

Ну, всегда есть моно, в моно компилятор - это сервис, и вы можете получить деревья синтаксического анализа во время выполнения.

Лучший вопрос, почему вы хотите?

1

Да, должен быть способ достижения этого: это также делает инструмент .NET Reflector. Однако не могу сказать, как это делается.

+1

Почему вы не отражаете отражатель;) – ntziolis

+9

Рефлектор не использует отражение, по крайней мере, не в контексте концепции .NET. Он фактически анализирует файл PE и сбрасывает код IL из секции .TEXT. Затем выполняется очень умное и крутое сопоставление шаблонов для сопоставления/декомпиляции IL обратно на целевой язык. –

2

Если вам не нужно делать это в режиме реального времени, взгляните на Reflector. Вы можете разобрать любую сборку .NET (включая основные DLL-файлы MS) и посмотреть код на выбранном вами языке. Это может быть очень образовательных.

Обновление Кто-нибудь пытался использовать рефлектор на отражателе, чтобы выяснить, как это делается?

+1

Обратите внимание, что это не де-оптимизирует код. Поэтому, если для IL был оптимизирован компилятор, он не возвращается к исходному источнику сборки, а к немного менее написанной на заказ оптимизированной версии.Его опрятный способ увидеть, что вы могли бы сделать наиболее эффективно. – DevelopingChris

+0

Вы не можете использовать Reflector on Reflector. Попробуй и посмотри, у тебя получится приятный сюрприз. – Aaronaught

+1

Рефлектор зашифрован таким образом, что он не может отразиться на себе, я думаю, что они использовали DotFuscator для этого. – DevelopingChris

16

Это зависит от того, что вы имеете в виду, прочитав код. Существует 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

+0

'GetMethodBody()' самый близкий, который вы можете получить, я думаю. – LBushkin

9

Вы вид может. Соответствующая функция - MethodBase.GetMethodBody.

Это не совсем полезный API. Вы можете получить некоторую базовую информацию о том, что находится внутри метода, и вы можете получить IL как массив байтов. Вот и все.

Там есть немного лучше API в Mono.Cecil библиотеки, которая выставляет на MethodDefinition класс с его собственной MethodBody реализации, которая содержит фактические Instructions, так что вы не должны интерпретировать необработанные байты-код. Тем не менее, если вы хотите получить код C# из него à la Reflector, вы будете сильно разочарованы. Кроме того, Сесил не очень хорошо документирован.

Если вы все еще хотите попробовать, то удачи.