unity 2.0 interception 学习2

上一篇:unity 2.0 interception 学习1

对于VirtualMethodInterceptor,还有需要澄清的地方:

1、代理是如何实现IInterceptingProxy接口的:

(1)先从以下实验代码了解 动态创建类创建的类如何实现接口: 

      public interface IHello
        {
            void SayHello();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            AppDomain domain = AppDomain.CurrentDomain;
            //动态程序集
            AssemblyBuilder assemblyBuilder = domain.DefineDynamicAssembly(new AssemblyName("test"), AssemblyBuilderAccess.Run);
            //动态程序集模块
            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("helloWorldTypeBuilder");
            //运行时创建类
            TypeBuilder helloWorldTypeBuilder = moduleBuilder.DefineType("hello");
            //声明实现IHello接口
            helloWorldTypeBuilder.AddInterfaceImplementation(typeof(IHello));
            //定义SayHello方法
            MethodBuilder myMethodBuilder =
               helloWorldTypeBuilder.DefineMethod("SayHello2",
                                    MethodAttributes.Public | MethodAttributes.Virtual,
                                    null,
                                    null);
            
            // 方法体开始
            ILGenerator myMethodIL = myMethodBuilder.GetILGenerator();

            myMethodIL.Emit(OpCodes.Ldstr, "hello world");
            
            Type[] showParameters = { typeof(String) };
            MethodInfo messageBoxShow = typeof(MessageBox).GetMethod("Show", showParameters);
            myMethodIL.Emit(OpCodes.Call, messageBoxShow);

            myMethodIL.Emit(OpCodes.Pop);
            myMethodIL.Emit(OpCodes.Ret);
            // 方法体结束

            //方法体注入接口SayHello方法
            MethodInfo sayHelloMethod = typeof(IHello).GetMethod("SayHello");
            helloWorldTypeBuilder.DefineMethodOverride(myMethodBuilder, sayHelloMethod);

            //调用
            Type test = helloWorldTypeBuilder.CreateType();//创建动态类
            var instance = Activator.CreateInstance(test);

            ((IHello)instance).SayHello();

            test.GetMethod("SayHello2").Invoke(instance, null);

            
        }
上面的理解了,分析源码就清楚多了。

 

(2)分析源码,了解IInterceptingProxy是如何被实现的:


在E:\Program Files\Microsoft Unity Application Block 2.0\UnitySource\Source\Unity.Interception\Src\Intercept.cs


 public static object NewInstanceWithAdditionalInterfaces(
            Type type,
            ITypeInterceptor interceptor,
            IEnumerable<IInterceptionBehavior> interceptionBehaviors,
            IEnumerable<Type> additionalInterfaces,
            params object[] constructorParameters)
        {
            Guard.ArgumentNotNull(type, "type");
            Guard.ArgumentNotNull(interceptor, "interceptor");
            Guard.ArgumentNotNull(interceptionBehaviors, "interceptionBehaviors");
            Guard.ArgumentNotNull(additionalInterfaces, "additionalInterfaces");

            if (!interceptor.CanIntercept(type))
            {
                throw new ArgumentException(
                    string.Format(
                        CultureInfo.CurrentCulture,
                        Resources.InterceptionNotSupported,
                        type.FullName),
                    "type");
            }

            var behaviors = interceptionBehaviors.ToList();

            if(behaviors.Where(ib => ib == null).Count() > 0)
            {
                throw new ArgumentException(
                    string.Format(CultureInfo.CurrentCulture, Resources.NullBehavior),
                    "interceptionBehaviors");
            }

            Type implementationType = type;

            var activeBehaviors = behaviors.Where(ib => ib.WillExecute);

            Type[] allAdditionalInterfaces = GetAllAdditionalInterfaces(activeBehaviors, additionalInterfaces);

            Type interceptionType = interceptor.CreateProxyType(implementationType, allAdditionalInterfaces);

            var proxy = (IInterceptingProxy)Activator.CreateInstance(interceptionType, constructorParameters);

            foreach (IInterceptionBehavior interceptionBehavior in activeBehaviors)
            {
                proxy.AddInterceptionBehavior(interceptionBehavior);
            }

            return proxy;
        }


