mercredi 30 octobre 2019

Loading an existing object on top of stack using reflection emit

I'm trying to implement method interception and currently I am doing this by creating a proxy, which returns a dynamically created object with the same fields and properties. The methods however, would be overridden to do something like

  • Get all attributes associated with the method and execute some code based on those attributes (currently just Console.WriteLine
  • Execute the actual method
  • Execute some other code based on the original attributes.

So far, I am able to override existing virtual method and call the aforementioned Console.WriteLine, but I am unable to call the actual method.

This is what I have so far

static void CreateMethod<T>(TypeBuilder tb)
        {
            var methodToOverride = typeof(T).GetMethod("Bar");
            var attribute = methodToOverride.GetCustomAttribute(typeof(MethodProxyAttribute));
            MethodBuilder methodBuilder = tb.DefineMethod(
                /* Change method name here */
                "Baz",
                MethodAttributes.Public
                | MethodAttributes.HideBySig
                | MethodAttributes.NewSlot
                | MethodAttributes.Virtual
                | MethodAttributes.Final,
                CallingConventions.HasThis,
                methodToOverride.ReturnType,
                Type.EmptyTypes
            );

            ILGenerator il = methodBuilder.GetILGenerator();

            il.Emit(OpCodes.Ldstr, "The I.M implementation of C");
            il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
            il.Emit(OpCodes.Ret);

            tb.DefineMethodOverride(methodBuilder, methodToOverride);
        }

I know possible solutions can be to use

  • OpCode.NewObj to create new instance of an object and call the method.
  • Use a static class with a static dictionary as V-Table to look up the original method

Is there any way to call the original method by emitting the call though?





Aucun commentaire:

Enregistrer un commentaire