Help me please with method import. I want to weave assembly and inject method call reference from base class defined in the other assembly (in fact it's the assembly where weaving code is defined).
private void InsertCallSetReference()
{
//Get the load instruction to replace
var ilProcessor = Property.SetMethod.Body.GetILProcessor();
var argumentLoadInstructions = ilProcessor.Body.Instructions.ToList();
MethodReference methodReference = ImportMethod("SetReference");
foreach (var instruction in argumentLoadInstructions)
{
if (instruction.OpCode == OpCodes.Stfld)
{
ilProcessor.InsertAfter(instruction, ilProcessor.Create(OpCodes.Call, methodReference));
ilProcessor.InsertAfter(instruction, ilProcessor.Create(OpCodes.Ldarg_1));
ilProcessor.InsertAfter(instruction, ilProcessor.Create(OpCodes.Ldstr, DBFieldName));
ilProcessor.InsertAfter(instruction, ilProcessor.Create(OpCodes.Ldarg_0));
ilProcessor.Remove(instruction);
break;
}
}
}
Method import code works just fine and returns method reference
private MethodReference ImportMethod(string name)
{
var type = MongoConnectModule.Import(typeof(BaseDataObject));
return MongoConnectModule.Import(type.Resolve().Methods.First(m => m.Name == name));
}
But after AssemblyDefinition Write call it throws me an error:
C:\dev\MongoConnect\WeavingTaskTest\Weaving\CodeWeaving.targets(32,5): error MSB4018: System.ArgumentException: Member 'System.Void MongoConnect.BaseDataObject::SetProperty(System.String,System.Object)' is declared in another module and needs to be imported
_assemblyDefinition.Write(_assemblyPath, new WriterParameters() { WriteSymbols = true, SymbolWriterProvider = debugWriterProvider });
Any idea how I could do that?
I've found the solution. The reason was really funny.
Module.Import()
method must be called from current module we want to modify, not the module where method is defined. It is not clear from original docs.For example, we want to add some method defined in the
Referenced.dll
assembly to ourMain.dll
assembly. Then we have to find main module of ourMain.dll
assembly and then callMainModule.Import(methodFromReferencedAssembly);