源代码分析,对 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);
}
到这里,都明白了。
源代码是个宝库,特别还有对泛型的处理,值得参考。