首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

unity 2.0 interception 学习一

2012-12-17 
unity 2.0 interception 学习1源代码分析,对 VirtualMethodInterceptor 刨根问底的线索:目的:类型拦截是如

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

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

unity 2.0 interception 学习一

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


到这里,都明白了。

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


热点排行