CreateProxyType在 E:\Program Files\Microsoft Unity Application Block 2.0\UnitySource\Source\Unity.Interception\Src\Interceptors\TypeInterceptors\VirtualMethodInterception\VirtualMethodInterceptor.cs


 public Type CreateProxyType(Type t, params Type[] additionalInterfaces)
        {
            Guard.ArgumentNotNull(t, "t");
            Guard.ArgumentNotNull(additionalInterfaces, "additionalInterfaces");

            if (!CanIntercept(t))
            {
                throw new InvalidOperationException(
                    string.Format(CultureInfo.CurrentCulture, Resources.InterceptionNotSupported, t.Name));
            }

            Type interceptorType;
            Type typeToDerive = t;
            bool genericType = false;

            if (t.IsGenericType)
            {
                typeToDerive = t.GetGenericTypeDefinition();
                genericType = true;
            }

            GeneratedTypeKey key = new GeneratedTypeKey(typeToDerive, additionalInterfaces);
            lock (derivedClasses)
            {
                if (!derivedClasses.TryGetValue(key, out interceptorType))
                {
                    InterceptingClassGenerator generator =
                        new InterceptingClassGenerator(typeToDerive, additionalInterfaces);
                    interceptorType = generator.GenerateType();
                    derivedClasses[key] = interceptorType;
                }
            }

            if (genericType)
            {
                interceptorType = interceptorType.MakeGenericType(t.GetGenericArguments());
            }

            return interceptorType;
        }


类InterceptingClassGenerator 在 E:\Program Files\Microsoft Unity Application Block 2.0\UnitySource\Source\Unity.Interception\Src\Interceptors\TypeInterceptors\VirtualMethodInterception\InterceptingClassGeneration\InterceptingClassGenerator.cs


构造函数:


public InterceptingClassGenerator(Type typeToIntercept, params Type[] additionalInterfaces)
        {
            this.typeToIntercept = typeToIntercept;
            this.additionalInterfaces = additionalInterfaces;
            CreateTypeBuilder();

        }


CreateTypeBuilder:


private void CreateTypeBuilder()
        {
            TypeAttributes newAttributes = typeToIntercept.Attributes;
            newAttributes = FilterTypeAttributes(newAttributes);

            Type baseClass = GetGenericType(typeToIntercept);

            ModuleBuilder moduleBuilder = GetModuleBuilder();
            typeBuilder = moduleBuilder.DefineType(
                "DynamicModule.ns.Wrapped_" + typeToIntercept.Name + "_" + Guid.NewGuid().ToString("N"),
                newAttributes,
                baseClass);//由此看见继承于typeToIntercept

            DefineGenericArguments(typeBuilder, baseClass);
            // 实现接口靠下面这句
            proxyInterceptionPipelineField = InterceptingProxyImplementor.ImplementIInterceptingProxy(typeBuilder);
        }



ImplementIInterceptingProxy 在 E:\Program Files\Microsoft Unity Application Block 2.0\UnitySource\Source\Unity.Interception\Src\Interceptors\TypeInterceptors\VirtualMethodInterception\InterceptingClassGeneration\InterceptingProxyImplementor.cs


internal static FieldBuilder ImplementIInterceptingProxy(TypeBuilder typeBuilder)
        {
            typeBuilder.AddInterfaceImplementation(typeof(IInterceptingProxy));//声明实现IInterceptingProxy接口
            FieldBuilder proxyInterceptorPipelineField =
                typeBuilder.DefineField(
                    "pipeline",
                    typeof(InterceptionBehaviorPipeline),
                    FieldAttributes.Private | FieldAttributes.InitOnly);
// 方法体注入靠下面这句
            ImplementAddInterceptionBehavior(typeBuilder, proxyInterceptorPipelineField);

            return proxyInterceptorPipelineField;
        }


        private static void ImplementAddInterceptionBehavior(TypeBuilder typeBuilder,  FieldInfo                             proxyInterceptorPipelineField)
        {
            // Declaring method builder
            // Method attributes
            const MethodAttributes methodAttributes = MethodAttributes.Private | MethodAttributes.Virtual
                | MethodAttributes.Final | MethodAttributes.HideBySig
                    | MethodAttributes.NewSlot;

            MethodBuilder methodBuilder =
                typeBuilder.DefineMethod(
                    "Microsoft.Practices.Unity.InterceptionExtension.IInterceptingProxy.AddInterceptionBehavior",
                    methodAttributes);

            // Setting return type
            methodBuilder.SetReturnType(typeof(void));
            // Adding parameters
            methodBuilder.SetParameters(typeof(IInterceptionBehavior));
            // Parameter method
            methodBuilder.DefineParameter(1, ParameterAttributes.None, "interceptor");

            ILGenerator il = methodBuilder.GetILGenerator();
            // Writing body
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldfld, proxyInterceptorPipelineField);
            il.Emit(OpCodes.Ldarg_1);
            il.EmitCall(OpCodes.Callvirt, InterceptionBehaviorPipelineMethods.Add, null);//IInterceptingProxy.AddInterceptionBehavior实际调的是红色
            il.Emit(OpCodes.Ret);
            typeBuilder.DefineMethodOverride(methodBuilder,IInterceptingProxyMethods.AddInterceptionBehavior);//红色的是AddInterceptionBehavior的methodinfo
        }


