jeudi 31 octobre 2019

Calling a method of existing object using IL Emit

I am attempting to write an attribute based interceptor (something similar to DynamicProxy). The idea being, based on certain custom attributes, a method inside that attribute would be called, i.e.

  • Call a method inside attribute class before actual method is called.
  • Call the actual method.

I am able to override existing method using MethodBuilder and TypeBuilder. However, I can't figure out how to call the method inside the Attribute.

My code :

static void CreateMethods<T>(TypeBuilder tb)
        {
            foreach (var methodToOverride in typeof(T).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
            {
                var attribute = (ProxyMethod)methodToOverride.GetCustomAttribute(typeof(ProxyMethod));
                if (attribute == null)
                    continue;

                MethodBuilder methodBuilder = tb.DefineMethod(
                    methodToOverride.Name,
                    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"); //step1
                il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); //step1

                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Call, methodToOverride);
                il.Emit(OpCodes.Ret);

                tb.DefineMethodOverride(methodBuilder, methodToOverride);
            }
        }

What I think I should do is load attribute onto stack, then call attribute.attributeMethod() by emitting a call to the MethodInfo. However, everywhere I look, I can find examples of creating a new instance of the objected using OpCodes.NewObj. I don't want to use this, because attributes may have parameters.

I can't think of any of calling the method inside attribute class (which would replace step1 comment).





Aucun commentaire:

Enregistrer un commentaire