Есть ли способ связать управляемую функцию в С#, как я бы неуправляемой функции в С++?

В С++ я получаю адрес функции и перезаписываю первые несколько байтов в jmp для своей функции, делаю некоторые вещи, восстанавливаю исходные байты и вызываю исходную функцию.

Можно ли сделать что-то подобное на С#?

Ответ 1

API-интерфейс .NET Profiler - это самый близкий метод перехвата Microsoft, одобренный Microsoft, во время выполнения. Как уже упоминалось, это несколько сложно реализовать, и я не знаю о библиотеке, которая упрощает ее реализацию с использованием исключительно управляемого кода.

Изучая варианты этого сам несколько месяцев назад, я наткнулся на CLR Method Injection, которая представляет собой статью с исходным кодом, объясняющую, как методы перехвата во время выполнения. Я считал, что сам это использовал, и даже имел образец проекта, но в конечном итоге пришел к выводу, что мне нужно больше, чем перехват методов, и потребуется другое решение. Однако этот подход напрямую отвечает на ваш вопрос.

Наконец, то, что я закончил, заключалось в разработке Afterthought в качестве альтернативы с открытым исходным кодом для PostSharp, который выполняется как шаг после компиляции и позволяет вам изменять существующие методы для вызова другого кода или полностью заменить реализации метода. Я сейчас работаю над новым синтаксисом жидкости, в который я буду включать образец теперь, чтобы предоставить вам пример, который поможет вам понять, как этот подход AOP будет отвечать вашим потребностям:

Methods
    .Named("Sum")
    .WithParams<int[]>()
    .Before((T instance, ref int[] values)
        => { var s = new Stopwatch(); s.Start(); return s; })
    .After((instance, stopwatch, values)
        => instance.Result = (int)stopwatch.ElapsedMilliseconds);   

В этом случае, изменяя существующий тип с помощью метода Sum, я представляю код до и после метода для измерения времени выполнения. После запуска Afterthought против исходного скомпилированного класса результирующий метод Sum будет иметь вызовы для этих лямбда-выражений (компилятор С# просто превращает их в статические методы) до и после тела метода. Я мог бы так же легко назвать Implement и заменить всю реализацию метода.

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

Ответ 2

Вы хотите подключиться во время выполнения или хотите исправить двоичный файл?

Чтобы подключиться во время выполнения, вы можете использовать профилирование api (относительно сложно): http://msdn.microsoft.com/en-us/magazine/cc188743.aspx

Чтобы подключиться к компилятору, вы можете использовать переписчик IL, например PostSharp.

Ответ 3

Техника, которую вы ищете, называется AOP - Aspect Oriented Programming. Вы можете найти несколько фреймворков для С#, если немного поблескиваете.

Обновление. Вы можете найти много ссылок и информации в этом вопросе: Встроенный АОП на С# - это на пути?