Модифицировать операнд IL с помощью Mono.Cecil

Я работаю с внешней библиотекой, в которой есть ошибка. Я выследил ошибку, это неправильное приведение, похожее на:

var projectionBufferBase = startBuffer as IProjectionBuffer;

Где это должно быть:

var projectionBufferBase = startBuffer as IProjectionBufferBase;

Глядя на IL, это представляется как:

isinst Microsoft.VisualStudio.Text.Projection.IProjectionBuffer

Я использовал Mono.Cecil для загрузки DLL и поиска строк, которые я хотел бы изменить, но я не уверен, как изменить операнд перед сохранением DLL обратно на диск.

MethodDefinition brokenMethod = ...

foreach (var item in brokenMethod.Body.Instructions)
{
    //Find the instruction with the incorrect operand
    if (item.Operand != null && item.Operand.ToString() == "Microsoft.VisualStudio.Text.Projection.IProjectionBuffer")
    {
        Console.WriteLine(item);
        //What do I assign here? It can't be a string.
        item.Operand = ...
    }
}

assemblyDefinition.Write(@"C:\Users\...\DirectoryWithDLLs\newDLL.dll");

item.Operand принимает объект, но если я установил его как строку, он не сможет записать DLL на диск. Могу ли я заменить операнд? Или мне создать совершенно новую инструкцию IL и заменить старую?

1 ответ

Решение

Со страницы документации Cecil здесь:

Чтобы вставить инструкцию перед другой:

var processor = method.Body.GetILProcessor();
var newInstruction = processor.Create(OpCodes.Call, someMethodReference);
var firstInstruction = method.Body.Instructions[0];

processor.InsertBefore(firstInstruction, newInstruction);

Вы правы. Вы не можете действительно назначить строку операнду здесь. Вам нужно использовать Cecil API для создания приведения к типу. Сначала нужно посмотреть, как это делается в IL, а затем скопировать его с помощью API.

В настоящее время я пытаюсь изучить документацию API, чтобы выяснить, какой метод следует использовать, но я не могу найти ни одного. У вас есть ссылка?

Другие вопросы по тегам