Enterprise Library Policy Injection Application Block 之二: PIAB设计和实现原理

前面一篇文章中,我对Enterprise Library中的PIAB Policy Injection Application Block)作了简单的介绍。在这篇文章主要谈谈我个人对PIAB设计和实现原理的一些理解。在介绍过程中,我尽量采用由浅入深出的方式,同时结合例子、Source Code。希望通过本篇文章让大家对PIAB有一个全面、深刻的认识。

一、MBRObjRefRealProxyTransparentProxy

在真正进入PIAB之前,我们现来谈论一些与之相关的、必要的背景知识。MBRObjRefRealProxyTransparentProxy,对于这些名词,我想熟悉或者接触过.NET Remoting的人肯定不会不陌生。由于PIAB的实现机制依赖于Remoting的这种Marshaling,如果对此不了解的读者将对后面的介绍很难理解,所以很有必要先做以下简单的介绍。

我们知道,CLR通过AppDomain实现不同Application之间的隔离,在通常情况下,不同AppDomain不同共享内存。在一个AppDomain中创建的对象不能直接被运行在另一个AppDomain的程序使用。跨AppDomain对象的共享依赖于一个重要的过程:Marshaling。我们有两种不同的Marshaling方式:Marshaling by ValueMarshaling by Reference。前者采用的是Serialization/Deserialization的方式,而后者则是采用传递Reference的方式来实现,其实现原来如下:

Remoting Infrastructure先生成对象的ObjRef InstanceObjRefSystem.Runtime.Remoting.ObjRef)代表远程对象的一个Reference,存储着跨AppDomain远程调用所需的所有的信息,比如URI、类型的层次结构、以及实现的Interface等等。ObjRef是可以序列化的,也就是说它可以按照by Value的方式进行Marshaling。所以可以这么说Marshaling by Reference依赖对对ObjRefMarshaling by Value

ObjRef产地到另一个AppDomain的实现,将根据ObjRef的数据生成两个Proxy对象:RealProxyTransparentProxyRealProxy根据ObjRef创建,通过RealProxy创建TransparentProxy。当进行远程调用的时候,Client直接和TransparentProxy打交道,对TransparentProxy的调用将会ForwardRealProxyRealProxy通过Remoting InfrastructureCommunicateActivation机制将Invocate传递给被激活的Remote Object

MBR通常在一个跨AppDomain的环境下实现远程调用,但是这种机制在用一个AppDomian依然有效,而且可以免去跨AppDomain的性能损失。PIAB就是充分运用了这种在同一个AppDomain下的MBR

二、Method Interception & Custom RealProxy

在第一部分我们知道,PIAB的实现是通过将Policy应用到对应的Method上,在真正执行目标对象具体的方法的之前,PIAB将整个方法的调用拦截,然后逐个调用应在Method上的Policy包含的所有CallHandler(在前一章我们说过Policy = Matching Rule + Call Handler),最后再调用真正目标对象的方法。我们把这种机制成为Method Injection

如何才有实现这样的Method Injection呢?这就要需要使用到我们在上面一节介绍的MBR了。通过上面的介绍,我们知道我们调用一个MBR Object的过程是这样的:Client Code==〉Transparent Proxy==〉Real Proxy==〉Target Object

在上面的Invocate Chain中,由于真正的目标对象的方法在最后一部才被调用,我们完全有可以在中途将调用劫持,使之先调用我们的CallHandler。而这种Inject的突破口在于RealProxy。在FCLFramework Class Library)中RealProxySystem.Runtime.Remoting.Proxies.RealProxy)是个特殊的Abstract Class,你可以继承RealProxy定义你自己的Custom RealProxy,将你需要注入的操作写在Invoke方法中。PIAB采用的就是这样一种解决方案。

