当前位置: 首页 > news >正文

一步一步学Remoting之三:复杂对象

这里说的复杂对象是比较复杂的类的实例,比如说我们在应用中经常使用的DataSet,我们自己的类等,通常我们会给远程的对象传递一些自己的类,或者要求对象返回处理的结果,这个时候通常也就是需要远程对象有状态,上次我们说了几种激活模式提到说只有客户端激活和Singleton是有状态的,而客户端激活和Singleton区别在于Singleton是共享对象的。因此我们可以选择符合自己条件的激活方式:
                        状态      拥有各自实例
Singleton              有            无
SingleCall              无            有
客户端激活              有            有
 
在这里,我们先演示自定义类的传入传出:
先说一个概念:MBV就是按值编码,对象存储在数据流中,用于在网络另外一端创建对象副本。MBR就是按引用编组,在客户机上创建代理,远程对象创建ObjRef实例,实例被串行化传递。

我们先来修改一下远程对象:
using  System; 

namespace  RemoteObject 

    
public   class  MyObject:MarshalByRefObject 
    { 
        
private  MBV _mbv;
        
private  MBR _mbr;
        
public   int  Add( int  a, int  b) 
        { 
            
return  a + b; 
        } 

        
public  MBV GetMBV()
        {
            
return   new  MBV( 100 );
        }

        
public  MBR GetMBR()
        {
            
return   new  MBR( 200 );
        }

        
public   void  SetMBV(MBV mbv)
        {
            
this ._mbv = mbv;
        }

        
public   int  UseMBV()
        {
            
return   this ._mbv.Data;
        }

        
public   void  SetMBR(MBR mbr)
        {
            
this ._mbr = mbr;
        }

        
public   int  UseMBR()
        {
            
return   this ._mbr.Data;
        }
    } 

    [Serializable]
    
public   class  MBV
    {
        
private   int  _data;
        
public  MBV( int  data)
        {
            
this ._data = data;
        }
        
public   int  Data
        {
            
get
            {
                
return   this ._data;
            }
            
set
            {
                
this ._data = value;
            }
        }
    }

    
public   class  MBR:MarshalByRefObject
    {
        
private   int  _data;
        
public  MBR( int  data)
        {
            
this ._data = data;
        }
        
public   int  Data
        {
            
get
            {
                
return   this ._data;
            }
            
set
            {
                
this ._data = value;
            }
        }
    }

Get方法用来从服务器返回对象,Set方法用于传递对象到服务器,Use方法用来测试远程对象的状态是否得到了保存。

我们先来测试一下客户端激活模式:(服务器端的设置就不说了)
    RemoteObject.MyObject app = (RemoteObject.MyObject)Activator.CreateInstance( typeof (RemoteObject.MyObject), null , new   object []{ new  System.Runtime.Remoting.Activation.UrlAttribute(System.Configuration.ConfigurationSettings.AppSettings[ " ServiceURL " ])});
            RemoteObject.MBV mbv
= app.GetMBV();
            Console.WriteLine(mbv.Data);
            RemoteObject.MBR mbr
= app.GetMBR();
            Console.WriteLine(mbr.Data);
            mbv
= new  RemoteObject.MBV( 100 );
            app.SetMBV(mbv);
            Console.WriteLine(app.UseMBV());
            
// mbr=new RemoteObject.MBR(200);
            
// app.SetMBR(mbr);
            
// Console.WriteLine(app.UseMBR());
            Console.ReadLine();

依次显示:100,200,100
前面2个100,200说明我们得到了服务器端返回的对象(分别是MBV和MBR方式的),后面一个100说明我们客户端建立了一个MBV的对象传递给了服务器,因为客户端激活模式是有状态的所以我们能使用这个对象从而输出100,最后我们注释了几行,当打开注释运行后出现异常“由于安全限制,无法访问类型 System.Runtime.Remoting.ObjRef。”这个在【通道】一节中会讲到原因。

好了,我们再来测试一下Singleton(别忘记修改客户端配置文件中的URI哦)
RemoteObject.MyObject app = (RemoteObject.MyObject)Activator.GetObject( typeof (RemoteObject.MyObject),System.Configuration.ConfigurationSettings.AppSettings[ " ServiceURL " ]);
            
// RemoteObject.MyObject app=(RemoteObject.MyObject)Activator.CreateInstance(typeof(RemoteObject.MyObject),null,new object[]{new System.Runtime.Remoting.Activation.UrlAttribute(System.Configuration.ConfigurationSettings.AppSettings["ServiceURL"])});

后面的语句省略,运行后同样出现100,200,100-》Singleton也是能保存状态的。
SingleCall呢?修改一下服务端的Config再来一次,在“Console.WriteLine(app.UseMBV());”出现了“未将对象引用设置到对象的实例。”因为服务端没有能够保存远程对象的状态,当然出错。

再看一下.net内置的一些复杂对象,比如DataSet,可能传入传出DataSet和DataTable在应用中比较普遍,一些不可序列话的类我们不能直接传递,比如DataRow等,要传递的时候可以考虑放入DataTable容器中。

远程对象修改如下:
using  System; 
using  System.Data;

namespace  RemoteObject 

    
public   class  MyObject:MarshalByRefObject 
    { 
        
public  DataSet Method(DataSet ds)
        {
            DataTable dt
= ds.Tables[ 0 ];
            
foreach (DataRow dr  in  dt.Rows)
            {
                dr[
" test " ] = dr[ " test " ] + " _ok " ;
            }
            
return  ds;
        }
    }

