unity 2.0 interception 学习1

源代码分析,对 VirtualMethodInterceptor 刨根问底的线索:

目的:类型拦截是如何产生动态实例及这个动态实例如何实现了接口IInterceptingProxy、behavior如何被集成、执行顺序如何被安排、为什么必须是virtual


Intercept 中

NewInstanceWithAdditionalInterfaces(
            Type type,
            ITypeInterceptor interceptor,
            IEnumerable<IInterceptionBehavior> interceptionBehaviors,
            IEnumerable<Type> additionalInterfaces,
            params object[] constructorParameters)

...


Type interceptionType= interceptor.CreateProxyType(implementationType, allAdditionalInterfaces); // 动态类型

            var proxy = (IInterceptingProxy)Activator.CreateInstance(interceptionType, constructorParameters);//interceptionType的动态实例,同时实现了IInterceptingProxy

            foreach (IInterceptionBehavior interceptionBehavior in activeBehaviors)
            {
                proxy.AddInterceptionBehavior(interceptionBehavior);//behavior被集成
            }

            return proxy;


VirtualMethodInterceptor : ITypeInterceptor 中

CreateProxyType:

InterceptingClassGenerator generator=
                        new InterceptingClassGenerator(typeToDerive, additionalInterfaces);//上面的interceptionType动态类型继承于typeToDerive,也就是type
                    interceptorType = generator.GenerateType();


InterceptingClassGenerator 

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);

            DefineGenericArguments(typeBuilder, baseClass);

            proxyInterceptionPipelineField = InterceptingProxyImplementor.ImplementIInterceptingProxy(typeBuilder);//实现IInterceptingProxy
        }


InterceptingProxyImplementor中

internal static FieldBuilder ImplementIInterceptingProxy(TypeBuilder typeBuilder)
        {
            typeBuilder.AddInterfaceImplementation(typeof(IInterceptingProxy));
            FieldBuilder proxyInterceptorPipelineField =
                typeBuilder.DefineField(
                    "pipeline",
                    typeof(InterceptionBehaviorPipeline),
                    FieldAttributes.Private | FieldAttributes.InitOnly);

            ImplementAddInterceptionBehavior(typeBuilder, proxyInterceptorPipelineField);

            return proxyInterceptorPipelineField;
        }


InterceptionBehaviorPipeline

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;
        }

看到这里,下面的图(执行顺序)也就是必然了:

Virtual的问题:

public class test_virtual
        {
            public void m1()
            {
            }

            public virtual void m2()
            {
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
                new AssemblyName("Unity_ILEmit_DynamicClasses"),               
                         AssemblyBuilderAccess.Run
                       
                        );
            ModuleBuilder moduleBuilder = null;
            string moduleName = Guid.NewGuid().ToString("N");
          
            moduleBuilder = assemblyBuilder.DefineDynamicModule(moduleName);
           

            Type baseClass = typeof(test_virtual);

            TypeAttributes attributes = baseClass.Attributes;

            if ((attributes & TypeAttributes.NestedPublic) != 0)
            {
                attributes &= ~TypeAttributes.NestedPublic;
                attributes |= TypeAttributes.Public;
            }

            attributes &= ~TypeAttributes.ReservedMask;
            attributes &= ~TypeAttributes.Abstract;

            TypeBuilder typeBuilder = moduleBuilder.DefineType(
                "DynamicModule.ns.Wrapped_test_virtual_" + Guid.NewGuid().ToString("N"),
                attributes,
                baseClass);

            Type t = typeBuilder.CreateType();

            MethodInfo[] ms = t.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

            string methodStr = "";

            foreach (var method in ms)
            {
                if ((method.IsPublic || method.IsFamily || method.IsFamilyOrAssembly)
                && method.IsVirtual
                && !method.IsFinal
                && method.DeclaringType != typeof(object))
                {
                    methodStr += method.Name + " ";
                }
            }

            MessageBox.Show(methodStr);

        }

这个代码是从unity 源代码中抠出来做实验,确实只有  m2     messagebox出来

代码跟踪是:

InterceptingClassGenerator类  -》 GenerateType方法 -》AddMethods()-》GetMethodsToIntercept():

private IEnumerable<MethodInfo> GetMethodsToIntercept()
        {
            List<MethodInfo> methodsToIntercept = new List<MethodInfo>();
            foreach (MethodInfo method in typeToIntercept.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
            {
                if (!method.IsSpecialName && MethodOverride.MethodCanBeIntercepted(method))
                {
                    methodsToIntercept.Add(method);
                }
            }

            MethodSorter sorter = new MethodSorter(typeToIntercept, methodsToIntercept);
            foreach (MethodInfo method in sorter)
            {
                yield return method;
            }
        }

MethodOverride.MethodCanBeIntercepted方法:

internal static bool MethodCanBeIntercepted(MethodInfo method)
        {
            return method != null &&
                (method.IsPublic || method.IsFamily || method.IsFamilyOrAssembly)
                && method.IsVirtual
                && !method.IsFinal
                && method.DeclaringType != typeof(object);
        }


到这里,都明白了。

源代码是个宝库,特别还有对泛型的处理,值得参考。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值