我们先不忙介绍PIAB的具体的实现原理,因为相对比较复杂。为了使读者能够更加容易地理解PIAB的实现,我写了一个简单的例子。我们它能够大体体现PIAB的实现机制。这是一个简单的Console Application,我首先定义了一个Custom RealProxy

   1: public class MyRealProxy<T> : RealProxy
   2: {
   3:     private T _target;
   4:     public MyRealProxy(T target)
   5:         : base(typeof(T))
   6:     {
   7:         this._target = target;
   8:     }
   9:  
  10:     public override IMessage Invoke(IMessage msg)
  11:     {
  12:         //Invoke injected pre-operation.
  13:         Console.WriteLine("The injected pre-operation is invoked");
  14:         //Invoke the real target instance.
  15:         IMethodCallMessage callMessage = (IMethodCallMessage)msg;
  16:         object returnValue = callMessage.MethodBase.Invoke(this._target, callMessage.Args);
  17:         //Invoke the injected post-operation.
  18:         Console.WriteLine("The injected post-peration is executed");
  19:         //Return
  20:         return new ReturnMessage(returnValue, new object[0], 0, null, callMessage);
  21:     }
  22: }

 

这是一个GenericRealProxy。在Invoke方法中,两个Console.Write()代表PIAB注入的CallHandler的调用(对于CallHandler的操作可以是在调用Target Object之前调用,也可以在之后调用,我们不妨称这两种类型的操作为Pre-operationPost-operation)。而对Target object的调用实际上是通过Reflection的方式调用的(callMessage.MethodBase.Invoke)。MyRealProxy通过传入Target Instance来创建。

我们在创建一个Factory Class,用于创建TransparentProxy。在PIAB中,这样一个ClassMicrosoft.Practices.EnterpriseLibrary.PolicyInjection.PolicyInjection来充当。

   1: public static class PolicyInjectionFactory
   2: {
   3:     public static T Create<T>()
   4:     {
   5:         T instance = Activator.CreateInstance<T>();
   6:         MyRealProxy<T> realProxy = new MyRealProxy<T>(instance);
   7:         T transparentProxy = (T)realProxy.GetTransparentProxy();
   8:         return transparentProxy;
   9:     }
  10: }

先通过Reflection的方式来创建Target Instance。通过该Instance创建我们在上面定义的Custom RealProxy。最后通过RealProxy返回一个TransparentProxy

有了上面两个Class,我们的编写如下的Code来验证我们自己的Method Injection

   1: public class Foo : MarshalByRefObject
   2: {
   3:     public void DoSomeThing()
   4:     {
   5:         Console.WriteLine("The method of target object is invoked!");
   6:     }
   7: }
   8:  
   9: public class Program
  10: {
  11:     public static void Main()
  12:     {
  13:         Foo foo = PolicyInjectionFactory.Create<Foo>();
  14:         foo.DoSomeThing();
  15:     }
  16: }

我们来看看程序运行后的结果:


可以看到正式我们需要的结果。从这个例子中我们可以看到,我们的
Client code中包含的仅仅是Business Logic相关的code, 而另外一些业务无关的Code则是通过Custom RealProxy的形式注入到Invocation Stack中。这充分体现了Business ConcernCrosscutting Concern的分离。

三、Call Handler Pipeline

我想有了上面的理论和例子作基础,大家对于PIAB真正的实现不难理解了。我们先来介绍一下PI一个重要的概念:CallHandler Pipeline。我们知道Policy被运用Method方面,一个Policy有多个CallHandler。所有一个Method往往关联着一连串的CallHandler。这种现在很常见,就上我们第一部分给出的例子一样,一个简单的ProcessOrder方面需要执行许多额外的业务无关的逻辑:AuthorizationAuditingTransaction EnlistException HandlingLogging

PIAB中,这些基于某个Method的所有CallHandler逐个串联在一起,组成一个CallHandler Pipeline 。具体情况如下图:


