AOP学习-基于Emit和Attribute的简单AOP实现

关于AOP的介绍,园子里曾经有段时间非常热。

我也看了很多AOP相关的文章,对AOP的概念有一定的了解,觉得园子里的大牛张逸的AOP介绍很不错:AOP技术基础

看了很多AOP的介绍之后,很想自己实现一个简单的AOP来感受一下,但是一直苦于不知道怎么实现。

后来看了园子里的一个介绍Emit的系列(Emit学习系列文章导航),才开始在原作者的基础上实现了简单的AOP框架,仅供学习使用。

1. ThinAOP的介绍

此框架非常简单,只有几个文件。但是就是因为简单,所以可以用来学习AOP的思想。

由于主要部分是有Emit实现的,所以没有Emit基础的话,最好先看一下Emit学习系列文章导航

具体结构如下:

image

2. ThinAOP的介绍-ProxyFactory

之所以先介绍ProxyFactory,是因为ProxyFactory是ThinAOP对外的接口,对于需要使用AOP的类,需要使用ProxyFactory来生成相应的代理类。

ProxyFactory类中只有一个静态方法,就是用来生成动态代理类的。

    public class ProxyFactory
    {
        public static T CreateProxy<T>(Type realProxyType)
        {
            var generator = new DynamicProxyGenerator(realProxyType, typeof(T));
            Type type = generator.GenerateType();

            return (T)Activator.CreateInstance(type);
        }
    }

3. ThinAOP的介绍-Metadata

Metadata中定义了四个类:

  • ExceptionMetadata:用于保存程序中exception的信息
  • MethodMetadata   :用于保存程序中方法的信息(目前只有方法名)
  • ParameterMetadata:用于保存程序中方法的参数信息
  • ResultMetadata:用于保存程序中方法的返回值信息

通过上面定义的四个类,我们可以看出此AOP框架值主要是针对方法这个级别的拦截。即拦截方法在执行前,执行后,异常时的操作。

这四个类非常简单,只是定义了一些属性。

4. ThinAOP的介绍-InvokeContext

保存了必须的上下文信息,也就是上面定义的那些Metadata

5. ThinAOP的介绍-DynamicProxyGenerator

这个类是整个框架的核心,用来生成动态代理,在代理中完成对方法的拦截操作,并在拦截后注入自己的代码。

核心方法是GenerateType,根据现有type生成新的type

        public Type GenerateType()
        {
            // 构造程序集
            BuildAssembly();
            // 构造模块
            BuildModule();
            // 构造类型
            BuildType();
            // 构造字段
            BuildField();
            // 构造函数
            BuildConstructor();
            // 构造方法
            BuildMethods();

            Type type = _typeBuilder.CreateType();
            // 将新建的类型保存在硬盘上(如果每次都动态生成,此步骤可省略)
            _assemblyBuilder.Save(AssemblyFileName);
            return type;
        }

其中的Emit代码,我已经写了相应的C#代码。

Emit代码类似IL,我也是先写C#代码,然后用ILSpy转成IL代码,然后参照IL代码来写的Emit部分代码。

6. ThinAOP的介绍-AspectAttribute

这个类定义了一系列的Attribute,方便于定义拦截操作。

主要定义了3中拦截操作:分别是执行前拦截 ,执行后拦截,异常时拦截

    [AttributeUsage(AttributeTargets.Method)]
    public abstract class PreAspectAttribute : AspectAttribute
    {
    }

    [AttributeUsage(AttributeTargets.Method)]
    public abstract class PostAspectAttribute : AspectAttribute
    {
    }

    [AttributeUsage(AttributeTargets.Method)]
    public abstract class ExceptionAspectAttribute : AspectAttribute
    {
    }

PS.

整个框架的实现参考了博客园里很多文章,这里就不一一列举了。

除了ThinAOP的框架外,我还写了了一个使用这个框架的例子,具体请参见提供的附件:ThinAOP

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
纯手工打造Emit实现AOP private static void OverrideMethods(TypeBuilder tb, MethodInfo method) { if (!method.IsPublic|| !method.IsVirtual || IsObjectMethod(method)) return; Type[] paramTypes = GetParameterTypes(method); MethodAttributes attr = MethodAttributes.Public | MethodAttributes.Family | MethodAttributes.HideBySig | MethodAttributes.Virtual; MethodBuilder mb = tb.DefineMethod(method.Name, attr, method.ReturnType, paramTypes); LocalBuilder result = null; ILGenerator il = mb.GetILGenerator(); bool is_void = method.ReturnType != typeof(void); if (is_void == false) result = il.DeclareLocal(method.ReturnType); object[] attrs = method.GetCustomAttributes(typeof(AspectAttribute), false); if (attrs != null) { //初始化所有当前方法用到的参数object[] CreateLocalParameterArr(il, paramTypes); //初始化AspectContext Type ctxType = typeof(AspectContext); ConstructorInfo info = ctxType.GetConstructor(Type.EmptyTypes); var ctx = il.DeclareLocal(ctxType); il.Emit(OpCodes.Newobj, info); il.Emit(OpCodes.Stloc, ctx); //给AspectContext的参数值属性ParameterArgs赋值 var propMethod = ctxType.GetMethod("set_ParameterArgs"); il.Emit(OpCodes.Ldloc, ctx); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Call, propMethod); int m = attrs.Length; LocalBuilder[] lbs = new LocalBuilder[m]; MethodInfo[] endInvokeMethods = new MethodInfo[m]; //初始化标记的横切对象,并调用横切对象的BeforeInvoke方法 for (int i = 0; i < m; i++) { var tmpType = attrs[i].GetType(); var aspect = il.DeclareLocal(tmpType); ConstructorInfo tmpInfo = tmpType.GetCon

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值