我一直在努力改变特定场景中TypeDefinition的BaseType。假设我们有以下装配。
Assembly1:
Class MyAssembly1Class:Test1Class {}
Assembly2:
Class MyAssembly2Class:Test2Class {}
现在我想将“Assembly1”中定义的“MyAssembly1Class”的Base类更改为assembly2中定义的“MyAssembly2Class”。即。
Class MyAssembly1Class:MyAssembly2Class {}
如何实现这一目标?
我尝试了以下代码:
public static void UpdateDerviedTextBoxTypes(AssemblyDefinition main, AssemblyDefinition otherAssembly)
{
TypeReference injectionTextBoxRef = null;
injectionTextBoxRef = otherAssembly.MainModule.GetType("MyAssembly2Class. Test2Class");
if (injectionTextBoxRef == null)
{
return;
}
foreach (TypeDefinition type in main.MainModule.Types)
{
if (type.IsClass && type.BaseType != null && type.BaseType.FullName == "MyAssembly1Class.Test1Class")
{
type.BaseType = injectionTextBoxRef;
}
}
}
虽然它不会抛出任何异常或错误,但是在ildasm.exe上加载输出dll时,我发现basetype没有改变。
答案 0 :(得分:1)
让我们说你要改变的派生类是:
类MyTextBox:TextBox { }
你的班级
类NewTextBox:TextBox {
}
如果在ildasm中打开MyTextClass构造函数定义,您会注意到一条指令调用BaseClass构造函数,即TextBox ::。ctor() 必须用NewTextBox reference.i.e替换它。 NewTextBox ::。构造函数()
试试这个:
injectionTextBoxRef:键入我们要替换的类的引用。
textBoxRef:键入要替换的类的基类的引用。
foreach (TypeDefinition type in main.MainModule.Types)
{
if (type.IsClass && type.BaseType != null && (type.BaseType.FullName ==
"System.Windows.Controls.TextBox" || type.BaseType.FullName == "Windows.UI.Xaml.Controls.TextBox"))
{
type.BaseType = injectionTextBoxRef;
foreach (MethodDefinition method in type.Methods)
{
if (method.Body == null)
continue;
if (method.IsConstructor)
{
for (int i = 0; i < method.Body.Instructions.Count; i++)
{
var inst = method.Body.Instructions[i];
if (inst.Operand == null)
continue;
if (inst.OpCode == OpCodes.Call && (inst.Operand.ToString().Contains("System.Void System.Windows.Controls.TextBox::.ctor()") || inst.Operand.ToString().Contains("System.Void Windows.UI.Xaml.Controls.TextBox::.ctor()")))
{
var next = method.Body.Instructions[i + 1];
var temp = inst;
inst = Instruction.Create(OpCodes.Call, textBoxRef);
inst.Next = temp.Next;
inst.Offset = temp.Offset;
inst.Previous = temp.Previous;
inst.SequencePoint = temp.SequencePoint;
var processor = method.Body.GetILProcessor();
processor.Remove(temp);
processor.InsertBefore(next, inst);
}
}
}
}
}
}