话续前文 : 自己实现简单的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. 微软发布TX(LINQ To Logs And Traces)

    微软开源技术公司于发布了Tx,这是一个Apache 2协议的开源项目,可以使用日志/跟踪文件辅助调试,以及创建实时监控和告警系统. 下面是几个引人关注的功能-- 允许在原始事件源上使用LINQ 允许在 ...

  2. Visual Studio跨平台开发Xamarin

    台湾微软的一系列Visual Studio跨平台开发Xamarin的资料,上面还有视频.具体参看 http://www.microsoft.com/taiwan/newsletter/library/ ...

  3. NodeJS入门(四)—— path对象

    很快Node就会迎来4.0的时代,届时将并入现有的iojs,所以先前写过的iojs入门系列直接更名为NodeJS入门. 本篇开始将逐个介绍Node的各主要模块,依循API文档走一遍,但会给出比API文 ...

  4. ENode框架使用场景简述

    ENode是一个.NET平台下,纯C#开发的,基于DDD,CQRS,ES,EDA,In-Memory架构风格的,可以帮助开发者开发高并发.高吞吐.可伸缩.可扩展的应用程序. 开源项目地址:https: ...

  5. AnguarJS 第一天----Hello World

    AngularJS是什么? AngularJS是目前很火的前端JS框架之一, AngularJS的开发团队将其描述为一种构建动态Web应用的结构化框架.它是完全使用JavaScript编写的客户端技术 ...

  6. 仅此一文让你明白ASP.NET MVC 之View的显示(仅此一文系列二)

    题外话 一周之前写的<仅此一文让你明白ASP.NET MVC原理>受到了广大学习ASP.NET MVC同学的欢迎,于是下定决心准备把它写成一个系列,以满足更多求知若渴的同学们.蒋金楠老师已 ...

  7. linux 使用fdisk分区扩容

    标签:fdisk分区 概述 我们管理的服务器可能会随着业务量的不断增长造成磁盘空间不足的情况,在这个时候我们就需要增加磁盘空间,本章主要介绍如何使用fdisk分区工具创建磁盘分区和挂载分区,介绍两种情 ...

  8. ASP.NET MVC学前篇之请求流程

    ASP.NET MVC学前篇之请求流程 请求流程描述 对于请求的流程,文章的重点是讲HttpApplication和HttpModule之间的关系,以及一个简单的示例实现.(HttpModule又是M ...

  9. php性能优化

    序   很长时间没有写博文了,最近换了工作,长时间加班,根本没有时间做其他事情!今天闲下来了,想一想php性能方面的事情.这也是我2014年的第一篇博文! 推荐阅读:初学者到中级者应该掌握的!   p ...

  10. 【PRINCE2是什么】PRINCE2认证之七大原则

    经过前几讲中关于PRINCE2六大要素,四大步骤及整体思维架构的学习,相信各位看官已经对于PRINCE2有了大概的了解,那我们今天的学习内容会正式进入到七大原则内容的分享. 我们先来回顾一下,PRIN ...