技术开发 频道

颠覆C#王权的“魔比斯环”



    四、在MSIL世界建立起强大的AOP帝国


    既然能用C#直接写MSIL,那么就可容易编写AOP框架了。虽然这是用C#代码写MSIL,但也要对MSIL有一定的了解,感兴趣的读者可以到微软网站去下载IL Specification。

    由于这个AOP框架的代码十分庞大,在这里只给出了一些代码片段。实现AOP框架的核心就是生成动态代理类。因此,使用IL生成代理类的框架是第一步。下面是生成代理类框架的核心代码:

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; }
    从上面的代码很容易猜到我要生成一个public的sealed类(不可继承)。接下来就是根据父类生成相应的方法(包括普通方法和构造方法),下面是一些代码片段:

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); ... ... }
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; } }
    使用Emit不仅仅可以实现AOP框架,还可以根据用户需要自动生成任何IL代码。这些IL代码不会受到VB.net、C#的限制。因此,用户可以通过Emit来优化生成的中间语言代码,并完成一些C#无法做到的任务。如果读者想了解Emit的详细用法,可以参考MSDN或其他的相关文档。
0
相关文章