使用.NET Remoting 技术并采用服务端SingleCall激活方式下如何实现客户端向服务端传递参数

时间:2021-02-08 12:13:40

      .NET Remoting技术是构建企业级分布式应用的很好选择,(个人感觉随.Net Framework 3.0推出的WCF更加强大和易用),我们的项目采用服务端SingleCall方式来激活远程对象,在这种方式下最大的特点是当你new一个对象出来的时候并不会调用相应类型的构造函数,只有当你使用该类型的方法时才会调用构造函数,为换句话说就是SingleCall方式下不保存对象状态,这样做的好处是客户端不会长时间占用服务器资源,但是也就造成不能共享状态。

      最近让我苦恼的一件事是:我想在客户端生成远程对象的时候传一个参数进去,但是服务端激活方式Singleton和SingleCall在生成远程对象时只支持调用无参的默认构造函数,所以在调用带参数的构造函数上我就死了心(不知道各位高手能不能搞定),下面我还原一下我的场景:

      项目采用多层架构,将各个base基类组织起来实现了这个架构,它相当于一个基础框架,以后的应用开发以这个架构为基础,在应用开发时假设框架是稳定的不可变的。

      客户端中生成远程对象的层可以叫做CustomUip,它有个base基类BaseUip,服务端中最接近客户端的层可以叫做ServiceLayer,它也有个base基类BaseService,和一个对外接口IService,客户端通过该接口来获取远程对象,通过ServiceLayer可以使用业务逻辑层ServiceLogic,可以用下面的伪码来说明:

 1、客户端CustomUip

     ///   <summary>
    
///  完成对CustomUip对象的封装
    
///   </summary>
     public   class  CustomUip: BaseUip
    {
        
///   <summary>
        
///  Initializes a new instance of the  <see cref="MascyrLoadUip"/>  class.
        
///   </summary>
        
///   <param name="loadingType"> Type of the loading. </param>
         public  CustomUip()
        {
        }

        
///   <summary>
        
///  Override the function of GetInterface
        
///   </summary>
        
///   <returns> the interface </returns>
         protected   override   object  GetInterface()
        {
            IService interfaceService 
=  (IService )Activator.GetObject( typeof (IService),  base .ServerUrl  +   " ServiceLayer " );

            
return  (IService) interfaceService ;
        }
    }

 

2、 客户端CustomUip的基类BaseUip(位于框架中)

 

     public   class  BaseUip
    {
        
public  BaseUip();

        
// 提供一系列方法
        
// 使用.NET Remoting 技术并采用服务端SingleCall激活方式下如何实现客户端向服务端传递参数使用.NET Remoting 技术并采用服务端SingleCall激活方式下如何实现客户端向服务端传递参数使用.NET Remoting 技术并采用服务端SingleCall激活方式下如何实现客户端向服务端传递参数使用.NET Remoting 技术并采用服务端SingleCall激活方式下如何实现客户端向服务端传递参数..

        
protected   virtual   object  GetInterface()
        {
        }
    }  

 

 3、服务端ServiceLayer

 

     ///   <summary>
    
///  完成对ServiceLayer对象的封装
    
///   </summary>
     public   class  ServiceLayer: ServiceBase, IService
    {
        
///   <summary>
        
///  Initializes a new instance of the  <see cref="MascyrLoadMbr"/>  class.
        
///   </summary>
         public  ServiceLayer()
        {
        }
    }

 

 

4、 服务端ServiceLayer的基类ServiceBase(位于框架中)

 

public   class  ServiceBase
{
    
//  Fields
     private  BaseLogic logic  =   new  BaseLogic( new  DefaultManager());

    
// 一系列其他方法和属性
    
//  Methods
     public  ServiceBase()
    {
        
this .set_Logic( this .logic);
    }    

    
//  Properties
     public  BaseLogic Logic
    {
        
get
        {
            
return   this .logic;
        }
        
set
        {
            
this .logic  =  value;
        }
    }
}

 

5、服务端ServiceLogic     

     ///   <summary>
    
///  完成对ServiceLogic对象的封装
    
///   </summary>
     public   class  ServiceLogic: BaseLogic
    {
        
///   <summary>
        
///  The type of loading data.
        
///   </summary>
         private  LoadingType loadingType  =  LoadingType.NONE;      
        
        
///   <summary>
        
///  Initializes a new instance of the ServiceLogic class. 
        
///   </summary>
         public  ServiceLogic()
        {
           
// 一些初始化操作
        }

        
///   <summary>
        
///  Initializes a new instance of the  <see cref="ServiceLogic"/>  class.
        
///   </summary>
        
///   <param name="loadingType"> Type of the loading. </param>
         public  ServiceLogic(LoadingType loadingType)
            : 
this ()
        {
            
this .loadingType  =  loadingType;
        }

        
// 一系列方法和属性
    }

 

     可以看到在 ServiceLogic 有一个含参构造函数:public ServiceLogic(LoadingType loadingType),这个参数是由客户端传来的控制信息,在代码2中使用Activator.GetObject方法获取对象,当使用该对象方法时只会调用ServiceLayer的无参构造函数,那么ServiceLogic的构造函数无法得到LoadingType参数,所以修改代码如下:

6、在IService接口中增加方法 void Register(LoadingType loadingType);

7、 修改CustomUip

     ///   <summary>
    
///  完成对CustomUip对象的封装
    
///   </summary>
     public   class  CustomUip: BaseUip
    {
        
///   <summary>
        
///  Initializes a new instance of the  <see cref="CustomUip"/>  class.
        
///   </summary>
        
///   <param name="loadingType"> Type of the loading. </param>
         public  CustomUip(LoadingType loadingType)
        {
            
this .loadingType  =  loadingType;
        }

        
///   <summary>
        
///  The loading type.
        
///   </summary>
         private  LoadingType loadingType  =  LoadingType.NONE;

        
///   <summary>
        
///  Override the function of GetInterface
        
///   </summary>
        
///   <returns> the interface </returns>
         protected   override   object  GetInterface()
        {
            IService interfaceService 
=  (IService )Activator.GetObject( typeof (IService ),  base .ServerUrl  +   " ServiceLayer " );            interfaceService .Register( this .loadingType);
            
return  (IService ) interfaceService ;
        }
    }

 

8、修改ServiceLayer    

     ///   <summary>
    
///  完成对ServiceLayer 对象的封装
    
///   </summary>
     public   class  ServiceLayer : ServiceBase,IService
    {
        
///   <summary>
        
///  To store loading type.
        
///   </summary>
         private   static  LoadingType StaticType  =  LoadingType.NONE;

        
///   <summary>
        
///  Initializes a new instance of the  <see cref="MascyrLoadMbr"/>  class.
        
///   </summary>
         public  ServiceLayer ()
        {
            
this .Logic  =   new  ServiceLogic (ServiceLayer.StaticType);
        }

        
///   <summary>
        
///  Registers the specified loading type.
        
///   </summary>
        
///   <param name="loadingType"> Type of the loading. </param>
         public   void  Register(LoadingType loadingType)
        {
            ServiceLayer .StaticType 
=  loadingType;
        }
    }


     通过上述修改可以实现客户端向服务端的参数传递, 在代码8中将LoadingType 声明为Static是因为每当客户端在CustomUip中调用远程对象ServiceLayer的方法时都会初始化 loadingType = LoadingType.NONE;这就导致Register失效,换句话说就是不能保证在new一个对象的同时能执行Register操作,因此声明loadingType 为Static 则能保证只在第一次使用ServiceLayer类型时初始化loadingType 一次,以后不管调用多少次构造函数都不会再去初始化loadingType。

    运行程序后,执行结果完全正确,送了一口气,呵呵。 

    如果还有其它更好的方法希望各位高人指点。