InterceptionBehaviorPipelineMethods 在 Unity\Unity\Unity.Interception\Src\Interceptors\TypeInterceptors\VirtualMethodInterception\InterceptingClassGeneration\InterceptionBehaviorPipelineMethods.cs


    internal static class InterceptionBehaviorPipelineMethods
    {
        internal static ConstructorInfo Constructor
        {
            get { return StaticReflection.GetConstructorInfo(() => new InterceptionBehaviorPipeline()); }
        }

        internal static MethodInfo Add
        {
            get { return StaticReflection.GetMethodInfo((InterceptionBehaviorPipelinepip) => pip.Add(null)); }
        }

        internal static MethodInfo Invoke
        {
            get { return StaticReflection.GetMethodInfo((InterceptionBehaviorPipeline pip) => pip.Invoke(null, null)); }
        }
    }


InterceptionBehaviorPipeline 在 E:\Program Files\Microsoft Unity Application Block 2.0\UnitySource\Source\Unity.Interception\Src\InterceptionBehaviors\InterceptionBehaviorPipeline.cs


    public class InterceptionBehaviorPipeline
    {
        private readonly List<IInterceptionBehavior> interceptionBehaviors;

        /// <summary>
        /// Creates a new <see cref="HandlerPipeline"/> with an empty pipeline.
        /// </summary>
        public InterceptionBehaviorPipeline()
        {
            interceptionBehaviors = new List<IInterceptionBehavior>();
        }

        /// <summary>
        /// Creates a new <see cref="HandlerPipeline"/> with the given collection
        /// of <see cref="ICallHandler"/>s.
        /// </summary>
        /// <param name="interceptionBehaviors">Collection of interception behaviors to add to the pipeline.</param>
        public InterceptionBehaviorPipeline(IEnumerable<IInterceptionBehavior> interceptionBehaviors)
        {
            Guard.ArgumentNotNull(interceptionBehaviors, "interceptionBehaviors");
            this.interceptionBehaviors = new List<IInterceptionBehavior>(interceptionBehaviors);
        }

        /// <summary>
        /// Get the number of interceptors in this pipeline.
        /// </summary>
        public int Count
        {
            get { return interceptionBehaviors.Count; }
        }

        /// <summary>
        /// Execute the pipeline with the given input.
        /// </summary>
        /// <param name="input">Input to the method call.</param>
        /// <param name="target">The ultimate target of the call.</param>
        /// <returns>Return value from the pipeline.</returns>
        public IMethodReturn Invoke(IMethodInvocation input, InvokeInterceptionBehaviorDelegate target)
        {
            if (interceptionBehaviors.Count == 0)
            {
                return target(input, null);
            }

            int interceptorIndex = 0;

            IMethodReturn result = interceptionBehaviors[0].Invoke(input, delegate
                                      {
                                          ++interceptorIndex;
                                          if (interceptorIndex < interceptionBehaviors.Count)
                                          {
                                              return interceptionBehaviors[interceptorIndex].Invoke;
                                          }
                                          else
                                          {
                                              return target;
                                          }
                                      });
            return result;
        }

        /// <summary>
        /// Adds a <see cref="IInterceptionBehavior"/> to the pipeline.
        /// </summary>
        /// <param name="interceptionBehavior">The interception behavior to add.</param>
        public void Add(IInterceptionBehavior interceptionBehavior)
        {
            Guard.ArgumentNotNull(interceptionBehavior, "interceptionBehavior");
            this.interceptionBehaviors.Add(interceptionBehavior);
        }
    }

到这里,看见NewInstanceWithAdditionalInterfaces方法中:

foreach (IInterceptionBehavior interceptionBehavior in activeBehaviors)
            {
                proxy.AddInterceptionBehavior(interceptionBehavior);
            }

AddInterceptionBehavior实际调用的是InterceptionBehaviorPipeline的Add方法

