Franmcod
Franmcod

Reputation: 359

Create an Instance of a Type, via Emit(Opcodes.Call, methodinfo)

I'm using Reflection, and ilGenerator, to create a .Exe, that calls a method from a DLL.

My problem is when it is an instance method, I have to put in stack the instance before calling the method. Therefore I have a method in C#, that creates and returns this instance. It is throwing System.MethodAccessException.

My question is, is this even possible? How does it work? By doing this in IL, il.Emit(Opcodes.call, methodInfo), in the call that creates the .exe, when in runtime, how does it know what method to call? Does the method that I want to call, go to the .exe assembly? I'm very confused by this.

I go to the DLL, get the type, get the MethodInfo that I want to call. I create a new Assembly->AssemblyBuilder->ModuleBuilder->TypeBuilder this new type that I am creating is extending the Type from the DLL:

 TypeBuilder tb = mb.DefineType("TypeApp" + typeName, baseType.Attributes, DLLType);

I create the MethodBuilder to be the entry point of the new type:

MethodBuilder metb = tb.DefineMethod("Main", MethodAttributes.Public |
            MethodAttributes.Static, typeof(void), argsArray);
ab.SetEntryPoint(metb);

Then I generate IL for the Main method:

ILGenerator il = metb.GetILGenerator();

il.Emit(OpCodes.Call, callcreateInstanceMethodInfo);

The IL continues, but I don't fully understand this so far so...

Then I create the .exe

 tb.CreateType();
 ab.Save(typeName + methodName + ".exe");

Upvotes: 3

Views: 381

Answers (1)

Brian Reichle
Brian Reichle

Reputation: 2856

It is throwing System.MethodAccessException.

Are you trying to call a method that is not normally visible to the type you are generating (calling a private or internal method, calling a protected method in a class you don't inherit from). I believe it is possible by disabling verification, but that increases the security requirements of the code which is a problem if you need to run in a partial trust environment.

in the call that creates the .exe, when in runtime, how does it know what method to call?

The emitted IL contains a 4-byte metadata token, this is essentially a reference to a record in one of the metadata tables in the generated module (either the MethodDef or MemberRef table). If it's MethodDef token, then it's a direct reference to the methods definition, if it's a MemberRef token then it will provide enough information to identify the correct assembly/class/method to call.

The code you show generating the IL, indicates that you using the call opcode. If you are calling a virtual method, then you should use callvirt instead (although you can use call for non-abstract methods, it will result in calling the specific implementation ... even if it was overridden, this can be unexpected and I read somewhere that there were added security requirements for using call on a virtual method of another object).

Upvotes: 2

Related Questions