我们从
Class Diagram的角度来认识CallHandler Pipeline (在PIAB中通过Microsoft.Practices.EnterpriseLibrary.PolicyInjection.HandlerPipeline来表示)。



   1: public delegate IMethodReturnInvokeHandlerDelegate(IMethodInvocation input, GetNextHandlerDelegate getNext);
   2: public interface IMethodInvocation
   3: {
   4:     IMethodReturnCreateExceptionMethodReturn(Exception ex);
   5:     IMethodReturnCreateMethodReturn(object returnValue, params object[] outputs);
   6:     IParameterCollectionArguments { get; }
   7:     IParameterCollectionInputs { get; }
   8:     IDictionaryInvocationContext { get; }
   9:     MethodBaseMethodBase { get; }
  10:     objectTarget { get; }
  11: }
  12: public delegate InvokeHandlerDelegate GetNextHandlerDelegate();
  13: public interface ICallHandler
  14: {
  15:     IMethodReturnInvoke(IMethodInvocation input, GetNextHandlerDelegate getNext);
  16: }

IMethodInvocation代表对一个方法的调用,它封装了一个Method Invocation的相关信息。比如:Parameter ListInvocation ContextTarget Object. InvokeHandlerDelegate代表的是对CallHandler的调用,由于所有的CallHandler被串成一个CallHandler Pipeline ,在调用了当前CallHandler之后,需要调用Pipeline中后一个CallHandler,对后一个CallHandler调用通过一个DelegateGetNextHandlerDelegate来表示,而该Delegate的返回值是InvokeHandlerDelegate。结合上面的CallHandler Pipeline 的链状结构,对这些应该不难理解。

我们最后来看看HandlerPipeline的定义,它的所有的CallHandler通过一个List来表示。

   1: public class HandlerPipeline
   2: {
   3:     private List<ICallHandler> handlers;
   4:     public HandlerPipeline();
   5:     public HandlerPipeline(IEnumerable<ICallHandler> handlers);
   6:     public IMethodReturnInvoke(IMethodInvocation input, InvokeHandlerDelegate target);
   7:  }

HandlerPipeline通过Invoke开始对其CallHandler PipeLine的调用:

   1: public IMethodReturn Invoke(IMethodInvocation input, InvokeHandlerDelegate target)
   2: {
   3:     if (this.handlers.Count == 0)
   4:     {
   5:         return target(input, null);
   6:     }
   7:     int handlerIndex = 0;
   8:     return this.handlers[0].Invoke(input, delegate {
   9:         handlerIndex++;
  10:         if (handlerIndex < this.handlers.Count)
  11:         {
  12:             ICallHandler local1 = this.handlers[handlerIndex];
  13:             return new InvokeHandlerDelegate(local1.Invoke);
  14:         }
  15:         return target;
  16:     });
  17: }

逻辑并不复杂,按照CallHandler List的先后顺序逐个调用,最后调用Target Object。方法中的第二个参数代表target代表对Target Object的调用。

四、PIAB中的Custom RealProxyInterceptingRealProxy

我们一直再强调,PIAB实际上是通过自定义RealProxy来实现的。而且在第二节我们也实验了这种做法的可行性。我们现在就来看看PIABCustom RealProxyMicrosoft.Practices.EnterpriseLibrary.PolicyInjection.RemotingInterception.InterceptingRealProxy

   1: public class InterceptingRealProxy : RealProxy, IRemotingTypeInfo
   2: {
   3:     private Dictionary<MethodBase, HandlerPipeline> memberHandlers;
   4:     private readonly object target;
   5:     private string typeName;
   6:  
   7:     public InterceptingRealProxy(object target, Type classToProxy, PolicySet policies);
   8:     private void AddHandlersForInterface(Type targetType, Type itf);
   9:     private void AddHandlersForType(Type classToProxy, PolicySet policies);
  10:     public bool CanCastTo(Type fromType, object o);
  11:     public override IMessage Invoke(IMessage msg);
  12:     public object Target { get; }
  13:     public string TypeName { get; set; }
  14: }

