[Solution] AOP原理解析及Castle、Autofac、Unity框架使用
本节目录:
AOP介绍
面向切面编程(Aspect Oriented Programming,英文缩写为AOP),通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
AOP是OOP的延续,是软件开发中的一个热点.
常用于:
Authentication
Caching
Lazy loading
Transactions
AOP基本原理
普通类
class Person : MarshalByRefObject
{
public string Say()
{
const string str = "Person's say is called";
Console.WriteLine(str);
return str;
}
}
代理类
public class Proxy<T> : RealProxy where T : new()
{
private object _obj;
public Proxy(object obj)
: base(typeof(T))
{
_obj = obj;
}
public override IMessage Invoke(IMessage msg)
{
Console.WriteLine("{0}:Invoke前", DateTime.Now);
var ret = ((IMethodCallMessage)msg).MethodBase.Invoke(_obj, null);
Console.WriteLine("{0}:Invoke后", DateTime.Now);
return new ReturnMessage(ret, null, 0, null, null);
}
}
执行
static void Main(string[] args)
{
var per = new Proxy<Person>(new Person()).GetTransparentProxy() as Person;
if (per != null)
{
var str = per.Say();
Console.WriteLine("返回值:" + str);
}
Console.ReadKey();
}
AOP框架
AOP有动态代理和静态IL织入.
本节主要介绍动态代理方式,静态可参考PostSharp.
Castle Core
原理:本质是创建继承原来类的代理类.重写虚方法实现AOP功能.
只需引用:
Install-Package Castle.Core
(在Castle的2.5以上版本,已经将 Castle.DynamicProxy2.dll 里有内容,集成到 Castle.Core.dll 中。)
Simple Class
public abstract class Person
{
public virtual void SayHello()
{
Console.WriteLine("我是{0}方法", "SayHello");
} public virtual void SayName(string name)
{
Console.WriteLine("我是{0}方法,参数值:{1}", "SayName", name);
} public abstract void AbstactSayOther(); public void SayOther()
{
Console.WriteLine("我是{0}方法", "SayOther");
}
}
interceptor
public class SimpleInterceptor : StandardInterceptor
{
protected override void PreProceed(IInvocation invocation)
{
Console.WriteLine("拦截器调用方法前,方法名是:{0}。", invocation.Method.Name);
} protected override void PerformProceed(IInvocation invocation)
{
Console.WriteLine("拦截器开始调用方法,方法名是:{0}。", invocation.Method.Name);
var attrs = invocation.MethodInvocationTarget.Attributes.HasFlag(MethodAttributes.Abstract);//过滤abstract方法
if (!attrs)
{
base.PerformProceed(invocation);//此处会调用真正的方法 invocation.Proceed();
}
} protected override void PostProceed(IInvocation invocation)
{
Console.WriteLine("拦截器调用方法后,方法名是:{0}。", invocation.Method.Name);
}
}
Main
static void Main(string[] args)
{
var generator = new ProxyGenerator(); //实例化【代理类生成器】
var interceptor = new SimpleInterceptor(); //实例化【拦截器】 //使用【代理类生成器】创建Person对象,而不是使用new关键字来实例化
var person = generator.CreateClassProxy<Person>(interceptor); Console.WriteLine("当前类型:{0},父类型:{1}", person.GetType(), person.GetType().BaseType);
Console.WriteLine(); person.SayHello();//拦截
Console.WriteLine(); person.SayName("Never、C");//拦截
Console.WriteLine(); person.SayOther();//普通方法,无法拦截
person.AbstactSayOther();//抽象方法,可以拦截 Console.ReadLine(); }
Castle Windsor
特性式AOP
public interface IPerson
{
void Say();
} [Interceptor(typeof(LogInterceptor))]
public class Person : IPerson
{
public void Say()
{
Console.WriteLine("Person's Say Method is called!");
}
}
public class LogInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine("{0}:拦截{1}方法{2}前,", DateTime.Now.ToString("O"), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name);
invocation.Proceed();
Console.WriteLine("{0}:拦截{1}方法{2}后,", DateTime.Now.ToString("O"), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name);
}
}
static void Main(string[] args)
{
using (var container = new WindsorContainer())
{
container.Register(Component.For<Person, IPerson>());
container.Register(Component.For<LogInterceptor, IInterceptor>());
var person = container.Resolve<IPerson>();
person.Say();
}
Console.ReadKey();
}
非侵入式AOP
public interface IPerson
{
void Say();
} public class Person : IPerson
{
public void Say()
{
Console.WriteLine("Person's Say Method is called!");
}
}
internal static class LogInterceptorRegistrar
{
public static void Initialize(WindsorContainer container)
{
container.Kernel.ComponentRegistered += Kernel_ComponentRegistered;
} private static void Kernel_ComponentRegistered(string key, IHandler handler)
{
handler.ComponentModel.Interceptors.Add(new InterceptorReference(typeof(LogInterceptor)));
}
}
public class LogInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine("{0}:拦截{1}方法{2}前,", DateTime.Now.ToString("O"), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name);
invocation.Proceed();
Console.WriteLine("{0}:拦截{1}方法{2}后,", DateTime.Now.ToString("O"), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name);
}
}
static void Main(string[] args)
{
using (var container = new WindsorContainer())
{
container.Register(Component.For<IInterceptor, LogInterceptor>());//先注入拦截器
LogInterceptorRegistrar.Initialize(container);
container.Register(Component.For<IPerson, Person>());
var person = container.Resolve<IPerson>();
person.Say();
}
Console.ReadKey();
}
Autofac
Install-Package Autofac.Aop
通过特性标签绑定
class LogInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine("{0}:拦截{1}方法{2}前,", DateTime.Now.ToString("O"), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name);
invocation.Proceed();
Console.WriteLine("{0}:拦截{1}方法{2}后,", DateTime.Now.ToString("O"), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name);
}
} public interface IPerson
{
void Say();
} [Intercept(typeof(LogInterceptor))]
public class Person : IPerson
{
public void Say()
{
Console.WriteLine("Person's Say Method is called!");
}
}
启用拦截器执行
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<Person>().As<IPerson>().EnableInterfaceInterceptors();
builder.RegisterType<LogInterceptor>();
using (var container = builder.Build())
{
container.Resolve<IPerson>().Say();
}
Console.ReadLine();
}
或采用非侵入性方法(去掉class上的特性仍可以)
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<Person>().As<IPerson>().EnableInterfaceInterceptors().InterceptedBy(typeof(LogInterceptor));
builder.RegisterType<LogInterceptor>();
using (var container = builder.Build())
{
container.Resolve<IPerson>().Say();
}
Console.ReadLine();
}
Unity
Unity默认提供了三种拦截器:TransparentProxyInterceptor、InterfaceInterceptor、VirtualMethodInterceptor。
TransparentProxyInterceptor:代理实现基于.NET Remoting技术,它可拦截对象的所有函数。缺点是被拦截类型必须派生于MarshalByRefObject。
InterfaceInterceptor:只能对一个接口做拦截,好处时只要目标类型实现了指定接口就可以拦截。
VirtualMethodInterceptor:对virtual函数进行拦截。缺点是如果被拦截类型没有virtual函数则无法拦截,这个时候如果类型实现了某个特定接口可以改用
Install-Package Unity.Interception
public class MyHandler : ICallHandler
{
public int Order { get; set; }//这是ICallHandler的成员,表示执行顺序
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
Console.WriteLine("方法执行前");
//这之前插入方法执行前的处理
var retvalue = getNext()(input, getNext);//在这里执行方法
//这之后插入方法执行后的处理
Console.WriteLine("方法执行后");
return retvalue;
}
}
public class MyHandlerAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new MyHandler();//返回MyHandler
}
}
public interface IPerson
{
void Say();
} [MyHandler]
public class Person : IPerson
{
public virtual void Say()
{
Console.WriteLine("Person's Say Method is called!");
}
}
static void Main(string[] args)
{
using (var container = new UnityContainer())
{
container.AddNewExtension<Interception>();
//1.TransparentProxyInterceptor
//container.Configure<Interception>().SetInterceptorFor<IPerson>(new TransparentProxyInterceptor()); //2.InterfaceInterceptor (使用1,2,3均可,这种侵入性最小)
container.Configure<Interception>().SetInterceptorFor<IPerson>(new InterfaceInterceptor()); //3.VirtualMethodInterceptor
//container.Configure<Interception>().SetInterceptorFor<Person>(new VirtualMethodInterceptor());
container.RegisterType<IPerson, Person>();
container.Resolve<IPerson>().Say();
}
Console.ReadKey();
}
[Solution] AOP原理解析及Castle、Autofac、Unity框架使用的更多相关文章
- [Solution] DI原理解析及Castle、Unity框架使用
本节目录 DI介绍 DI基本原理 DI框架 Castle Windsor Unity Autofac Spring.Net DI介绍 控制反转(Inversion of Control,英文缩写为Io ...
- AOP原理解析及Castle、Autofac、Unity框架使用
转自:https://www.cnblogs.com/neverc/p/5241466.html AOP介绍 面向切面编程(Aspect Oriented Programming,英文缩写为AOP), ...
- Spring笔记(3) - debug源码AOP原理解析
案例 @EnableAspectJAutoProxy//开启基于注解的aop模式 @Configuration public class AOPConfig { //业务逻辑类加入容器中 @Bean ...
- Spring AOP原理解析
原文链接请参见:http://blog.csdn.net/u010723709/article/details/47839307
- JavaScript 模板引擎实现原理解析
1.入门实例 首先我们来看一个简单模板: <script type="template" id="template"> <h2> < ...
- ABP中动态WebAPI原理解析
ABP中动态WebAPI原理解析 动态WebAPI应该算是ABP中最Magic的功能之一了吧.开发人员无须定义继承自ApiController的类,只须重用Application Service中的类 ...
- SSH深度历险(十) AOP原理及相关概念学习+AspectJ注解方式配置spring AOP
AOP(Aspect Oriented Programming),是面向切面编程的技术.AOP基于IoC基础,是对OOP的有益补充. AOP之所以能得到广泛应用,主要是因为它将应用系统拆分分了2个部分 ...
- Spring IOC设计原理解析:本文乃学习整理参考而来
Spring IOC设计原理解析:本文乃学习整理参考而来 一. 什么是Ioc/DI? 二. Spring IOC体系结构 (1) BeanFactory (2) BeanDefinition 三. I ...
- ulua、tolua原理解析
在聊ulua.tolua之前,我们先来看看Unity热更新相关知识. 什么是热更新 举例来说: 游戏上线后,玩家下载第一个版本(70M左右或者更大),在运营的过程中,如果需要更换UI显示,或者修改游戏 ...
随机推荐
- Spring MVC3返回JSON数据中文乱码问题解决(转)
Spring MVC3返回JSON数据中文乱码问题解决 查了下网上的一些资料,感觉比较复杂,这里,我这几使用两种很简单的办法解决了中文乱码问题. Spring版本:3.2.2.RELEASE Jack ...
- Javascript 固定表格表头
遇到一个简单的需求: 客户有一个表格可能有很多内容,当内容很多的时候,表格就会出现滚动条 客户希望当表格内容很多时,只滚动表格而不滚动浏览器窗口 在网上找到很多相关的插件,要不就是太复杂,要不就是满足 ...
- Splunk - 如何在WebFramework之CORS模式下你的网站和splunk web进行交互
1. 修改配置文件以支持CORS 进入/Applications/Splunk/etc/system/local 修改server.conf 在最后加入如下: [httpServer]crossOri ...
- 用issnode+IIS来托管NodeJs Server
用issnode+IIS来托管NodeJs Server之一:安装篇 用issnode+IIS来托管NodeJs Server之二:移植 用issnode+IIS来托管NodeJs Server之三: ...
- [Scheme]一个Scheme的Metacircular evaluator
这个解释器可以用来跑前面两篇文章的例子,所以一并扔出来,三部曲哈哈. Lisp内置的S-expression相当于解析好的语法树,而借助quasiquote和unquote又很容易进行语法树层面的变换 ...
- WWDC2016-session402-whatsNewInSwift3
Dock 应用的介绍:1.设计到的东西多2.使用 swift 设计3.Dock 的代码量: 200,000行4.更少的重写相同功能的代码 swift.org 官网介绍 Swift Open Sourc ...
- Android获取TextView显示的字符串宽度
工作上有业务需要判断textview是否换行,我的做法是判断textview要显示的字符串的宽度是否超过我设定的宽度,若超过则会执行换行. 项目中的其他地方也有这样的需求,故直接使用了那一块的代码.如 ...
- 【C】——幻方算法
一.幻方按照阶数可分成了三类,即奇数阶幻方.双偶阶幻方.单偶阶幻方. 二.奇数阶幻方(劳伯法) 奇数阶幻方最经典的填法是罗伯法.填写的方法是: 把1(或最小的数)放在第一行正中:按以下规律排列剩下的( ...
- 《objective-c基础教程》学习笔记(十一)—— 类别
在编写面向对象程序的时候,我们经常想为现有的类添加一些新的行为.有些时候,我们可以创建这个类的子类.但是,如果我们用到工具集或者类库的时候,无法处理新建的子类.这时,Objective-C就给我们提供 ...
- js多线程?
http://www.cnblogs.com/o--ok/archive/2012/11/04/JS.html http://blog.csdn.net/nx8823520/article/detai ...