Although CORBA objects are by definition only passed by reference, it is sometimes useful to pass objects by value as well. This is supported by the CORBA IDL 'valuetype' declaration.
A valuetype contains the state of an object that is to be transferred by value. It can also contain some meta information as to where the implementation of the object can be found. Since a CORBA server may reside on an arbitrary platform, the code for this implementation cannot be transferred as well, but needs to be implemented locally on the target systems.
In order to provide a container for the state members of the valuetype an abstract class is generated together with a factory interface for a system independent access to the constructor. Any implementation of the valuetype has to be derived from the generated abstract class.
Moreover, J-Integra® Espresso conveniently provides the developer with a generated default implementation of this factory interface.
CORBA IDL valuetype <---> Ics.CORBA.portable.StreamableValue <---> Ics.CORBA.portable.ValueFactory |
module Valtype { valuetype Info { // explicit state to transport: private string _name; private string _message; // public interface: string toString(); // public Factory interface: factory create(in string name, in string message); }; interface Greetings { Info hello( in Info who); }; }; |
Beside the usual code for mapping the 'Greetings' interface, the IDL compiler will generate code for mapping the 'Info' valuetype:
Because this default factory has to refer explicitly to an implementation of the valuetype, we have to provide an implementation suitable for the default factory to avoid implementing an own factory as well.
Therefore, our implementation must be named '<valuetype>Impl' and must be placed within the same namespace (InfoSrvImpl.cs):
namespace Valtype { public class InfoImpl: Valtype.Info { public InfoImpl() { } public InfoImpl( string name, string message ) { _name = name; _message = message; } public override string toString() { return "Info: " + _name + " says " + _message + " (server implementation)"; } } } |
public class GreetingsImpl: Valtype.GreetingsPOA { public override Valtype.Info hello( Valtype.Info theInfo ) { System.Console.WriteLine("\nhello called with\n {0}", theInfo.toString()); Valtype.InfoDefaultFactory oFactory = new Valtype.InfoDefaultFactory(); Valtype.Info oInfo = oFactory.create( "Jack", "The weather will be bad!" ); System.Console.WriteLine("\nReturning\n {0}", oInfo.toString()); return oInfo; } } |
namespace Valtype { public class InfoImpl: Valtype.Info { public InfoImpl() { } public InfoImpl( string name, string message ) { _name = name; _message = message; } public string name { set { _name = value; } get { return _name; } } public string message { set { _message = value; } get { return _message; } } public override string toString() { return "Info: " + _name + " says " + _message + " (client implementation)"; } } } |
(Of course, we could have used the same implementation on both sides, due to the fact that our example transports from .NET to .NET.)
There is no need to use the factory (as we did on the server side).
It is also possible to create the implementation of the valuetype object straightforward and use it with its local interface (ValuetypeClt.cs):
Valtype.Greetings oGreetings = Valtype.GreetingsHelper.narrow( oGreetingsObj ); // Create parameter for server call: Valtype.InfoImpl oInfo = new Valtype.InfoImpl(); oInfo.name = "John"; oInfo.message = "The weather is fine!"; System.Console.WriteLine( "\nCall server with Info:\n {0}", oInfo.toString() ); Valtype.Info oRetInfo = oGreetings.hello( oInfo ); System.Console.WriteLine( "\nServer answered Info:\n {0}", oRetInfo.toString() ); |
a.) Start the Server.
b.) Start the Client.