您的位置:首页 > 运维架构

.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?

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;
}
//..........
//............
}
类TransproxyProxy中维护着一个到target类实例的引用(必须是MarshalByRefObject类型的子类),最终的方法调用会通过消息机制到达target实例--语句RemotingServices.ExecuteMessage(this.m_Target,callMsg);,在调用目标对象的目标方法之前会调用InvokeBeforeAttribute,错误时会调用InvokeExceptionAttribute,而完成后调用InvokeAfterAttribute.这里需要注意的是Unity2.0Interception中将要调用的InterceptionBehavior构建成管道模型,编程时会有Scop样的开闭结构,而这里的实现只是顺序的调用,这点需要加以区分。InvokeBeforeAttribute等方法实现如下

viewsourceprint?

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);
}
}
}
2.InterfaceInterceptor代码

viewsourceprint?

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();
}
上面代码通过Emit编程动态构建程序集,程序集中包括一个到目标类的代理类,针对给定接口中的方法签名逐个创建代理方法--语句CreateProxyMethod(info,m_TypeBuilder);
另外可以看到代理类型的程序集只在第一次访问时被创建
--语句
Typetype=builder.GetType("TempAssemblyInjection__Proxy"+interfaceType.Name+targetType.Name);
if(type!=null)
{
returntype;
}

建立的代理类定义类似如下代码:

viewsourceprint?

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>);
}
}
DynamicProxy.InterceptHandler的代码

viewsourceprint?

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);
}
}
原文链接:/article/4891085.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: