.Net中的Interception--一个简单的AOP框架学习
2011-03-19 01:15
633 查看
最近翻手头的dll文件时无意中发现了一个Interception实现,这个框架比起目前流行的AOP框架显的比较简漏,但却很好的体现出了.net下AOP是怎么实现的,于是就整理出来。
在.NetUnity2.0中的Interception,按三种方式实现:
1.TransparentProxy/RealProxyInterceptor即Remoting代理机制。
2.InterfaceInterceptor即动态代码(Emit编程)实现
3.VirtualMethodInterceptor也是动态代码实现,Emit编程基本类似于IL编程了。
实例拦截与类型拦截
1.实例拦截
TransparentProxy与InterfaceInterceptor属于实例拦截,所谓实例拦截就是被拦截对象完整而独立的在内参中存在。Client端通过代理类与被拦截对象发生通信(方法调用)。
2.类型拦截
VirtualMethod方式属于类型拦截,内参中不存在被拦截类型的实例,拦截框架通过动态代码生成被拦截类型的子类型程序集,该程序集被加载后对应的子类型被实例化于内存中与Client发生通信
下面针对TransparentProxy/RealProxy与InterfaceInterceptor帖出手头上dll实现的代码
1.TransparentProxy/RealProxy实现
viewsourceprint?
类TransproxyProxy中维护着一个到target类实例的引用(必须是MarshalByRefObject类型的子类),最终的方法调用会通过消息机制到达target实例--语句RemotingServices.ExecuteMessage(this.m_Target,callMsg);,在调用目标对象的目标方法之前会调用InvokeBeforeAttribute,错误时会调用InvokeExceptionAttribute,而完成后调用InvokeAfterAttribute.这里需要注意的是Unity2.0Interception中将要调用的InterceptionBehavior构建成管道模型,编程时会有Scop样的开闭结构,而这里的实现只是顺序的调用,这点需要加以区分。InvokeBeforeAttribute等方法实现如下
viewsourceprint?
2.InterfaceInterceptor代码
viewsourceprint?
上面代码通过Emit编程动态构建程序集,程序集中包括一个到目标类的代理类,针对给定接口中的方法签名逐个创建代理方法--语句CreateProxyMethod(info,m_TypeBuilder);
另外可以看到代理类型的程序集只在第一次访问时被创建
--语句
Typetype=builder.GetType("TempAssemblyInjection__Proxy"+interfaceType.Name+targetType.Name);
if(type!=null)
{
returntype;
}
建立的代理类定义类似如下代码:
viewsourceprint?
DynamicProxy.InterceptHandler的代码
viewsourceprint?
原文链接:/article/4891085.html
在.NetUnity2.0中的Interception,按三种方式实现:
1.TransparentProxy/RealProxyInterceptor即Remoting代理机制。
2.InterfaceInterceptor即动态代码(Emit编程)实现
3.VirtualMethodInterceptor也是动态代码实现,Emit编程基本类似于IL编程了。
实例拦截与类型拦截
1.实例拦截
TransparentProxy与InterfaceInterceptor属于实例拦截,所谓实例拦截就是被拦截对象完整而独立的在内参中存在。Client端通过代理类与被拦截对象发生通信(方法调用)。
2.类型拦截
VirtualMethod方式属于类型拦截,内参中不存在被拦截类型的实例,拦截框架通过动态代码生成被拦截类型的子类型程序集,该程序集被加载后对应的子类型被实例化于内存中与Client发生通信
下面针对TransparentProxy/RealProxy与InterfaceInterceptor帖出手头上dll实现的代码
1.TransparentProxy/RealProxy实现
using System.Reflection; |
using System.Runtime.Remoting.Proxies; |
using System.Runtime.Remoting.Messaging; |
using System.Runtime.Remoting; |
internal class TransparentProxy:RealProxy |
{ |
//Fields |
private readonly MarshalByRefObjectm_Target; |
//Methods |
public TransparentProxy(MarshalByRefObjecttarget) |
: base (target.GetType()) |
{ |
this .m_Target=target; |
} |
public static object GetProxy(MarshalByRefObjecttarget) |
{ |
TransparentProxyproxy= new TransparentProxy(target); |
return proxy.GetTransparentProxy(); |
} |
public override IMessageInvoke(IMessagemsg) |
{ |
IMessagemessage= null ; |
IMethodCallMessagecallMsg=msg as IMethodCallMessage; |
if (callMsg!= null ) |
{ |
object []customAttributes=callMsg.MethodBase.GetCustomAttributes( true ); |
this .InvokeBeforeAttribute(customAttributes,callMsg); |
try |
{ |
message=RemotingServices.ExecuteMessage( this .m_Target,callMsg); |
} |
catch (Exceptionexception) |
{ |
this .InvokeExceptionAttribute(customAttributes,callMsg,exception); |
throw ; |
} |
this .InvokeAfterAttribute(customAttributes,callMsg,((ReturnMessage)message).ReturnValue); |
} |
return message; |
} |
//.......... |
//............ |
} |
private void InvokeAfterAttribute( object []attributes,IMethodCallMessagecallMsg, object result) |
{ |
foreach ( object obj2 in attributes) |
{ |
AfterAttributeattribute=obj2 as AfterAttribute; |
if (attribute!= null ) |
{ |
attribute.Invoke( this .m_Target,callMsg.MethodBase,callMsg.InArgs,result); |
} |
} |
List<IInterception>interceptionList=ProxyBuilder.GetInterceptionList( this .m_Target.GetType().FullName+ "." +callMsg.MethodName,InterceptionType.After); |
if (interceptionList!= null ) |
{ |
foreach (IInterceptioninterception in interceptionList) |
{ |
interception.Invoke( this .m_Target,callMsg.MethodBase,callMsg.InArgs,result); |
} |
} |
} |
public static object GetProxyInstance( object target,TypeinterfaceType) |
{ |
return Activator.CreateInstance(GetProxyType(target.GetType(),interfaceType), new object []{target,interfaceType}); |
} |
private static TypeGetProxyType(TypetargetType,TypeinterfaceType) |
{ |
AppDomaindomain=Thread.GetDomain(); |
AssemblyNamename= new AssemblyName(); |
name.Name= "TempAssemblyInjection" ; |
AssemblyNamename2=name; |
AssemblyBuilderassemblyBuilder=domain.DefineDynamicAssembly(name2,AssemblyBuilderAccess.Run); |
ModuleBuilderbuilder=assemblyBuilder.DefineDynamicModule( "TempClassInjection" ); |
Typetype=builder.GetType( "TempAssemblyInjection__Proxy" +interfaceType.Name+targetType.Name); |
if (type!= null ) |
{ |
return type; |
} |
m_TypeBuilder=builder.DefineType( "TempAssemblyInjection__Proxy" +interfaceType.Name+targetType.Name,TypeAttributes.Public,targetType.BaseType, new Type[]{interfaceType}); |
m_Target=m_TypeBuilder.DefineField( "target" ,interfaceType,FieldAttributes.Private); |
m_Interface=m_TypeBuilder.DefineField( "iface" , typeof (Type),FieldAttributes.Private); |
CreateConstructor(m_TypeBuilder,m_Target,m_Interface); |
foreach (MethodInfoinfo in interfaceType.GetMethods()) |
{ |
CreateProxyMethod(info,m_TypeBuilder); |
} |
return m_TypeBuilder.CreateType(); |
} |
另外可以看到代理类型的程序集只在第一次访问时被创建
--语句
Typetype=builder.GetType("TempAssemblyInjection__Proxy"+interfaceType.Name+targetType.Name);
if(type!=null)
{
returntype;
}
建立的代理类定义类似如下代码:
public class TempAssemblyInjection__ProxyIAnimalDog:IAnimal |
{ |
//Fields |
private Typeiface; |
private IAnimaltarget; |
//Methods |
public TempAssemblyInjection__ProxyIAnimalDog( object obj1,Typetype1) |
{ |
this .target=(IAnimal)obj1; |
this .iface=type1; |
} |
public override int Run( int num1, int num2) |
{ |
object []parameters= new object []{num1,num2}; |
return ( int )DynamicProxy.InterceptHandler( this .target,<BR>Helper.GetMethodFromType( this .target.GetType(),MethodBase.GetCurrentMethod()),<BR>parameters,<BR>Helper.AspectUnion(Helper.GetMethodFromType( this .iface,MethodBase.GetCurrentMethod()).GetCustomAttributes( typeof (AspectAttribute), true ))<BR>); |
} |
} |
public static object InterceptHandlerMethod( object target,MethodBasemethod, object []parameters,AspectAttribute[]attributes) |
{ |
object obj2; |
foreach (AspectAttributeattribute in attributes) |
{ |
if (attribute is BeforeAttribute) |
{ |
attribute.Invoke(target,method,parameters, null ); |
} |
} |
foreach (IInterceptioninterception in ProxyBuilder.GetInterceptionList(target.GetType().FullName+ "." +method.Name,InterceptionType.Before)) |
{ |
interception.Invoke(target,method,parameters, null ); |
} |
try |
{ |
obj2=target.GetType().GetMethod(method.Name).Invoke(target,parameters); |
} |
catch (Exceptionexception) |
{ |
foreach (AspectAttributeattribute2 in attributes) |
{ |
if (attribute2 is ExceptionAttribute) |
{ |
attribute2.Invoke(target,method,parameters,exception); |
} |
} |
foreach (IInterceptioninterception2 in ProxyBuilder.GetInterceptionList(target.GetType().FullName+ "." +method.Name,InterceptionType.Exception)) |
{ |
interception2.Invoke(target,method,parameters,exception); |
} |
throw ; |
} |
foreach (AspectAttributeattribute3 in attributes) |
{ |
if (attribute3 is AfterAttribute) |
{ |
attribute3.Invoke(target,method,parameters,obj2); |
} |
} |
foreach (IInterceptioninterception3 in ProxyBuilder.GetInterceptionList(target.GetType().FullName+ "." +method.Name,InterceptionType.After)) |
{ |
interception3.Invoke(target,method,parameters,obj2); |
} |
return obj2; |
} |
//Properties |
public static CallbackInterceptHandler |
{ |
get |
{ |
return new Callback(DynamicProxy.InterceptHandlerMethod); |
} |
} |
相关文章推荐
- .Net中的Interception--一个简单的AOP框架学习
- [转]AspectF,一个.NET下超简单的轻量级AOP框架
- 一个简单的AOP框架学习
- AspectF,一个.NET下超简单的轻量级AOP框架
- AspectF,一个.NET下超简单的轻量级AOP框架
- Emit学习-实战篇-实现一个简单的AOP框架(一)
- Emit学习-实战篇-实现一个简单的AOP框架(三)
- Emit学习-实战篇-实现一个简单的AOP框架(二)
- 一个简单的AOP框架
- 深入浅出学习Struts1框架(一):一个简单mvc模式代码示例开始
- node学习(4)一个简单的express框架的示例
- Netty学习:搭建一个简单的Netty服务(JAVA NIO 类库的异步通信框架)
- aop框架的一个简单实现
- 为了支持AOP的编程模式,我为.NET Core写了一个轻量级的Interception框架[开源]
- Spring学习(2)一个简单的AOP实例
- Dapper - .Net 环境下一个简单对象映射的框架
- 深入浅出学习Struts1框架(一):一个简单mvc模式代码示例开始
- 三大框架学习:Struts2简单入门(通过一个简单的登陆实例详解)
- VS2010 C++ MFC框架学习笔记1 - 创建一个简单的加法计算器(1)
- Dora.Interception: 一个为.NET Core度身定制的AOP框架