在.Net中实现自己的简易AOP
RealProxy基本代理类
RealProxy类提供代理的基本功能。这个类中有一个GetTransparentProxy方法,此方法返回当前代理实例的透明代理。这是我们AOP实现的主要依赖。
新建一个代理类MyProxy继承RealProxy,IIntercept是我们自己实现的拦截器接口,内部只有一个Do方法
private object _target; //当前代理实例 private List<IIntercept> _intercepts; //拦截器 MyProxy(object target, Type type,params IIntercept[] intercepts) : base(type) { _target = target; _intercepts = intercepts!=null? intercepts.ToList():null; }RealProxy中Invoke方法会执行当前代理实例中方法,所以我们可以重写Invoke来实现AOP
public override IMessage Invoke(IMessage msg) { var ctr = msg as IConstructionCallMessage; if (ctr != null)//执行构造函数 { Console.WriteLine("Construction"); RealProxy _proxy = RemotingServices.GetRealProxy(this._target); _proxy.InitializeServerObject(ctr); MarshalByRefObject tp = (MarshalByRefObject)this.GetTransparentProxy(); return EnterpriseServicesHelper.CreateConstructionReturnMessage(ctr, tp); } //执行当前代理实例方法 if(_intercepts!=null) { foreach (var _intercept in _intercepts) { _intercept.Do(); } } var call = msg as IMethodCallMessage; Console.WriteLine(string.Format("proxy method:{0}", call.MethodName)); var result = call.MethodBase.Invoke(this._target,call.Args); return new ReturnMessage(result,new object[0],0,null,call); }封装代理类的实现,注意:RealProxy构造函数要求目标代理类必须必须从 MarshalByRef类型派生,所以我们需要继承 MarshalByRefObject类或者 ContextBoundObject类
public static class ActivatorContainer { public static T Create<T>(params IIntercept[] intercepts) { //构造函数不会被代理 var result= Activator.CreateInstance(typeof(T)); var myProxy = new MyProxy(result, typeof(T), intercepts); return (T)myProxy.GetTransparentProxy(); } } var log = new LogIntercept(); var time = new TimeIntercept(); var hance = ActivatorContainer.Create<Person>(log,time); hance.Say("hello Proxy");运行结果:
熟悉Castle的动态代理的同学可能会发现,我们自己实现的就像Castle的简易版,基于上面的代码我们也可以实现一个完善的动态代理
ProxyAttribute特性
ProxyAttribute特性标志指示对象类型需要自定义代理。使用特性的相当于代替了上面的ActivatorContainer静态类来自动实现类的代理
[AttributeUsage(AttributeTargets.Class)] public class MyProxyAttribute : ProxyAttribute { private List<Type> _types; //拦截器 //注:特性参数限制于bool, byte, char, double, float, int, long, short, string, System.Type, object, enum。 public MyProxyAttribute(params Type[] types) { _types = types?.ToList(); } public override MarshalByRefObject CreateInstance(Type serverType) { System.Console.WriteLine("Start!"); var target= base.CreateInstance(serverType); List<IIntercept> intercepts = null; if (_types!=null) { intercepts = new List<IIntercept>(); intercepts.AddRange(_types.Select(s => { return (IIntercept)Activator.CreateInstance(s); })); } var myProxy = new MyProxy(target, serverType, intercepts?.ToArray()); return (MarshalByRefObject)myProxy.GetTransparentProxy(); } }此时,我们只要在需要代理的类上加上MyProxyAttribute标志,代理类需要继承 ContextBoundObject类,而不能是 MarshalByRefObject类,然后直接new相关类就行了。此种实现方式构造函数也会被代理,可以通过特性参数注入拦截器类型来实现相关拦截器,相对于直接new拦截器来说更为方便,但不够灵活。但有一个好处就是如果没有继承ContextBoundObject类,目标类不会被代理,也不会不会报错。而上面的实现方式如果没有继承MarshalByRefObject类,运行则会报错。
var hance = new Person(); hance.Say("hello");运行结果:
在.Net中实现自己的简易AOP的更多相关文章
- 在.NET项目中使用PostSharp,实现AOP面向切面编程处理
PostSharp是一种Aspect Oriented Programming 面向切面(或面向方面)的组件框架,适用在.NET开发中,本篇主要介绍Postsharp在.NET开发中的相关知识,以及一 ...
- JavaEE开发之Spring中的依赖注入与AOP
上篇博客我们系统的聊了<JavaEE开发之基于Eclipse的环境搭建以及Maven Web App的创建>,并在之前的博客中我们聊了依赖注入的相关东西,并且使用Objective-C的R ...
- JavaEE开发之Spring中的依赖注入与AOP编程
上篇博客我们系统的聊了<JavaEE开发之基于Eclipse的环境搭建以及Maven Web App的创建>,并在之前的博客中我们聊了依赖注入的相关东西,并且使用Objective-C的R ...
- 利用.NET Core类库System.Reflection.DispatchProxy实现简易Aop
背景 Aop即是面向切面编程,众多Aop框架里Castle是最为人所知的,另外还有死去的Spring.NET,当然,.NET Core社区新秀AspectCore在性能与功能上都非常优秀,已经逐渐被社 ...
- ORACLE PL/SQL 中序列(sequence)的简易使用方法介绍
如果我是C罗 原文 ORACLE PL/SQL 中序列(sequence)的简易使用方法介绍 sequence在ORACLE中应用十分广泛,就是序列号的意思,会自动增加指定变数,如逐次增加1或者2或者 ...
- js中的经典案例--简易万年历
js中的经典案例--简易万年历 html代码 <!DOCTYPE html> <html> <head> <meta charset="utf-8& ...
- [译]如何在ASP.NET Core中实现面向切面编程(AOP)
原文地址:ASPECT ORIENTED PROGRAMMING USING PROXIES IN ASP.NET CORE 原文作者:ZANID HAYTAM 译文地址:如何在ASP.NET Cor ...
- Spring同一个类中的注解方法调用AOP失效问题总结
public interface XxxService { // a -> b void a(); void b(); } @Slf4j public class XxxServiceImpl ...
- C#利用Attribute实现简易AOP介绍
首先看一段简单的代码: public partial class Form1 : Form { public Form1() { InitializeComponent(); } //来自UI层的调用 ...
随机推荐
- 高性能Javascript--脚本的无阻塞加载策略
Javascript在浏览器中的性能,可以说是前端开发者所要面对的最重要的可用性问题. 在Yahoo的Yslow23条规则当中,其中一条是将JS放在底部 .原因是,事实上,大多数浏览器使用单进程处理U ...
- 常见CSS与HTML使用误区
误区一.多div症 <div class="nav"> <ul> <li><a href="/home/"> ...
- Electron使用与学习--(页面间的通信)
目录结构: index.js是主进程js. const electron = require('electron') const app = electron.app const BrowserWin ...
- hash表长度优化证明
hash表冲突的解决方法一般有两个方向: 一个是倾向于空间换时间,使用向量加链表可以最大程度的在节省空间的前提下解决冲突. 另外一个倾向于时间换空间,下面是关于这种思路的一种合适表长度的证明过程: 这 ...
- [C#] 简单的 Helper 封装 -- CookieHelper
using System; using System.Web; namespace ConsoleApplication5 { /// <summary> /// Cookie 助手 // ...
- MySQL 系列(三)你不知道的 视图、触发器、存储过程、函数、事务、索引、语句
第一篇:MySQL 系列(一) 生产标准线上环境安装配置案例及棘手问题解决 第二篇:MySQL 系列(二) 你不知道的数据库操作 第三篇:MySQL 系列(三)你不知道的 视图.触发器.存储过程.函数 ...
- pandas基础-Python3
未完 for examples: example 1: # Code based on Python 3.x # _*_ coding: utf-8 _*_ # __Author: "LEM ...
- CSS中强悍的相对单位之em(em-and-elastic-layouts)学习小记
使用相对单位em注意点 1.浏览器默认字体是16px,即1em = 16px,根元素设置如下 html{ font-size: 100%; /* WinIE text resize correctio ...
- arcgis api for js入门开发系列八聚合效果(含源代码)
上一篇实现了demo的图层控制模块,本篇新增聚合效果,截图如下(源代码见文章底部): 聚合效果实现的思路如下: 1.map.html引用聚合包,项目已经包含进来了的聚合文件夹: <script ...
- 最小生成树(Kruskal算法-边集数组)
以此图为例: package com.datastruct; import java.util.Scanner; public class TestKruskal { private static c ...