但是有一个环节:InterceptionBehaviorPipeline在proxy实例中是如何实例化的? 


internal static class InterceptingProxyImplementor
    {
        internal static FieldBuilder ImplementIInterceptingProxy(TypeBuilder typeBuilder)
        {

            typeBuilder.AddInterfaceImplementation(typeof(IInterceptingProxy));

            //定义了这个field,但在哪里newInterceptionBehaviorPipeline()的呢?

            FieldBuilder proxyInterceptorPipelineField =
                typeBuilder.DefineField(
                    "pipeline",
                    typeof(InterceptionBehaviorPipeline),
                    FieldAttributes.Private | FieldAttributes.InitOnly);

            ImplementAddInterceptionBehavior(typeBuilder, proxyInterceptorPipelineField);

            return proxyInterceptorPipelineField;

        }

.......

自己做一个实验:

public class t1
        {
            public string s1;
            public t1()
            {
                s1 = "xxx";
            }
        }

        

        private void button4_Click(object sender, EventArgs e)
        {
            AppDomain domain = AppDomain.CurrentDomain;
            //动态程序集
            AssemblyBuilder assemblyBuilder = domain.DefineDynamicAssembly(new AssemblyName("test"), AssemblyBuilderAccess.Run);
            //动态程序集模块
            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("helloWorldTypeBuilder");
            //运行时创建类
            TypeBuilder helloWorldTypeBuilder = moduleBuilder.DefineType("hello");

            helloWorldTypeBuilder.DefineField(
                    "myt1",
                    typeof(t1),
                    FieldAttributes.Public | FieldAttributes.InitOnly);

            Type testT1 = helloWorldTypeBuilder.CreateType();
            object ins1 = Activator.CreateInstance(testT1);
            string s = ((t1)testT1.GetField("myt1").GetValue(ins1)).s1;// 红色的一定是null,程序会运行时报错
            MessageBox.Show(s);
        }


要在动态类的构造函数中去构造myt1:


 private void button4_Click(object sender, EventArgs e)
        {
            AppDomain domain = AppDomain.CurrentDomain;
            //动态程序集
            AssemblyBuilder assemblyBuilder = domain.DefineDynamicAssembly(new AssemblyName("test"), AssemblyBuilderAccess.Run);
            //动态程序集模块
            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("helloWorldTypeBuilder");
            //运行时创建类
            TypeBuilder helloWorldTypeBuilder = moduleBuilder.DefineType("hello");

            FieldBuilder myt1Field = helloWorldTypeBuilder.DefineField(
                    "myt1",
                    typeof(t1),
                    FieldAttributes.Public | FieldAttributes.InitOnly);

            ConstructorBuilder ctorBuilder = helloWorldTypeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new Type[]{typeof(string)});
            ILGenerator il = ctorBuilder.GetILGenerator();
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Newobj, typeof(t1).GetConstructor(Type.EmptyTypes));
            il.Emit(OpCodes.Stfld, myt1Field);
            il.Emit(OpCodes.Ret);


            Type testT1 = helloWorldTypeBuilder.CreateType();
            object ins1 = Activator.CreateInstance(testT1,new string[]{""});
            string s = ((t1)testT1.GetField("myt1").GetValue(ins1)).s1;
            MessageBox.Show(s);
        }


这样就可以了。

你会在类InterceptingClassGenerator中发现InterceptionBehaviorPipeline的实例化:

private void AddConstructor(ConstructorInfo ctor)
        {
            if (!(ctor.IsPublic || ctor.IsFamily || ctor.IsFamilyOrAssembly)) return;

            MethodAttributes attributes =
                (ctor.Attributes
                & ~MethodAttributes.ReservedMask
                & ~MethodAttributes.MemberAccessMask)
                | MethodAttributes.Public;

            ParameterInfo[] parameters = ctor.GetParameters();

            Type[] paramTypes = parameters.Select(item => item.ParameterType).ToArray();

            ConstructorBuilder ctorBuilder = typeBuilder.DefineConstructor(
                attributes, ctor.CallingConvention, paramTypes);

            for (int i = 0; i < parameters.Length; i++)
            {
                ctorBuilder.DefineParameter(i + 1, parameters[i].Attributes, parameters[i].Name);
            }

            ILGenerator il = ctorBuilder.GetILGenerator();

            // Initialize pipeline field
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Newobj, InterceptionBehaviorPipelineMethods.Constructor);
            il.Emit(OpCodes.Stfld, proxyInterceptionPipelineField);


            // call base class construtor
            il.Emit(OpCodes.Ldarg_0);
            for (int i = 0; i < paramTypes.Length; ++i)
            {
                il.Emit(OpCodes.Ldarg, i + 1);
            }

            il.Emit(OpCodes.Call, ctor);

            il.Emit(OpCodes.Ret);
        }