上面是它所有的成员定义,其中memberHandlers是一个以MethodBaseKeyDictionary,表示应用在Target Object上面的所有的CallHandler Pipeline。通过这个很容易获得某个具体的方法调用的Pipeline。而target值得是真正的Target Object我们着重来看看Invoke的定义:

   1: public override IMessage Invoke(IMessage msg)
   2: {
   3:     HandlerPipeline pipeline;
   4:     IMethodCallMessage callMessage = (IMethodCallMessage) msg;
   5:     if (this.memberHandlers.ContainsKey(callMessage.MethodBase))
   6:     {
   7:         pipeline = this.memberHandlers[callMessage.MethodBase];
   8:     }
   9:     else
  10:     {
  11:         pipeline = new HandlerPipeline();
  12:     }
  13:     RemotingMethodInvocation invocation = new RemotingMethodInvocation(callMessage, this.target);
  14:     return ((RemotingMethodReturn) pipeline.Invoke(invocation, delegate (IMethodInvocation input, GetNextHandlerDelegate getNext) {
  15:         try
  16:         {
  17:             object returnValue = callMessage.MethodBase.Invoke(this.target, invocation.Arguments);
  18:             return input.CreateMethodReturn(returnValue, invocation.Arguments);
  19:         }
  20:         catch (TargetInvocationException exception)
  21:         {
  22:             return input.CreateExceptionMethodReturn(exception.InnerException);
  23:         }
  24:  
  25:     })).ToMethodReturnMessage();
  26: }

上面的一段代码不长,多看几遍应该不难理解。总的来说上面的Code现根据msg解析出MethodBase,再获取对应的CallHandler Pipeline,最后调用Pipeline

五、Policy Injection Transparent Proxy Factory

介绍到这里,细心的读者可以意识到了,我们实际上还还有两件事情没有解决:CallHandler Pipeline的初始化和Transparent Proxy的创建。这两件事情都由PolicyInject.Create和方法来完成。

需要指出的,应用PIABClass需要具有两个条件中至少一个:

  •  Class继承System.MarshalByRefObject
  • Class实现某个Interface

PolicyInjectiond提供了两种类型的Create方式,一种需要制定Interface,另一种不需要: 

   1: public static TInterface Create<TObject, TInterface>(params object[] args);
   2: public static TObject Create<TObject>(params object[] args);

其实还有两个重载,在这里就不需要多做介绍了。在具体的实现中,最终又是调用一个PolicyInjector对象来实现的。

   1: public static TObject Create<TObject>(params object[] args)
   2: {
   3:     return DefaultPolicyInjector.Create<TObject>(args);
   4: }
   5:  
   6: public static TInterface Create<TObject, TInterface>(params object[] args)
   7: {
   8:  
   9:     returnDefaultPolicyInjector.Create<TObject, TInterface>(args);
  10: }

PolicyInjector是一个Abstract Class。其中Policies属性代表应用在该对象上的所有PolicyPolicy = CallHandler + Matching Rule 

   1: [CustomFactory(typeof(PolicyInjectorCustomFactory))]
   2: public abstract class PolicyInjector
   3: {
   4:     private PolicySetpolicies;
   5:     public PolicyInjector();
   6:     public PolicyInjector(PolicySet policies);
   7:     public TInterface Create<TObject, TInterface>(params object[] args);
   8:     public TObject Create<TObject>(params object[] args);
   9:     public objectCreate(Type typeToCreate, params object[] args);
  10:     public object Create(Type typeToCreate, Type typeToReturn, params object[] args);    
  11:     public PolicySetPolicies { get; set; }
  12:     //Otehrs
  13: }

PolicyInjection Class中定义了一个叫做DefaultPolicyInjector的属性,其定义如下:

   1: private static PolicyInjectorDefaultPolicyInjector
   2: {
   3:     get
   4:     {
   5:         if (defaultPolicyInjector == null)
   6:         {
   7:             lock (singletonLock)
   8:             {
   9:                 if (defaultPolicyInjector == null)
  10:                 {
  11:                     defaultPolicyInjector = GetInjectorFromConfig(ConfigurationSourceFactory.Create());
  12:                 }
  13:             }
  14:         }
  15:         return defaultPolicyInjector;
  16:     }
  17: }

