Подключение функции из введенной библиотеки DLL к существующему методу во время выполнения в C#

#c# #cil #monkeypatching #dll-injection

Вопрос:

Во-первых, я не пытаюсь взломать какую-либо игру. Я хочу иметь возможность создавать моды для игр, написанных на C#, без поддержки модов.

Давайте предположим, что игра содержит этот простой класс:

 namespace Game
{
    public class GameLogic
    {
        public void DoThis() {
            Console.WriteLine("Game-Logic");
        }
    }
}
 

DoThis() Метод вызывается каждую секунду.
Теперь я хочу, чтобы следующий ExtraLogic() метод был подключен к началу или концу функции.

 namespace GamePatch
{
    public class Mod
    {
        public void ExtraLogic() {
            Console.WriteLine("Extra-Logic");
        }
    }
}
 

Конечно, сначала я должен ввести мод-dll с моим пользовательским кодом.
Допустим, у меня уже есть загрузчик для внедрения библиотеки dll и вызова DllMain метода.
Поскольку я не могу легко встроить логику в метод в c#, мне, вероятно, придется каким-то образом изменять инструкции в памяти.

Можно ли как-то вставить вызов в ExtraLogic() ? Я знаю, что можно каким-то образом изменить код IL во время выполнения. И что бы мне пришлось делать, если DoThis() бы у метода были параметры, которые я хотел бы использовать в своей логике модов?

Я бы предпочел решение без фреймворков, так как хочу понять процесс выполнения моего метода.

Комментарии:

1. У меня нет никакого опыта в этом, но поиск дал мне отправную точку, с которой я бы начал: MethodRental.swapmethod.

2. может быть, эта библиотека работает для вас: github.com/pardeike/Harmony

3. @JeroenvanLangen, эта ссылка, похоже, предполагает, что вы можете поменять местами только тело метода в динамическом модуле. Но даже если это можно использовать в более общем плане, типы/методы/поля, на которые ссылаются в IL, ссылаются с помощью маркеров метаданных, которые являются специфичными для модуля; маловероятно, что игровые модули будут иметь существующие ссылки на методы, которые будут введены, поэтому я не думаю, что вы можете использовать это для добавления вызовов в любом случае.