客户端修改如下:
    RemoteObject.MyObject app  =  (RemoteObject.MyObject)Activator.GetObject( typeof (RemoteObject.MyObject),System.Configuration.ConfigurationSettings.AppSettings[ " ServiceURL " ]);
            DataSet ds
= new  DataSet();
            DataTable dt
= new  DataTable();
            dt.Columns.Add(
new  DataColumn( " test " , typeof (System.String)));
            DataRow dr
= dt.NewRow();
            dr[
" test " ] = " data " ;
            dt.Rows.Add(dr);
            ds.Tables.Add(dt);
            ds
= app.Method(ds);
            Console.WriteLine(ds.Tables[
0 ].Rows[ 0 ][ " test " ].ToString());
            Console.ReadLine();


运行后发现输出data_ok了。在这里不管用哪种模式来激活都会得到data_ok,因为我们并没有要求远程对象来保存状态。

总结:

所有必须跨越应用程序域的本地对象都必须按数值来传递,并且应该用 [serializable] 自定义属性作标记,否则它们必须实现 ISerializable 接口。对象作为参数传递时,框架将该对象序列化并传输到目标应用程序域,对象将在该目标应用程序域中被重新构造。无法序列化的本地对象将不能传递到其他应用程序域中,因而也不能远程处理。通过从 MarshalByRefObject 导出对象,可以使任一对象变为远程对象。当某个客户端激活一个远程对象时,它将接收到该远程对象的代理。对该代理的所有操作都被适当地重新定向,使远程处理基础结构能够正确截取和转发调用。尽管这种重新定向对性能有一些影响,但 JIT 编译器和执行引擎 (EE) 已经优化,可以在代理和远程对象驻留在同一个应用程序域中时,防止不必要的性能损失。如果代理和远程对象不在同一个应用程序域中,则堆栈中的所有方法调用参数会被转换为消息并被传输到远程应用程序域,这些消息将在该远程应用程序域中被转换为原来的堆栈帧,同时该方法调用也会被调用。从方法调用中返回结果时也使用同一过程。

附msdn有关章节:
http://msdn.microsoft.com/library/CHS/cpguide/html/cpconRemotableNon-RemotableObjects.asp

 

 

TrackBack:http://www.cnblogs.com/lovecherry/archive/2005/05/20/159335.html

转载于:https://www.cnblogs.com/hdjjun/archive/2008/06/17/1223935.html

相关文章:

  • linux下查看磁盘空间
  • Greenplum table 之 appendonly的列存储表
  • 云计算实验(二)Hadoop 练习
  • 云计算实验(三)CloudSim练习
  • 信息安全实验一:DES分组密码算法 2019.03.21
  • 信息安全实验二:分组密码工作模式 2019.04.15
  • 信息安全实验三:求模逆算法 2019.04.18
  • 信息安全实验四:RSA公钥加密算法 2019.04.28
  • 信息安全实验五:散列算法 2019.05.18
  • 信息安全实验六:RSA数字签名算法 2019.06.01
  • 基于寒武纪平台的边缘智能实践课程-实验报告 2019.7.5
  • 基于深度学习的实时人脸识别 2019.3.6
  • YOLO论文阅读 ⽬标检测: You Only Look Once: Unified, Real-Time Object Detection 2018.12.20
  • TensorFlow与Flask结合打造手写体数字识别 https://www.imooc.com/learn/994
  • 云计算第2次作业
  • 收藏网友的 源程序下载网
  • 「前端」从UglifyJSPlugin强制开启css压缩探究webpack插件运行机制
  • 【跃迁之路】【733天】程序员高效学习方法论探索系列(实验阶段490-2019.2.23)...
  • Android 控件背景颜色处理
  • Node + FFmpeg 实现Canvas动画导出视频
  • react 代码优化(一) ——事件处理
  • Shadow DOM 内部构造及如何构建独立组件
  • Vue.js-Day01
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • 七牛云 DV OV EV SSL 证书上线,限时折扣低至 6.75 折!
  • 前端面试题总结
  • 如何优雅的使用vue+Dcloud(Hbuild)开发混合app
  • 使用parted解决大于2T的磁盘分区
  • 我看到的前端
  • 线上 python http server profile 实践
  • 一些基于React、Vue、Node.js、MongoDB技术栈的实践项目
  • 智能合约Solidity教程-事件和日志(一)
  • No resource identifier found for attribute,RxJava之zip操作符
  • 数据可视化之下发图实践
  • ​Linux·i2c驱动架构​
  • #中的引用型是什么意识_Java中四种引用有什么区别以及应用场景
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (附源码)spring boot公选课在线选课系统 毕业设计 142011
  • (附源码)ssm教师工作量核算统计系统 毕业设计 162307
  • (一)eclipse Dynamic web project 工程目录以及文件路径问题
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • (原創) 如何刪除Windows Live Writer留在本機的文章? (Web) (Windows Live Writer)
  • (原創) 系統分析和系統設計有什麼差別? (OO)
  • (转)memcache、redis缓存
  • .apk文件,IIS不支持下载解决
  • .desktop 桌面快捷_Linux桌面环境那么多,这几款优秀的任你选
  • .NET 4.0中使用内存映射文件实现进程通讯
  • .NET Core跨平台微服务学习资源
  • .NET Framework 4.6.2改进了WPF和安全性
  • .pyc文件还原.py文件_Python什么情况下会生成pyc文件?
  • /usr/bin/perl:bad interpreter:No such file or directory 的解决办法
  • @RequestBody详解:用于获取请求体中的Json格式参数
  • [Android] Implementation vs API dependency
  • [BUUCTF]-PWN:wustctf2020_number_game解析(补码,整数漏洞)
  • [C++ 从入门到精通] 12.重载运算符、赋值运算符重载、析构函数