.net利用Attribute简单实现AOP
2015-02-07 12:40
477 查看
近日在学AOP,前一篇文章是基于透明代理/真实代理实现的,(前文参考链接:/article/9758640.html),但是每次实现AOP之前需要实例化一个新对象,总感觉不爽.这不.接下来我们使用Attribute来实现AOP.
一、什么是Attribute?
Attribute是一个类,在MSDN文档中对它是这样描述的。Attribute 类将预定义的系统信息或用户定义的自定义信息与目标元素相关联。 目标元素可以是程序集、类、构造函数、委托、枚举、事件、字段、接口、方法、可移植可执行文件模块、参数、属性、返回值、结构或其他特性。所有特性类型都直接或间接地从 Attribute 类派生。 特性可应用于任何目标元素;多个特性可应用于同一目标元素;并且特性可由从目标元素派生的元素继承。 使用 AttributeTargets 类可以指定特性所应用到的目标元素。MSDN原文请参考:https://msdn.microsoft.com/zh-cn/library/system.attribute(v=vs.110).aspx
官方的话还是太官方了,我用通俗一点的话来说就是,用Attribute属性给相应的类或方法贴上标签,在调用的时候,根据标签来判断是否执行一些自定义内容.(如果说的有误,请读者批评指正,先感谢了).
由于对Attribute运用的不多,对它的理解也没有那么透彻,如果读者很想弄清楚,推荐你看看这个,对你理解Attribute应该会有帮助.参考链接:http://www.cnblogs.com/clhed/articles/1324175.html
二、下面我们就用一个.net实例,来看看怎么使用Attribute来实现AOP吧.这个实例实现的计算器简单运算.
先看看整个项目的结构,下图:(后附上源码)1.首先我们打开VS2010,新建一个解决方案,名字随便起,小编命名为:AopAttributePractice.
(在这小编啰嗦一句:给项目起名别太任性,最好能见文知义,最好别用拼音,别告诉我不知道单词怎么写,在线翻译工具那么多,别偷懒啊)
2.为AopAttributePractice解决方案添加一个C#类库,命名为:Calculator.
3.为Calculator类库添加一个Calculator类,类中代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Calculator { public class Calculator { private double _x; private double _y; public Calculator() { } public Calculator(double x, double y) { this._x = x; this._y = y; } public double X { get { return _x; } set { _x = value; } } public double Y { get { return _y; } set { _y = value; } } } }代码浅显易懂,就不解释了.
2.为Calculator类库添加一个类,命名为ICalculator,此类目的是在定义一个接口,类中代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Calculator { public interface ICalculator { double Add(double x, double y); double substract(Calculator calculator); double Mutiply(double x, double y); double Divide(Calculator calculator); } }方法从上到下依次为:加法,减法,乘法,除法。
3.为Calculator类库添加一个实现ICalculator的类,命名为:CalculatorHandler,类中代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Calculator { //业务层的类和方法,让他继承自上下文绑定类的基类 <span style="color:#ff0000;">[MyCalculator]</span> public class CalculatorHandler:ContextBoundObject,ICalculator { //具备标签的方法才能被拦截 [MyCalculatorMethod] public double Add(double x, double y) { Console.WriteLine("{0} + {1} = {2}", x, y, x + y); return x + y; } <span style="color:#ff0000;">[MyCalculatorMethod]</span> public double substract(Calculator calculator) { Console.WriteLine("{0} - {1} = {2}",calculator.X,calculator.Y,calculator.X - calculator.Y); return calculator.X - calculator.Y; } public double Mutiply(double x, double y) { Console.WriteLine("{0} * {1} = {2}", x, y, x * y); return x * y; } public double Divide(Calculator calculator) { Console.WriteLine("{0} / {1} = {2}", calculator.X, calculator.Y, calculator.X / calculator.Y); return calculator.X / calculator.Y; } } }让该类继承ContextBoundObject类和ICalculator类.ICalulator类不做解释,下面对ContextBoundObject类做简单的解释:
ContextBoundObject类:实现被拦截的类,需要从ContextBoundObject类派生,这个类的对象通过Attribute来指定它所在Context,凡是进入该Context的调用都可以被拦截.
代码中红色部分需要基于后面代码的实现才能实现,在这一步,可以先不用理会。
4.准备工作做好了接下来就开始Attribute的实现过程。
新建类MyCalculatorAttribute,类中代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.Remoting.Contexts; namespace Calculator { //贴上类的标签 [AttributeUsage(AttributeTargets.Class,AllowMultiple = false)] //当对一个类应用 sealed 修饰符时,此修饰符会阻止其他类从该类继承 //ContextAttribute:构造器带有一个参数,用来设置ContextAttribute的名称。 public sealed class MyCalculatorAttribute:ContextAttribute, IContributeObjectSink { public MyCalculatorAttribute() : base("MyCalculator") { Console.WriteLine("MyCalculatorAttribute...构造函数"); } //实现IContributeObjectSink接口当中的消息接收器接口 public System.Runtime.Remoting.Messaging.IMessageSink GetObjectSink(MarshalByRefObject obj, System.Runtime.Remoting.Messaging.IMessageSink nextSink) { return new MyAopHandler(nextSink); } } }重要注释都在类中标明,再次不再累述.
5.继续添加新类MyCalculatorMethodAttribute类,类中代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Calculator { //贴上方法标签 [AttributeUsage(AttributeTargets.Method,AllowMultiple = false)] public class MyCalculatorMethodAttribute:Attribute { public MyCalculatorMethodAttribute() { Console.WriteLine("MyCalculatorMethodAttribute...构造函数"); } } }6.下面就开始我们的拦截过程,也就是实现AOP的重要部分.
新建一个MyAopHandler类,类中代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.Remoting.Messaging; namespace Calculator { //AOP方法处理类,实现了IMessageSink接口,以便返回给IContributeObjectSink接口的GetObjectSink方法 public sealed class MyAopHandler:IMessageSink { //下一个接收器 private IMessageSink nextSink; public MyAopHandler(IMessageSink nextSink) { this.nextSink = nextSink; } public IMessageSink NextSink { get { return nextSink; } } //同步处理方法 public IMessage SyncProcessMessage(IMessage msg) { IMessage message = null; //方法调用接口 IMethodCallMessage callMessage = msg as IMethodCallMessage; //如果被调用的方法没打MyCalculatorMethodAttribute标签 if (callMessage == null || (Attribute.GetCustomAttribute(callMessage.MethodBase, typeof(MyCalculatorMethodAttribute))) == null) { message = nextSink.SyncProcessMessage(msg); } else { PreProceed(msg); message = nextSink.SyncProcessMessage(msg); PostProceed(message); } return message; } //异步处理方法 public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink) { Console.WriteLine("异步处理方法..."); return null; } //方法执行前 public void PreProceed(IMessage msg) { IMethodMessage message = (IMethodMessage)msg; Console.WriteLine("New Method Start..."); Console.WriteLine("This Method Is {0}", message.MethodName); Console.WriteLine("This Method A Total of {0} Parameters Including:", message.ArgCount); for (int i = 0; i < message.ArgCount; i++) { Console.WriteLine("Parameter{0}:The Args Is {1}.",i+1,message.Args[i]); } } //方法执行后 public void PostProceed(IMessage msg) { IMethodReturnMessage message = (IMethodReturnMessage)msg; Console.WriteLine("The Return Value Of This Method Is {0}", message.ReturnValue); Console.WriteLine("Method End\n"); } } }图中的方法不需要我们自己逐个写,只需要把鼠标放在继承的类IMessageSink上,右击,就会出现实现接口,点击实现接口即可.下图:
自动生成的异步调用方法,在这里我们没用到,后面处理就会发现,并没有执行这条语句。
7.OK,Calculator类库中的代码就这么多了,别忘了给CalculatorHandler类中方法添加相应的标签.
接下来我们就实现这个AOP拦截过程。
在解决方案里新建一个控制台应用程序(ConsoleApplication).命名为:AopAttributeCalculatorClient,Program类中代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Calculator; using System.Runtime.Remoting.Contexts; namespace AopAttributeCalculatorClient { class Program { static void Main(string[] args) { //实例化Calculator类 Calculator.Calculator calculator = new Calculator.Calculator(); calculator.X = 10; calculator.Y = 20; CalculatorHandler handler = new CalculatorHandler(); //打上标签的方法 handler.Add(calculator.X, calculator.Y); handler.substract(calculator); //没有打标签的方法 handler.Mutiply(30, 40);//自定义传值,跟Calculator类无关 handler.Divide(calculator); } }8.来看看控制台输出情况吧,下图:
添加标签的方法都被遭到了拦截,显然达到了的我们的目的。
9.到此,小编有个疑问,是不是在此基础上,定义类的时候,给类和方法添加标签都能被拦截呢??很明显是肯定可以被拦截的.不信??下面这个例子会让你相信的。
我们在Program类中添加一些代码,Program中整个代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Calculator; using System.Runtime.Remoting.Contexts; namespace AopAttributeCalculatorClient { class Program { static void Main(string[] args) { //实例化Calculator类 Calculator.Calculator calculator = new Calculator.Calculator(); calculator.X = 10; calculator.Y = 20; CalculatorHandler handler = new CalculatorHandler(); //贴上标签的方法 handler.Add(calculator.X, calculator.Y); handler.substract(calculator); //为贴上标签的方法 handler.Mutiply(30, 40); handler.Divide(calculator); //实例化Communition类 Communication com = new Communication(); com.SayBye(); com.SayHello(); } } //贴上类的标签 [MyCalculator] //一定要继承ContextBoundObject类 public class Communication:ContextBoundObject { public Communication() { } //贴上方法标签 [MyCalculatorMethod] public void SayHello() { Console.WriteLine("hello..."); } public void SayBye() { Console.WriteLine("bye!"); } } }10.执行结果如下:
很显然得到了验证.读者可以自行去掉继承的那个类或者去掉标签,再看看效果.
到此,该项目就结束了.如果读者不知道程序怎么调用的?那就自己单步调试吧.更容易帮助你理解.
最后附上源码,源码下载
相关文章推荐
- 利用Attribute实现AOP
- 利用.net提供的类库实现简单的加解密
- AOP学习-基于Emit和Attribute的简单AOP实现
- C#.NET利用ContextBoundObject和Attribute实现AOP技术--AOP事务实现例子
- 基于.net简单实现AOP
- 利用.net(C#)执行sql脚本的简单实现
- C# Attribute 实现简单的 AOP 处理的例子(转)
- C#利用Attribute实现简易AOP介绍
- 一起谈.NET技术,IoC+AOP的简单实现
- .NET平台上超简单实现AOP
- 利用 AOP 实现 .NET 上完整的基于角色的访问控制(RBAC)模型{zhuang}
- 自定义ORM系列(一)利用attribute实现简单的reader=>entity和reader=>List<entity>映射
- 利用 AOP 实现 .NET 上完整的基于角色的访问控制(RBAC)模型
- 利用Attribute实现Aop
- 利用 AOP 实现 .NET 上完整的基于角色的访问控制(RBAC)模型
- 利用Attribute给C#实现AOP?
- .net中利用代理实现AOP
- 学习笔记---元数据、程序集、GAC版本控制、属性(Attribute)、反射(利用.NET编译器实现表达式计算器)
- 自己实现简单的AOP(二)引入Attribute 为方法指定增强对象
- 利用Attribute实现Aop