Remoting Step by Step 3: complex objects
Complex objects are examples of complex classes, such as dataset that we often use in applications and our own classes, generally, we will pass some of our own classes to the remote object, or require the object to return the processing result. In this case, the Remote Object usually needs to be stateful, the last time we talked about several activation modes, we mentioned that only client activation and Singleton are stateful, while the difference between client activation and Singleton is that Singleton is a shared object. Therefore, we can select an activation method that meets our own conditions:
Status has its own instance
Singleton has none
Singlecall does not have
Client activation has
Here, we will first demonstrate the transfer of custom classes:
First, let's talk about the concept: mbv is value-based encoding. objects are stored in data streams and used to create object copies at the other end of the network. MBR creates a proxy on the client according to the reference group, creates an objref instance from a remote object, and serializes the instance.
Let's first modify the remote object: 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)
{
This. _ mbv = mbv;
}
Public int usembv ()
{
Return this. _ mbv. Data;
}
Public void setmbr (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;
}
}
}
}
The get method is used to return objects from the server. The set method is used to pass objects to the server. The use method is used to test whether the status of remote objects is saved.
Let's test the client activation mode first: (the server side is not mentioned) 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 = app. getmbv ();
Console. writeline (mbv. data );
Remoteobject. 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 ();
Display: 100,200,100
The first two 100,200 items indicate that we have obtained the objects returned by the server (mbv and MBR methods respectively). The next 100 items indicate that the client has created an mbv object and passed it to the server, because the client activation mode is stateful, we can use this object to output 100. At last, we commented a few lines. When the annotation was opened, an exception occurred. "due to security restrictions, the system cannot be accessed. runtime. remoting. objref." The reason is described in the [Channel] section.
Now let's test Singleton (do not forget to modify the URI in the client configuration file) 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"])});
The subsequent statements are omitted. After running, 100,200,100-"Singleton can also be saved.
What about singlecall? Modify the config of the server and run it again. In "console. writeline (App. usembv ();", "the instance of the object that has not been referenced is displayed ." Because the server cannot save the status of the remote object, an error occurs.
Let's take a look. net built-in complex objects, such as dataset, may be passed in and out of dataset and datatable in the application is more common, some non-sequential class we cannot directly pass, such as datarow, etc, when you want to transfer data, you can consider putting it into the able container.
Modify the remote object as follows: 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;
}
}
}
Modify the client as follows: remoteobject. myobject APP = (remoteobject. myobject) activator. GetObject (typeof (remoteobject. myobject), system. configuration. configurationsettings. deleettings ["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 ();
The output data_ OK is displayed after running. No matter which mode is used for activation, data_ OK is obtained because the remote object is not required to save the status.
Summary:
All local objects that must span the application domain must be passed by numerical value, and[Serializable]Custom Attributes are marked, otherwise they must be implementedIserializableInterface. When an object is passed as a parameter, the Framework serializes the object and transmits it to the target application domain. The object will be re-constructed in the target application domain. Local objects that cannot be serialized cannot be passed to other application domains, and thus cannot be processed remotely. FromMarshalbyrefobjectYou can export any object to a remote object. When a client activates a remote object, it receives the proxy of the remote object. All operations on the proxy are appropriately reoriented so that the remote processing infrastructure can correctly intercept and forward calls. Although this type of redirection has some impact on the performance, the JIT compiler and execution engine (EE) have been optimized to allow proxies and remote objects to reside in the same application domain, prevent unnecessary performance loss. If the proxy and remote object are not in the same application domain, all method call parameters in the stack will be converted to messages and transmitted to the remote application domain, these messages will be converted to the original stack frame in the remote application domain, and the method call will also be called. The same process is also used when returning results from a method call.
Related msdn chapters are attached:
Http://msdn.microsoft.com/library/CHS/cpguide/html/cpconRemotableNon-RemotableObjects.asp