话续前文 : 自己实现简单的AOP(一)简介

在前一篇文章中,对AOP的实现方式做了一个简单介绍。接下来,引入Attribute 为方法指定增强对象,由此实现一个简单的AOP。

注意:指定的是增强对象,“对象”,也就是说Attribute标记,标记的其实是一个对象。由此、使用多态便可轻松实现增强的扩展。

自定义的Attribute

    /// <summary>
/// 为方法标记指定的增强对象
/// <para>指定的增强,可通过代理 DelayProxy 织入</para>
/// </summary>
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
public sealed class AdviceAttribute : Attribute
{
/// <summary>
/// 增强对象
/// </summary>
public AdviceAbstract Advice { get; private set; } /// <summary>
/// 使用指定类型的默认增强对象
/// <para>如果类型为空 则不使用任何增强</para>
/// </summary>
/// <param name="type"></param>
public AdviceAttribute(Type type)
: this(type, string.Empty)
{ } /// <summary>
/// 使用公有静态方法名初始化指定类型的增强对象
/// <para>如果类型为空 则不使用任何增强</para>
/// </summary>
/// <param name="type">类型</param>
/// <param name="methodName">
/// 公有静态方法名
/// <para>如果方法名为空,调用默认构造函数</para>
/// </param>
public AdviceAttribute(Type type, string methodName)
{
// 如果类型为空 则不使用任何增强
if (type == null)
{
this.Advice = null;
return;
} if (string.IsNullOrWhiteSpace(methodName))
{
this.Advice = Activator.CreateInstance(type) as AdviceAbstract;
return;
} this.Advice = type.InvokeMember(
methodName,
System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.Static,
null, null, null) as AdviceAbstract;
} #region 以下两种方式效果不是很好,不推荐使用,故 构造函数私有化 /// <summary>
/// 使用参数列表初始化指定类型的增强对象
/// </summary>
/// <param name="type">类型</param>
/// <param name="objs">参数列表</param>
private AdviceAttribute(Type type, params object[] objs)
{
this.Advice = Activator.CreateInstance(type, objs) as AdviceAbstract;
} /// <summary>
/// 使用命名参数初始化指定类型的增强对象
/// </summary>
/// <param name="namedParameter">
/// 以 冒号 和 分号 分割的形参的命名参数列表
/// <para>支持的数据类型有:string, int, bool 及 可通过静态方法Parse 反序列化的类型</para>
/// </param>
/// <param name="type"></param>
private AdviceAttribute(string namedParameter, Type type)
{
this.Advice = ReflectionUtil.InvokeConstructor(type, namedParameter) as AdviceAbstract;
} #endregion }

Attribute

增强的抽象类 和 自定义的增强

    /// <summary>
/// 抽象的增强类
/// </summary>
public abstract class AdviceAbstract
{
public abstract IMessage Invoke(MarshalByRefObject target, IMethodCallMessage callMessage);
} public class MyAdvice : AdviceAbstract
{
public override IMessage Invoke(MarshalByRefObject target, IMethodCallMessage callMessage)
{
this.BeforeInvoke(target); IMessage message = DelayProxyUtil.InvokeBeProxy(target, callMessage); this.AfterInvoke(target); return message;
} protected virtual void BeforeInvoke(MarshalByRefObject target)
{
Console.WriteLine("Before");
} protected virtual void AfterInvoke(MarshalByRefObject target)
{
Console.WriteLine("After");
} }

Advice

有了如上的两个组件,再借助代理类 DelayProxy<T>,将增强织入,简单的AOP就已经初具原形了。

    /// <summary>
/// 支持泛型、支持延迟初始化的代理类, 可为 MarshalByRefObject 的子类型提供代理
/// <para>在执行代理的过程中,获取 AdviceAttribute 所指定的增强,并织入该增强</para>
/// </summary>
public class DelayProxy<T> : RealProxy where T : MarshalByRefObject
{
private static object objLock = new object(); /// <summary>
/// 被代理的对象
/// </summary>
private T target; /// <summary>
/// 是否延迟初始化
/// <para>True:延迟, False: 不延迟</para>
/// </summary>
private readonly bool delay; public DelayProxy(T target, bool delay)
: base(typeof(T))
{
this.target = target;
this.delay = delay;
} /// <summary>
/// 调用被代理对象
/// <para>支持 out ref 参数</para>
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
public override IMessage Invoke(IMessage msg)
{
if (this.delay && this.target == null)
{
lock (objLock)
{
if (this.delay && this.target == null)
{
T instance = Activator.CreateInstance(typeof(T)) as T; // 自动装配属性
// 为属性对象启用代理,并延迟初始化被代理的对象
// DelayProxyUtil.AutowiredProperties(instance); this.target = instance;
}
}
} IMethodCallMessage callMessage = (IMethodCallMessage)msg; AdviceAttribute attri = ReflectionUtil.GetCustomAttribute<AdviceAttribute>(callMessage.MethodBase); if (attri != null && attri.Advice != null)
{
return attri.Advice.Invoke(this.target, callMessage);
} return DelayProxyUtil.InvokeBeProxy(this.target, callMessage);
} }

DelayProxy

附源码(MVC4的项目 没有packages文件夹):http://files.cnblogs.com/files/08shiyan/AOPDemo.zip

该源码中还实现了被代理对象的延迟初始化。

未完待续...

自己实现简单的AOP(二)引入Attribute 为方法指定增强对象的更多相关文章

