Модифицировать операнд 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, чтобы выяснить, какой метод следует использовать, но я не могу найти ни одного. У вас есть ссылка?