颠覆C#王权的“魔比斯环”
四、在MSIL世界建立起强大的AOP帝国
既然能用C#直接写MSIL,那么就可容易编写AOP框架了。虽然这是用C#代码写MSIL,但也要对MSIL有一定的了解,感兴趣的读者可以到微软网站去下载IL Specification。
由于这个AOP框架的代码十分庞大,在这里只给出了一些代码片段。实现AOP框架的核心就是生成动态代理类。因此,使用IL生成代理类的框架是第一步。下面是生成代理类框架的核心代码:
从上面的代码很容易猜到我要生成一个public的sealed类(不可继承)。接下来就是根据父类生成相应的方法(包括普通方法和构造方法),下面是一些代码片段:public TypeBuilder GenerateType() // 返回动态代理类的Type
...{
string className = GetNewClassName();
TypeAttributes typeAttributes = TypeAttributes.Class | TypeAttributes.Public |
TypeAttributes.Sealed;TypeBuilder typeBuilder = m_EmitClassInfo.Module.DefineType(className,
typeAttributes, m_EmitClassInfo.BaseType);
return typeBuilder;
}
private void GenerateMethod() // 生成普通的方法
...{
MethodAttributes methodAttributes = MethodAttributes.Public;
MethodBuilder methodBuilder =
m_TypeBuilder.DefineMethod("__GetMethodInvocation", methodAttributes, typeof(IMethodInvocation),
new Type[] ...{ typeof(ICallable), typeof(MethodInfo) });m_EmitClassInfo.__GetMethodInvocation = methodBuilder;
![]()
ILGenerator ilGenerator = methodBuilder.GetILGenerator();
Label execIfLabel = ilGenerator.DefineLabel();
Label endIfLabel = ilGenerator.DefineLabel();
LocalBuilder methodInvocation = ilGenerator.DeclareLocal(typeof(IMethodInvocation));
ilGenerator.Emit(OpCodes.Ldarg_0);
... ...
}
使用Emit不仅仅可以实现AOP框架,还可以根据用户需要自动生成任何IL代码。这些IL代码不会受到VB.net、C#的限制。因此,用户可以通过Emit来优化生成的中间语言代码,并完成一些C#无法做到的任务。如果读者想了解Emit的详细用法,可以参考MSDN或其他的相关文档。private void GenerateConstructor() // 生成构造方法
...{
try
...{
MethodAttributes methodAttributes = MethodAttributes.Public;
CallingConventions callingConventions = CallingConventions.Standard;
m_BaseConstructorParams = m_EmitClassInfo.ConstructorArgumentsType;
m_ConstructorParams = new Type[m_BaseConstructorParams.Length + 1];
m_BaseConstructorParams.CopyTo(m_ConstructorParams, 0);
m_ConstructorParams[m_BaseConstructorParams.Length] = typeof(IInterceptor);
m_constructorBuilder = m_TypeBuilder.DefineConstructor(methodAttributes, callingConventions,
m_ConstructorParams);m_EmitClassInfo.Constructor = m_constructorBuilder;
m_IlGenerator = m_constructorBuilder.GetILGenerator();
}
catch (Exception e)
...{
throw e;
}
}
0
相关文章