由于上面这个方法具体调用的Stack trace太深了,不可能很详细地指出其具体的实现。简单地说,该属性会返回一个默认的PolicyInjectorRemotingPolicyInjector并对其进行初始化。初始化的内容就包括初始化所有的Policy(这就是我们在本节开始提出的CallHandler Pipeline的初始化)。由于我们可以有两种方式将Policy映射到目标成员:AttributeConfiguration。所有具体的做法是先通过分析Configuration找出所有通过configuration方式添加的Policy,然后通过Reflection找出所有通过使用Attribute方式添加的Policy。所以,如果你通过两种方式将相同的Policy应用到同一个对象上,该对象上将会有两个一样CallHandler,个人觉得这是一个值得商榷的做法,我不太赞成这样的行为。

我们接着看PolicyInjector接着是如何工作的:

   1: public TInterface Create<TObject, TInterface>(params object[] args)
   2: {
   3:     return (TInterface) this.Create(typeof(TObject), typeof(TInterface), args);
   4: }
   5:  
   6: public TObject Create<TObject>(params object[] args)
   7: {
   8:     return (TObject) this.Create(typeof(TObject), typeof(TObject), args);
   9: }

上面连个方法由于调用到同一个Create Overload

   1: publicobjectCreate(Type typeToCreate, Type typeToReturn, params object[] args)
   2: {
   3:     PolicySet policiesFor = this.policies.GetPoliciesFor(typeToCreate);
   4:     this.EnsureTypeIsInterceptable(typeToReturn, policiesFor);
   5:     return this.DoCreate(typeToCreate, typeToReturn, policiesFor, args);
   6:  }

首先找出对应TypePolicy,然后判断该类型是否支持Method InterceptionRemotingPolicyInjector对该方法是这样实现的:要么继承MarshalByRefObjectClass,要么是个Interface。所以我们才有本节开始提出的两个条件。

   1: public override boolTypeSupportsInterception(Type t)
   2: {
   3:     if (!typeof(MarshalByRefObject).IsAssignableFrom(t))
   4:     {
   5:         return t.IsInterface;
   6:     }
   7:     return true;
   8: }

上面连个方法由于调用到同一个Create Overload

   1: public object Create(Type typeToCreate, Type typeToReturn, params object[] args)
   2: {
   3:     PolicySet policiesFor = this.policies.GetPoliciesFor(typeToCreate);
   4:     this.EnsureTypeIsInterceptable(typeToReturn, policiesFor);
   5:     return this.DoCreate(typeToCreate, typeToReturn, policiesFor, args);
   6: }

首先找出对应TypePolicy,然后判断该类型是否支持Method InterceptionRemotingPolicyInjector对该方法是这样实现的:要么继承MarshalByRefObjectClass,要么是个Interface。所以我们才有本节开始提出的两个条件。

   1: protected override object DoWrap(object instance, Type typeToReturn, PolicySet policiesForThisType)
   2: {
   3:     if (PolicyInjector.PolicyRequiresInterception(policiesForThisType))
   4:     {
   5:         InterceptingRealProxy proxy = new InterceptingRealProxy(this.UnwrapTarget(instance), typeToReturn, policiesForThisType);
   6:         return proxy.GetTransparentProxy();
   7:     }
   8:     return instance;
   9: }

和我们给出的例子差不多,创建RealPoxy,根据该RealProxy返回Transparent Proxy

五、Policy Injection Design

最后给出整个PIAB实现的所使用的Class,基本上所有的Class都在上面的内容中介绍过了:


在本系列的第三部分,我将介绍如何创建
Custom Handler,以及如何将他采用不同的方式应用到你的Application中。

EnterLib PIAB系列:

Enterprise Library Policy Injection Application Block 之一: PIAB Overview
Enterprise Library Policy Injection Application Block 之二: PIAB设计和实现原理
Enterprise Library Policy Injection Application Block 之三: PIAB的扩展—创建自定义CallHandler(提供Source Code下载)
Enterprise Library Policy Injection Application Block 之四:如何控制CallHandler的执行顺序

标签: PIAB, AOP, EnterLib
posted @ 2008-01-31 09:45 Artech 阅读(9304) 评论(42) 编辑 收藏

 回复 引用 查看   
#1楼 2008-01-31 09:57 Justin      

刚看到这两个介绍Remoting架构的图,大家随便看看

 回复 引用   
#2楼 2008-01-31 11:26 william.wu[未注册用户]
好文
 回复 引用 查看   
#3楼[楼主] 2008-01-31 12:49 Artech      
@Justin
这张图片对认识Remoting Infrastructure来说,很直观,谢谢提供。

 回复 引用 查看   
#4楼[楼主] 2008-01-31 12:49 Artech      
@william.wu
谢谢关注。

 回复 引用 查看   
#5楼 2008-01-31 15:01 lodestar      
这个应该是代理实现AOP的一种做法,.net下用Attribute好像更普遍。
 回复 引用   
#6楼 2008-01-31 15:51 石桥头[未注册用户]
图文并貌 很好 很强大
 回复 引用 查看   
#7楼 2008-02-01 11:33 暗香浮动      
一直感觉enterprise library 有些无从下手的感觉。
看了这篇文章感觉好像摸到点门路了。
谢谢。

 回复 引用 查看   
#8楼[楼主] 2008-02-01 13:52 Artech      
@lodestar
PIAB采用就是Attribute + Refection 或者Configuration的方式。但是这仅仅是运用Policy的方式,需要采用某种方式实现Invocation Interjection,PIAB采用的是MBR的方式。

 回复 引用 查看   
#9楼[楼主] 2008-02-01 13:52 Artech      
@石桥头
@暗香浮动
3x

 回复 引用 查看   
#10楼 2008-02-03 14:23 Anders06      
底子太薄一时没看明白,下次再看:) 并期待下文

我现在最好奇的是PIAB带给我们的是什么,仅仅是这样的AOP?
因为我觉得自己利用Remoting的机制来实现AOP也没太多的代码和工作量。 而且可以施加更多的控制。

如果你对那一套很熟悉了早就投入了实际的应用(AOP概念的提出应该有很长的历史了吧,而且.NET上的应用也肯定挺多的吧。《.NET本质论》里也早有提及),你还会选择PIAB吗?PIAB给我们带来的仅仅是方便?相比“传统”的哪一套有什么优势呢?

楼主是否能够比较下它们各自的优势呢:)

 回复 引用   
#11楼 2008-02-14 16:10 StrongBird[未注册用户]
@lodestar
Attribute或者Configuration都是Policy的载体,你甚至可以通过Custom的载体来承载Policy(比如数据库,自定义文件等)。而代理拦截是实现PI的具体方式之一,当然也可以有别的方式,只不过PIAB用的是代理拦截的方式。

 回复 引用   
#12楼 2008-02-14 16:11 StrongBird[未注册用户]
这系列文章写得太好了,非常直观易懂,非常感谢博主。
 回复 引用 查看   
#13楼[楼主] 2008-02-19 13:27 Artech      
@Anders06
我觉得PIAB就是通过Remoting的技术实现了Methed Injection,最终实现了AOP。 PIAB可以看成一种解决问题的思路、一种实现的框架。这两种不是相对的,你完全可以采用另一种方式来实现PIAB。
PIAB最大的贡献还是实现了AOP。

 回复 引用 查看   
#14楼[楼主] 2008-02-19 13:27 Artech      
@StrongBird
Thanks!

 回复 引用   