AddConstructor这个方法是上面标注为蓝色的方法GenerateType中被调用:

public Type GenerateType()
        {
            AddMethods();
            AddProperties();
            AddEvents();

            AddConstructors();//这里面会调用

            int memberCount = 0;
            HashSet<Type> implementedInterfaces = GetImplementedInterfacesSet();
            foreach (var @interface in this.additionalInterfaces)
            {
                memberCount =
                    new InterfaceImplementation(this.typeBuilder, @interface, this.proxyInterceptionPipelineField, true)
                        .Implement(implementedInterfaces, memberCount);
            }

            Type result = typeBuilder.CreateType();
#if DEBUG_SAVE_GENERATED_ASSEMBLY
            assemblyBuilder.Save("Unity_ILEmit_DynamicClasses.dll");
#endif
            return result;
        }

以上把IInterceptingProxy接口的实现说清楚了。接下来要关注第二个问题:

2、下图是如何实现的:

看这

类 InterceptionBehaviorPipeline 的 方法:

public IMethodReturn Invoke(IMethodInvocation input, InvokeInterceptionBehaviorDelegate target)
        {
            if (interceptionBehaviors.Count == 0)
            {
                return target(input, null);
            }

            int interceptorIndex = 0;
//interceptionBehaviors这个数组中正是我们定义的每一个IInterceptionBehavior实例
            IMethodReturn result = interceptionBehaviors[0].Invoke(input, delegate
                                      {
                                          ++interceptorIndex;
                                          if (interceptorIndex < interceptionBehaviors.Count)
                                          {
                                              return interceptionBehaviors[interceptorIndex].Invoke;
                                          }
                                          else
                                          {
                                              return target;
                                          }
                                      });
            return result;
        }

应该是很清楚的体现了上图

InterceptionBehaviorPipeline.Invoke在哪里被调用?

在Unity\Unity\Unity.Interception\Src\Interceptors\TypeInterceptors\VirtualMethodInterception\InterceptingClassGeneration\MethodOverride.cs

