I have been struggling to change the BaseType of a TypeDefinition in specific scenario. Let's say we have below assemblies.
Assembly1:
Class MyAssembly1Class: Test1Class{}
Assembly2:
Class MyAssembly2Class: Test2Class{}
Now I want to change the Base class of "MyAssembly1Class" defined in "Assembly1" to "MyAssembly2Class" defined in assembly2. i.e.
Class MyAssembly1Class: MyAssembly2Class{}
How can this be achieved?
I tried code below:
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;
}
}
}
though it does not throw any exception or error, but on loading the output dll on ildasm.exe, I observed that basetype is not changed.
Let's say the derived class that you are going to change is:
class MyTextBox: TextBox
{
}
Your's class
Class NewTextBox:TextBox
{
}
If you open MyTextClass constructor definition in ildasm you will notice an instruction calling BaseClass constructor i.e. TextBox::.ctor()
This must be replaced with NewTextBox reference.i.e. NewTextBox::.ctor()
try this:
injectionTextBoxRef: Type reference of the class we are replacing with.
textBoxRef: Type reference of the base class of the class you are replacing.
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);
}
}
}
}
}
}