#15楼 2008-03-14 19:19 DDDDDD[未注册用户]
"逻辑并不复杂,按照CallHandler List的先后顺序逐个调用,最后调用Target Object。方法中的第二个参数代表target代表对Target Object的调用。"
代码中我没看到循环或梯归啊,怎么说是“逐个调用”呢,
请LZ指教!


 回复 引用   
#16楼 2008-03-14 19:29 DDDDDD[未注册用户]
也就是说
handlerIndex++;应该被循环或梯归调用,可是物品看不出来,能否指教?

 回复 引用 查看   
#17楼[楼主] 2008-03-17 09:13 Artech      
@DDDDDD
之所以没有使用循环,使因为通过GetNext Delegate进行对下一个Handler的调用。

 回复 引用   
#18楼 2008-03-24 14:44 DDDDDD[未注册用户]
谢谢
 回复 引用   
#19楼 2008-03-24 14:46 DDDDDD[未注册用户]
还有小小的请求,
有空的时候多谢谢文章,在你的文章里确实学到了不少东西!

 回复 引用   
#20楼 2008-03-27 18:12 SandyLee[未注册用户]
讲得这么好,希望博主把EL所有库的原理都讲解一下!
 回复 引用 查看   
#21楼 2008-09-09 10:25 浮云的等待      
謝謝樓主分享,我還是沒有完全看明白,要好好研究一下
 回复 引用 查看   
#22楼[楼主] 2008-09-12 09:20 Artech      
@浮云的等待
可以参考Remoting相关的文档,这样对于PIAB的理解相信会有帮助!

 回复 引用   
#23楼 2008-11-17 14:15 freecloud[未注册用户]
如果不继承MarshalByRefObject,接口怎么实现
 回复 引用 查看   
#24楼[楼主] 2008-11-18 12:06 Artech      
@freecloud
意思是能够被PIAB劫持的对象必须继承自MarshalByRefObject,或者实现一个接口!

 回复 引用 查看   
#25楼 2009-01-07 17:04 Flicker      
使用Remoting的对方法进行拦截,那被调用方法的实例就必须是上下绑定的对象,先不说性能上怎麽样,但是从结构就不合理!
 回复 引用 查看   
#26楼[楼主] 2009-01-09 08:06 Artech      
@Flicker
这是最为常见的一种实现AOP的方式,Remoting的机制只有在跨AppDomain的情况下,才会有明显的性能问题,在这里性能不是问题。

何为“上下绑定的对象”?

 回复 引用 查看   
#27楼 2009-01-13 10:40 Flicker      
不好意思,不是上下绑定的对象,是上下文绑定的对象。
你这样就会要求被劫持的对象在新的context中,这样不会有性能损失吗?
(我不是很了解PIAB,只是对AOP非常感兴趣。)
请教一下:)

 回复 引用 查看   
#28楼 2009-05-31 21:57 父辈的旗帜      
学习学习.

但我不太清楚RealProxy的实现机理是如何的,为什么它可以截获方法的调用啊?IMessage Invoke(IMessage msg)是如何截获到方法的啊?

 回复 引用 查看   
#29楼 2009-07-20 17:26 Ready!      
请教博主:

之前看到过用Remoting实现AOP,定义自己的ContextAttribute(拥有自己的MessageSink),然后使需要被侵入的对象继承自ContextBoundObject就可以了,感觉不很复杂。 看上去底层实现机制似乎跟PIAB是一样的。 请问,这里用PIAB有什么显著的优势吗?期待您的回复,谢谢!

 回复 引用 查看   
#30楼[楼主] 2009-07-20 17:56 Artech      
引用Ready!:
请教博主:

之前看到过用Remoting实现AOP,定义自己的ContextAttribute(拥有自己的MessageSink),然后使需要被侵入的对象继承自ContextBoundObject就可以了,感觉不很复杂。 看上去底层实现机制似乎跟PIAB是一样的。 请问,这里用PIAB有什么显著的优势吗?期待您的回复,谢谢!

