现在的位置: 首页 > 综合 > 正文

.net 真实代理和透明代理的交互

2013年07月17日 ⁄ 综合 ⁄ 共 4472字 ⁄ 字号 评论关闭

1.本地代理调用

using System;
using System.Runtime.Remoting ;
using System.Runtime.Remoting.Services ;
using System.Runtime.Remoting.Activation ;
using System.Runtime.Remoting.Proxies ;
using System.Runtime.Remoting.Messaging ;


/*
  本程序说明了截获是如何进行的,以及真实代理和透明代理之间的关系及交互。
*/

namespace Intercept_example
{
    
class Class1
    
{  
        
private static string[] gg={"sdf""fsddx"};
        [STAThread]
        
static void Main(string[] args)
        
{
            Example exa 
= new Example("sky" ) ;
            exa.say_hello() ;
        }

    }
 
 
    
//定义一个真实代理,用于实现一个特定的预处理和后处理
    public class InterceptProxy :  RealProxy
    
{
        
private readonly MarshalByRefObject target ;
  
        
public InterceptProxy(MarshalByRefObject obj ,Type type) :base(type)
        
{
            
this.target = obj ;
        }


  
        
public override IMessage Invoke(IMessage msg)
        
{
            IMethodCallMessage call 
= (IMethodCallMessage)msg ;
   
            
//如果触发的是构造函数,此时target的构建还未开始
            IConstructionCallMessage ctor = call as IConstructionCallMessage ;
            
if(ctor != null)
            
{
                System.Console.WriteLine(
"转发构造函数调用!") ;

                RealProxy default_proxy 
= RemotingServices.GetRealProxy(this.target) ;
//因为远端对象也是在本地,故也要用透明代理去调用实际操作?

                default_proxy.InitializeServerObject(ctor) ;
                MarshalByRefObject tp 
= (MarshalByRefObject)this.GetTransparentProxy() ;

                
return EnterpriseServicesHelper.CreateConstructionReturnMessage(ctor,tp);
    
            }


            System.Console.WriteLine(
"预处理中......") ;
            System.Threading.Thread.Sleep(
1000) ;
   
            IMethodReturnMessage result_msg 
= RemotingServices.ExecuteMessage(this.target ,call) ;
   
            System.Console.WriteLine(
"后处理中......") ;
            System.Threading.Thread.Sleep(
1000) ;
            System.Console.WriteLine(
"后处理结束!") ;

            
return result_msg ; 

        }

    }

  
 

    
//定义一个特性,该特性可以将上面的真实代理与运用该特性的class联系起来
    [AttributeUsage(AttributeTargets.Class)]
    
public class InterceptProxyAttribute : ProxyAttribute
    
{
        
//得到透明代理
        public override MarshalByRefObject CreateInstance(Type serverType)
        
{
            System.Console.WriteLine(
"创建代理开始!") ;
            
//未初始化的实例
            MarshalByRefObject target =  base.CreateInstance (serverType);

            InterceptProxy rp 
= new InterceptProxy(target ,serverType) ;
MarshalByRefObject obj 
= (MarshalByRefObject)rp.GetTransparentProxy();
            System.Console.WriteLine(
"创建代理结束!") ;
            
return obj ;
        }

    }


    [InterceptProxy]
    
public class Example : ContextBoundObject//放到特定的上下文中,该上下文外部才会得到该对象的透明代理
    {
        
private string name ;
        
public Example(string a)
        
{
            System.Console.WriteLine(
"开始初始化成员!") ;
            
this.name = a ;
        }


        
public void say_hello()
        
{
            Console.WriteLine(
"hello ! " + name ) ;
        }

    }

}

创建代理开始!
                                //返回透明代理给对象
创建代理结束!
                                //对象中的透明代理发起调用
转发构造函数调用!
开始初始化成员!
预处理中......
hello ! sky
后处理中......


CLR里面有这么个透明代理的类(__TransparantProxy);我们既不能让自己的代理类从透明代理类派生以获得这种能力(正如大多数人希望 的那样),也不能通过自定义属性、实现标志性接口等等方法让CLR认为我们的一个类能够透明的“模仿”另一个类。要想在CLR中获取一个透明代理,需要提 供一个真实代理(real   proxy,下简称RP)。    
  一个真实代理是一个从System.Runtime.Remoting.Proxies.RealProxy派生而来的类。这个RealProxy类的首 要功能就是帮我们在运行期动态生成一个可以透明兼容于某一个指定类的透明代理类实例。怎么告诉它我们想要“模仿”的类呢?你需要在从RealProxy类 派生出来的真实代理类的构造器中显式调用该类中的一个protected   RealProxy(Type   classToProxy)构造器,传入我们需要透明代理去模仿的那个类型

2.在远程调用中

在.Net Remoting中,采用了远程代理(Remote Proxy)模式。
采用代理技术,使得对象可以在两个不同的应用程序域(甚至可以是两台不同的机器)之间传递。
代理在.Net中被分为透明代理 (Transparent Proxy)和真实代理(Real Proxy)。
Transparent Proxy的目标是在 CLR 中在 IL 层面最大程度扮演被代理的远端对象,从类型转换到类型获取,从字段访问到方法调用。对 CLR 的使用者来说,Transparent Proxy和被其代理的对象完全没有任何区别,只有通过 RemotingServices.IsTransparentProxy 才能区分两者的区别。
Real Proxy则是提供给 CLR 使用者扩展代理机制的切入点,通过从Real Proxy继承并实现 Invoke 方法,用户自定义代理实现可以自由的处理已经被从栈调用转换为消息调用的目标对象方法调用,如实现缓存、身份验证、安全检测、延迟加载等等。

当客户端发起一个远程调用后,透明代理为该远程调用生成一个 IMessage 对象,并将它传给实际代理。之后,实际代理会查询特定远程对象相关的配置信息,再决定加载哪些消息接收器来处理该远程调用。代理把IMessage对象传给消息接收器来处理该远程调用。

实际代理至少需要加载两个消息接收器。
1. 格式转换接收器(binary和soap),负责将IMessage对象序列化为数据流,最终再由网络传送出去。
2. 传送接收器(http和tcp),负责把数据流输送到目的地或远程服务器。

PS  透明对象和真实对象的关系
Activator.GetObject ()和Activator.CreateInstance()返回给客户一个代理对象。实际上得到两个代理对象,透明代理和真实代理。透明代理像远程对 象,它执行远程对象的所有公共方法,这些方法调用真实对象的Invoke()方法,传送包含方法调用的消息。

消息流动:
-- call-->【透明对象】--IMessage-->【实际代理】--IMessage2-->【消息接收器】(在一个调用中,编码 >>自定义前期操作>>传送到远端 >>收到应答>>自定操作后续操作>>解码)
参与对象:
RealProxy,IMessage,IClientChannelSink
http://blog.csdn.net/anghlq/archive/2006/10/31/1358780.aspx

抱歉!评论已关闭.