  1. 自己实现简单的AOP(一)简介

    AOP 和 OOP,在我看来是两种相辅相成的技术,作为OOP的补充,AOP 有着自己特殊的应用场景. 假设,我们需要在Service层实现以下几项基本功能: /// <para>1.自动管 ...

  2. aop学习总结二------使用cglib动态代理简单实现aop功能

    aop学习总结二------使用cglib动态代理简单实现aop功能 模拟业务需求: 1.拦截所有业务方法 2.判断用户是否有权限,有权限就允许用户执行业务方法,无权限不允许用户执行业务方法 (判断是 ...

  3. 从Unity中的Attribute到AOP(二)

    上一篇文章我们初步了解了一下Attributes的含义,并且使用系统自带的Attributes写了点代码.在进一步解剖我们的代码之前,我觉得有个概念可能需要巩固一下:什么是元数据? 我们知道C#代码会 ...

  4. 动手造轮子:实现一个简单的 AOP 框架

    动手造轮子:实现一个简单的 AOP 框架 Intro 最近实现了一个 AOP 框架 -- FluentAspects,API 基本稳定了,写篇文章分享一下这个 AOP 框架的设计. 整体设计 概览 I ...

  5. 自己实现简单的AOP(三) 实现增强四项基本功能

    前面的两篇随笔,都是只是个铺垫,真正实现增强四项基本功能的重头戏,在本篇随笔中, 本文将通过AOP实现如下的四个基本功能: /// <para>1.自动管理数据库连接[可选]</pa ...

  6. 自己实现简单的AOP(四)自动初始化代理对象

    前面三篇随笔,已经完成了AOP的核心功能,但 代理对象的初始化还是有些麻烦,本文将解决该问题. Demo 片段如下: public class HomeController : Controller ...

  7. spring---aop(9)---Spring AOP中引入增强

    写在前面 Spring将introduction通知看作一种特殊类型的拦截通知.用Spring的行话来讲,对方法的增强叫做Wearing(织入),而对类的增强叫introduction(引入).Int ...

  8. 从头认识Spring-3.1 简单的AOP日志实现-某方法之前的前后记录日志

    这一章节我们引入简单的AOP日志实现. 1.domain 蛋糕类: package com.raylee.my_new_spring.my_new_spring.ch03.topic_1_1; pub ...

  9. 从头认识Spring-3.4 简单的AOP日志实现-扩展添加检查订单功能,以便记录并检測输入的參数

    这一章节我们再上一个章节的基础上加上一个检查订单功能 1.domain 蛋糕类: package com.raylee.my_new_spring.my_new_spring.ch03.topic_1 ...

随机推荐

  1. 神奇的css!竟然可以这样玩转表格

    这是在对一个博客模板进行移动端适配时遇到的一个场景.html结构如下: 要解决的问题是如何在不修改任何html代码的情况下,仅仅通过css实现下面的效果: 1)改变它们的显示顺序,.MainCell显 ...

  2. lua中实现异步资源读写

    同样还是更新方面的需求,当我们检测到版本是新安装的以后,要进行upd目录清除.如果使用os.execute执行 rm -rf ooxx 是非常快的但由于os.execute一旦报错,那整个lua进程就 ...

  3. 优化MySchool数据库设计之【巅峰对决】

    优化MySchool数据库设计 之独孤九剑 船舶停靠在港湾是很安全的,但这不是造船的目的 By:北大青鸟五道口原玉明老师 1.学习方法: 01.找一本好书 初始阶段不适合,可以放到第二个阶段,看到知识 ...

  4. EF6 Power Tools的妙用和问题

    环境:vs2013+EF:6.1.3.0+Power Tools:Beta 4 power tools:是一个反向工程,在已有数据库的情况下,可以利用它生成Code Frist模式的代码. 问题: 它 ...

  5. sublime3 插件

    Sublime Text 3能用支持的插件推荐 从二月份用测试版本build 3012开始用sublime text 3,虽然很多插件在sublime text 3不工作了,因为sublime tex ...

  6. li 前面的缩进怎么去除?

    异常处理汇总-前端系列 http://www.cnblogs.com/dunitian/p/4523015.html 设置margin和padding为0或者为比较小的值就可以了

  7. Nokia 920板砖自救(理论上通用,升级Win10成板砖也可以用这个恢复)

    异常处理汇总 ~ 修正果带着你的Net飞奔吧! http://www.cnblogs.com/dunitian/p/4599258.html 个人博客:http://dnt.dkill.net 下载下 ...

  8. LINQ系列:Linq to Object集合操作符

    集合操作符对元素的集合或序列集合进行操作,并返回一个集合.LINQ共有4种集合查询操作符:Distinct.Union.Intersect和Except. 1. Distinct Distinct操作 ...

  9. 【Win10应用开发】协议-下篇:自定义多个协议

    前面介绍了如何为应用程序自定义协议,于是有朋友会问,我希望为我的应用注册多个协议,不同的协议处理不同的事情,能吗?答案是能的. 方法主要在配置清单文件上,这里我给出一个例子,示例应用将注册两个协议,分 ...

  10. 解密jQuery内核 样式操作

    基础回顾 jQuery里节点样式读取以及设置都是通过.css()这个方法来实现的,本章通一下分解探究下jquery里这部分代码的实现 那么jQuery要处理样式的哪些问题? 先简单回顾下样式操作会遇到 ...