.net里面可远程操作对象有2种:值封送对象(其特点是通过序列化操作可保存会话状态),引用封送对象(不能使用序列化保存会话状态,只能通过创建副本进行远程操作)。在remoting里面由于单元素对象激活和客户激活是有会话状态的,所以牵涉到保存对话状态,这时的远程操作就必须使用值封送对象,值封送对象可以通过序列化操作来保存会话状态;可以申请新的对象实例,并且对新的新的对象实例的操作或者set(写入的值),传到服务器端使用(这就是保存会话状态);而单调用元素是没有会话状态的,所以不能够使用值封送对象来远程操作,只能使用引用封装对象,只能在客户端创建一个服务器端的副本操作,意思是同样可以创建新的对象实例,但对其操作的结果只能是在本地的副本上面,不能返回到服务器端,不能传到服务器端使用。只能在本地使用。分别看看实例:首先看客户端调用:我们先来修改一下远程对象:dll对象的修改: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; } } }} 客户端的修改: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(600); app.SetMBV(mbv); Console.WriteLine(app.UseMBV()); //mbr=new RemoteObject.MBR(200); //app.SetMBR(mbr); //Console.WriteLine(app.UseMBR()); Console.ReadLine(); 结果可以看到输出100,200,600,就象前面说的一样,600是我们用了set方法,象新建的对象里面输入的值,而这个值同样也被传到了服务器端里面,这就是序列化的保存了会话状态。这个对于客户端激活和Singleton是同样有效的。 看看如果是Singleton我们也来试试。 客户端程序修改:RemoteObject.MyObject app=(RemoteObject.MyObject)Activator.GetObject(typeof(RemoteObject.MyObject),System.Configuration.ConfigurationSettings.AppSettings["ServiceURL"]); 客户端配置文件同样也要修改. 得到的结果和客户端激活完全一样。 怎样去理解不保存对话状态而调用远程对象呢,我们用dataset来试一下:远程对象修改如下: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就是从服务器上面取下来的。这个结果是2个结果组合而成。(感谢lovecherry的blog,我的文章里面加入了一些自己的理解和思考,如果大家想看到纯净版的remoting请看http://www.cnblogs.com/lovecherry。不敢掠人之美。)