Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Method import using Mono.Cecil

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?

like image 297
kreig Avatar asked May 14 '26 22:05

kreig


1 Answers

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 our Main.dll assembly. Then we have to find main module of our Main.dll assembly and then call MainModule.Import(methodFromReferencedAssembly);

like image 181
kreig Avatar answered May 17 '26 10:05

kreig



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!