的类MethodOverride的方法CreateMethodOverride中可以找到答案:

 private MethodBuilder CreateMethodOverride(MethodBuilder delegateMethod)
        {
            MethodAttributes attrs =
                methodToOverride.Attributes & ~MethodAttributes.NewSlot & ~MethodAttributes.Abstract;

            MethodBuilder methodBuilder = typeBuilder.DefineMethod(methodToOverride.Name, attrs);

            var paramMapper = new MethodOverrideParameterMapper(methodToOverride);
            paramMapper.SetupParameters(methodBuilder);

            methodBuilder.SetReturnType(paramMapper.GetParameterType(methodToOverride.ReturnType));
            methodBuilder.SetParameters(methodParameters.Select(pi => paramMapper.GetParameterType(pi.ParameterType)).ToArray());

            int paramNum = 1;
            foreach (ParameterInfo pi in methodParameters)
            {
                methodBuilder.DefineParameter(paramNum++, pi.Attributes, pi.Name);
            }

            ILGenerator il = methodBuilder.GetILGenerator();

            LocalBuilder methodReturn = il.DeclareLocal(typeof(IMethodReturn));
            LocalBuilder ex = il.DeclareLocal(typeof(Exception));
            LocalBuilder parameterArray = il.DeclareLocal(typeof(object[]));
            LocalBuilder inputs = il.DeclareLocal(typeof(VirtualMethodInvocation));

            // Create instance of VirtualMethodInvocation
            il.Emit(OpCodes.Ldarg_0); // target object

            il.Emit(OpCodes.Ldtoken, methodToOverride);
            if (methodToOverride.DeclaringType.IsGenericType)
            {
                il.Emit(OpCodes.Ldtoken, methodToOverride.DeclaringType);
                il.Emit(OpCodes.Call, MethodBaseMethods.GetMethodForGenericFromHandle);
            }
            else
            {
                il.Emit(OpCodes.Call, MethodBaseMethods.GetMethodFromHandle); // target method
            }

            EmitLoadConstant(il, methodParameters.Length);
            il.Emit(OpCodes.Newarr, typeof(object)); // object[] parameters
            if (methodParameters.Length > 0)
            {
                il.Emit(OpCodes.Stloc, parameterArray);

                for (int i = 0; i < methodParameters.Length; ++i)
                {
                    il.Emit(OpCodes.Ldloc, parameterArray);
                    EmitLoadConstant(il, i);
                    EmitLoadArgument(il, i);
                    if (methodParameters[i].ParameterType.IsValueType || methodParameters[i].ParameterType.IsGenericParameter)
                    {
                        il.Emit(OpCodes.Box, paramMapper.GetParameterType(methodParameters[i].ParameterType));
                    }
                    else if (methodParameters[i].ParameterType.IsByRef)
                    {
                        Type elementType =  paramMapper.GetElementType(methodParameters[i].ParameterType);
                        il.Emit(OpCodes.Ldobj, elementType);
                        if (elementType.IsValueType || elementType.IsGenericParameter)
                        {
                            il.Emit(OpCodes.Box, elementType);
                        }
                    }

                    il.Emit(OpCodes.Stelem_Ref);
                }

                il.Emit(OpCodes.Ldloc, parameterArray);
            }
            il.Emit(OpCodes.Newobj, VirtualMethodInvocationMethods.VirtualMethodInvocation);
            il.Emit(OpCodes.Stloc, inputs);

            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldfld, proxyInterceptionPipelineField);
            il.Emit(OpCodes.Ldloc, inputs);

            // Put delegate reference onto the stack
            il.Emit(OpCodes.Ldarg_0);
            MethodInfo invokeTarget = delegateMethod;

            if(delegateMethod.IsGenericMethod)
            {
                invokeTarget = delegateMethod.MakeGenericMethod(paramMapper.MappedGenericParameters);
            }

            il.Emit(OpCodes.Ldftn, invokeTarget);
            il.Emit(OpCodes.Newobj, InvokeInterceptionBehaviorDelegateMethods.InvokeInterceptionBehaviorDelegate);

            // And call the pipeline
            il.Emit(OpCodes.Call, InterceptionBehaviorPipelineMethods.Invoke);


            il.Emit(OpCodes.Stloc, methodReturn);

            // Was there an exception?
            Label noException = il.DefineLabel();
            il.Emit(OpCodes.Ldloc, methodReturn);
            il.EmitCall(OpCodes.Callvirt, IMethodReturnMethods.GetException, null);
            il.Emit(OpCodes.Stloc, ex);
            il.Emit(OpCodes.Ldloc, ex);
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Ceq);
            il.Emit(OpCodes.Brtrue_S, noException);
            il.Emit(OpCodes.Ldloc, ex);
            il.Emit(OpCodes.Throw);

            il.MarkLabel(noException);

            // handle return value
            if (MethodHasReturnValue)
            {
                il.Emit(OpCodes.Ldloc, methodReturn);
                il.EmitCall(OpCodes.Callvirt, IMethodReturnMethods.GetReturnValue, null);
                if (ReturnType.IsValueType || ReturnType.IsGenericParameter)
                {
                    il.Emit(OpCodes.Unbox_Any, paramMapper.GetParameterType(ReturnType));
                }
                else
                {
                    il.Emit(OpCodes.Castclass, paramMapper.GetParameterType(ReturnType));
                }
            }

            // handle byref parameters
            if (methodParameters.Length > 0)
            {
                int outArgIndex = 0;
                foreach (int parameterIndex in OutputParameterIndices)
                {
                    // Get parameter value (the address) onto the stack)
                    Type elementType = paramMapper.GetElementType(methodParameters[parameterIndex].ParameterType);
                    EmitLoadArgument(il, parameterIndex);

                    // Get result of output parameter out of the results array
                    il.Emit(OpCodes.Ldloc, methodReturn);
                    il.Emit(OpCodes.Callvirt, IMethodReturnMethods.GetOutputs);
                    EmitLoadConstant(il, outArgIndex);
                    il.Emit(OpCodes.Callvirt, IListMethods.GetItem);
                    EmitUnboxOrCast(il, elementType);

                    // And store the results
                    il.Emit(OpCodes.Stobj, elementType);
                    ++outArgIndex;
                }
            }

            il.Emit(OpCodes.Ret);

            return methodBuilder;
        }

我们应该体会到了System.Reflection.Emit是一个奇妙的命名空间。

下一篇:unity 2.0 interception 学习3


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值