V. Supplement of remoting Basics
Based on the above description, a simple remoting is basically completed.Program. This is a standard method to create a remoting program, but in actual development, what we encounter may be strange. If we only grasp one so-called "standard ", it is impossible to imagine that you can "Try it out and eat it all over the sky.
1. register multiple channels
In remoting, multiple channels can be created simultaneously, that is, different channels can be created based on different ports. However, remoting requires that the channel name must be different because it must be used as the unique identifier of the channel. Although ichannel has the channelname attribute, this attribute is read-only. Therefore, the method for creating channels described above cannot meet the requirements for registering multiple channels at the same time.
At this time, we must use the idictionary interface in system. Collection:
Register the TCP channel:
Idictionary tcpprop = new hashtable (); Tcpprop ["name"] = "tcp9090 "; Tcpprop ["Port"] = 9090; Ichannel channel = new tcpchannel (tcpprop, New binaryclientformattersinkprovider (), New binaryserverformattersinkprovider ()); Channelservices. registerchannel (Channel ); |
Register an HTTP channel:
Idictionary httpprop = new hashtable (); Httpprop ["name"] = "http8080 "; Httpprop ["Port"] = 8080; Ichannel channel = new httpchannel (httpprop, New soapclientformattersinkprovider (), New soapserverformattersinkprovider ()); Channelservices. registerchannel (Channel ); |
You can define different channel names in the name attribute.
2. Remote Object metadata relevance
Because remote objects are used on both the server and client, the common method is to generate two identical object DLL files and add references respectively. However,CodeSecurity, and reduce the client's relevance to remote object metadata, we need to modify this method. That is, remote objects are implemented on the server side, while metadata of these implementations is deleted on the client side.
Because of the different activation modes, the methods for creating objects on the client are also different, so the relevance of metadata should be separated into two cases.
(1) wellknown activation mode:
Implemented through interfaces. On the server side, interfaces and specific classes are provided, while on the client side, only interfaces are provided:
Public interface iserverobject { Person getpersoninfo (string name, string sex, int age ); }Public class serverobject: marshalbyrefobject, iserverobject {......} |
Note: The names of the object Assembly generated on both sides must be the same. Strictly speaking, the namespace names must be the same.
(2) Client activation mode:
As mentioned above, for the client activation mode, whether the static method or the createinstance () method is used, the constructor must be called on the client to instantiate the object. Therefore, the remote object we provide on the client cannot only provide interfaces, but there is no class implementation. In fact, there are two ways to separate metadata from remote objects:
A. Use the wellknown activation mode to simulate the client activation mode:
The method is to use the "Abstract Factory" in the design pattern. The following class chart describes the overall solution:
We add Abstract Factory interfaces and implementation classes to remote objects on the server:
Public interface iserverobject { Person getpersoninfo (string name, string sex, int age ); }Public interface iserverobjfactory { Iserverobject createinstance (); } Public class serverobject: marshalbyrefobject, iserverobject { Public Person getpersoninfo (string name, string sex, int age) { Person = new person (); Person. Name = Name; Person. Sex = sex; Person. Age = age; Return person; } } Public class serverobjfactory: marshalbyrefobject, iserverobjfactory { Public iserverobject createinstance () { Return new serverobject (); } } |
Then, only the factory interface and the original object interface are provided in the remote object of the client:
Public interface iserverobject { Person getpersoninfo (string name, string sex, int age ); }Public interface iserverobjfactory { Iserverobject createinstance (); } |
We use wellknown activation mode to register remote objects on the server:
// Transfer object; Remotingconfiguration. registerwellknownservicetype ( Typeof (serverremoteobject. serverobjfactory ), "Servicemessage", wellknownobjectmode. singlecall ); |
Note that the registration is not a serverobject class object, but a serverobjfactory class object.
Client:
Serverremoteobject. iserverobjfactory serverfactory = (Serverremoteobject. iserverobjfactory) activator. GetObject ( Typeof (serverremoteobject. iserverobjfactory ), "TCP: // localhost: 8080/servicemessage ");Serverremoteobject. iserverobject serverobj = serverfactory. createinstance (); |
Why is this a simulation of the client activation mode? From the perspective of the activation method, we use the singlecall mode to activate the object. However, activation is not a remote object to be passed, but a factory object. If the client wants to create a remote object, it should also be obtained through the createinstance () method of the factory object. This method is called on the client. Therefore, the implementation method is equivalent to the client activation mode.
B. Use Substitution classes to replace metadata of remote objects
In fact, we can use a trick to cheat remoting. The alternative class mentioned here is trick. Since the service is provided, the implementation details of the remote object passed by remoting are of course placed on the server side. However, to put a copy of the object on the client, it is helpless because the client must call the constructor. Since the specific implementation is on the server side and in order to be instantiated on the client side, it is better to achieve this on the client side. As for the Implementation Details, you don't have to worry about it.
If the remote object has a method, the server provides the method implementation, and the client provides this method. As for the implementation, you can throw an exception, or return a null value. If the method returns void, it can be null. The key is that this method is required for this client class object. The implementation of this method is similar to the declaration of the method, so I say it is a trick. If the method is used, the constructor is also used.
It is more intuitive to use code to describe this "conspiracy:
Server:
Public class serverobject: marshalbyrefobject { Public serverobject () {}Public Person getpersoninfo (string name, string sex, int age) { Person = new person (); Person. Name = Name; Person. Sex = sex; Person. Age = age; Return person; } } |