实际上AOP本身的实现并不复杂,PIAB的好处就在于提供给你一种可扩展的AOP框架,通过PIAB你可以通过Attribute或者Configuration进行策略的注入,你可以采用PIAB提供的不同的Inteceptor,甚至可以自定义Inteceptor实现你说希望的截获方式。使用PIAB,你还可以同EnterLib的其他ApplicationBlock进行集成(比如Unity)。

 回复 引用 查看   
#31楼 2009-08-17 09:36 stargazer      
请教Artech:
现在在全面拜读您的Enterprise系列。您的精湛的技术让我获益匪浅,以前看微软的Enterprise有些无从下手,现在有了条路子指导,感谢您。另外有个问题想请教您:
public IMethodReturn Invoke(IMethodInvocation input, InvokeHandlerDelegate target)
{
if( handlers.Count == 0 )
{
return target(input, null);
}

int handlerIndex = 0;

IMethodReturn result = handlers[0].Invoke(input, delegate
{
++handlerIndex;
if(handlerIndex < handlers.Count)
{
return handlers[handlerIndex].Invoke;
}
else
{
return target;
}
});
return result;

}
当handlerIndex < this.handlers.Count 时,调用pipeline的callhandler,但是这个方法是从return this.handlers[0].Invoke 第0个开始调用callhandler,在delegate中,如果确保handlerIndex按照顺序增加。这段程序我看不懂,请指教。

 回复 引用 查看   
#32楼[楼主] 2009-08-23 19:59 Artech      
引用stargazer:
请教Artech:
现在在全面拜读您的Enterprise系列。您的精湛的技术让我获益匪浅,以前看微软的Enterprise有些无从下手,现在有了条路子指导,感谢您。另外有个问题想请教您:
public IMethodReturn Invoke(IMethodInvocation input, InvokeHandlerDelegate target)
{
if( handlers.Count == 0 )
{
return target(input, ...

其实像这种代码的逻辑还得自己仔细地分析,呵呵!
handlerIndex 首先设为0,并开始循环,意味着从Handler Pipeline的第一个CallHandler执行。在执行后,handlerIndex加1,开始下一个CallHandler的执行。当handlerIndex等于CallHandler的数量后,调用目标对象!

 回复 引用 查看   
#33楼 2009-08-26 12:28 stargazer      
Tks! Artech
 回复 引用 查看   
#34楼 2009-08-27 09:18 stargazer      
自己基础太差了。所有有些看不明。再次问下
if(handlerIndex < handlers.Count)
{
return handlers[handlerIndex].Invoke;
}
return 返回ICallHandler.Invoke方法调用,是不是还去跑
IMethodReturn result = handlers[0].Invoke(input, delegate
{
++handlerIndex;
if(handlerIndex < handlers.Count)
{
return handlers[handlerIndex].Invoke;
}
else
{
return target;
}
})这个循环。就是自己调用自己。++handlerIndex;最后调用target

 回复 引用 查看   
#35楼 2009-12-25 13:08 Harold Shen      
个人感觉Sping.net的AOP实现比Enterprise Library的好很多。微软不能再闭门造车了。
 回复 引用 查看   
#36楼[楼主] 2009-12-25 17:57 Artech      
引用Harold Shen:个人感觉Sping.net的AOP实现比Enterprise Library的好很多。微软不能再闭门造车了。

我觉得Spring.NET比PIAB要全面得多,并不是一个等级的东西。不过从设计上看,Spring.NET未必就比PIAB好!

 回复 引用 查看   
#37楼 2010-11-18 12:12 xiaosuo      
关注
 回复 引用 查看   
#38楼 2011-07-11 11:02 肖敏      
SSCLI2.0
创建透明代理的关键方法:
// Create a tranparent proxy that behaves as an object of the desired class
CTPMethodTable::CreateTPOfClassForRP(ty, &gc.orRP, &gc.orTP);

发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 1059492 GgjwyHF1u2Q=