Невозможно установить базовый класс типа с помощью Mono Cecil

Я пытаюсь использовать Mono Cecil для управления DLL. Что я хочу сделать, так это установить базовый тип некоторых классов на System.MarshalByRefObject из mscorlib.dll. Я использую следующий код.

var assembly = AssemblyDefinition.ReadAssembly(inputtarget);
var types = assembly.MainModule.Types;
var myTypesToChange = types.Where(...).Select(t => t);
var baseType = AssemblyDefinition.ReadAssembly(@"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscorlib.dll").MainModule.Types.Where(t => t.Name.Contains("MarshalByRefObject")).Select(t => t).First();
foreach (var myType in myTypesToChange)
{
    myType.BaseType = baseType;
}
assembly.Write(outputtarget);

В выводе базовый тип не задан!

Когда я устанавливаю BaseType в TypeReference, выбранный из существующей сборки, он правильно устанавливает базовый тип.

Я считаю, что то, что я делаю, очень похоже на то, как это делается, как это предлагается в этот ответ на комментарий к статье Code Project Изменение кода IL с помощью Mono.Cecil:

Да, вы можете переписать базовый тип любого класса:

var assembly = AssemblyDefinition.ReadAssembly(AssemblyPath); 
var mainModule = assembly.MainModule;

var companyType = mainModule.Types.First(t => t.Name == "Company");
var ownerType = mainModule.Types.First(t => t.Name == "Owner");

ownerType.BaseType = companyType;
assembly.Write(AssemblyPath);

Это должно быть легко! Что я делаю неправильно?


person simpleusr    schedule 10.12.2014    source источник
comment
Я понимаю, что был задан связанный с этим вопрос: stackoverflow.com/questions/22911825/ .. Пожалуйста, помогите!!!!   -  person simpleusr    schedule 10.12.2014
comment
Если тот же вопрос уже задавался ранее, как вы утверждаете, то ваш вопрос является дубликатом и должен быть закрыт.   -  person stakx - no longer contributing    schedule 11.12.2014


Ответы (1)


Проблема в том, что метаданные сборки не учитываются. Каждая сборка имеет метаданные, которые содержат информацию, связанную со ссылками на сборки и использованием типов.

Что вам нужно сделать, так это импортировать тип MarshalByRefObject в mainModule:

var assembly = assemblyDef.AssemblyDefinition;
var types = assembly.MainModule.Types;
var myTypesToChange = types.Select(t => t);
var baseType = AssemblyDefinition.ReadAssembly(@"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscorlib.dll").MainModule.Types.Where(t => t.Name.Contains("MarshalByRefObject")).Select(t => t).First();
foreach (var myType in myTypesToChange)
{
    myType.BaseType = mainModule.Import(baseType);
}

Помимо расширения метаданных, необходимо изменить CIL-код конструкторов, чтобы вызывать конструктор нового базового класса вместо исходного.

Наконец, предложение. Я думаю, что TypeReference для MarshalByRefObject можно извлечь более элегантным способом:

var baseType = mainModule.Import(typeof (MarshalByRefObject));
for (...)
{
    myType.BaseType = baseType;
}
person user3636971    schedule 26.08.2015