Sample Code
The standard InterSystems IRIS® installation includes a sample ObjectScript project that demonstrates how to generate and use InterSystems IRIS proxy classes with .NET code. This chapter describes how to compile and run the project, and provides a convenient copy of the ObjectScript source code.
Compiling and Running the .NET Test Project
The project code consists of two parts:
The RemoteTest .NET project located in <install-root>\dev\dotnet\samples\remote\test\
The %Net.Remote.DotNet.Test class, which is part of the InterSystems IRIS class library.
The following sections describe how to compile and run the project.
Compiling the .NET Assembly
Open the RemoteTest project file (RemoteTest.csproj) in Visual Studio and compile it. The DotNetGatewaySamples.dll file will be created in ..remote\test\obj\Debug. This is the assembly that will be imported into InterSystems IRIS.
Creating and Running the Server
Create an Object Gateway server description, as described in Defining an Object Gateway Server.
Start the server, as described in Running an Object Gateway Server.
Generating InterSystems IRIS Proxy Classes
To import the sample .NET classes, start a Terminal session and use the following syntax to run the ExpressImport() method of the %Net.Remote.ImportHelper class:
do ##class(%Net.Remote.ImportHelper).ExpressImport(gatewaySamplesDll,port)
where gatewaySamplesDll is a fully qualified path to DotNetGatewaySamples.dll (which you generated in step 1), and port is the port number of the Object Gateway server over which the proxy classes communicate with the .NET classes (which you started in step 3).
For example:
do ##class(%Net.Remote.ImportHelper).ExpressImport( "C:\InterSystems\IRIS\dev\dotnet\samples\remote\test\obj\Debug\DotNetGatewaySamples.dll", "55000")
The imported classes will be located in the remote/test package in the %SYS namespace.
This step should be repeated whenever you have modified or recompiled your .NET classes.
Running the InterSystems IRIS DotNet.Test Examples
The %Net.Remote.DotNet.Test class includes two ObjectScript test methods, Test() and TestArrays(). For both methods, the port argument is the number of the port over which the proxy classes communicate with the .NET classes (as described in the previous section), and the host argument identifies the machine on which the server is running. The port argument is required; the host argument is optional and defaults to 127.0.0.1 (the local machine).
The Test() method shows how to use the sample classes delivered with InterSystems IRIS. Use the following statement to run it at the Terminal:
do ##class(%Net.Remote.DotNet.Test).Test(port,host)
See The Test() Method for a listing of the ObjectScript code.
The TestArrays() method demonstrates the use of .NET arrays. Use the following statement to run it at the Terminal:
do ##class(%Net.Remote.DotNet.Test).TestArrays(port,host)
See The TestArrays() Method for a listing of the ObjectScript code.
Source Code for the Test Class
This section provides a convenient copy of the code found in the %Net.Remote.DotNet.Test class, which includes two ObjectScript test methods, Test() and TestArrays().
Class %Net.Remote.DotNet.Test Extends %RegisteredObject [ Abstract, ProcedureBlock ] { ClassMethod Test(port As %Integer, host As %String = "127.0.0.1") [ Final ] { ///... } ClassMethod TestArrays(port As %Integer, host As %String = "127.0.0.1") [ Final ] { ///... } }
The Test class includes references to %objlasterror, which should be used as a debug resource only (for example, in development code that does not yet report errors properly), so that the underlying problem can be diagnosed and the offending code's error reporting can be corrected. It is appropriate for such code to kill %objlasterror whenever it uses an error status that is an expected condition and not a reportable error.
Test() Method
The Test() method demonstrates how to interact with the DotNetGatewaySamples.dll assembly.
ClassMethod Test(port As %Integer, host As %String = "127.0.0.1") [ Final ] { ///... }
The ObjectScript method code is listed here under the following section headings:
part 1 — connect to current namespace
part 2 — create and populate a Student object
part 3 — hashtable example
part 4 — modify the hashtable
part 5 — ArrayList and List examples
part 6 — create and populate an Address object
part 7 — change an Address
part 8 — get an array of Strings
part 9 — disconnect and catch errors
The original source code for the %Net.Remote.DotNet.Test class is available in the InterSystems IRIS class library under in the %SYS namespace.
Set %objlasterror="",$ZT="Error" // connect to current namespace, use 2 second timeout Set namespace=$Namespace,timeout=2 Set classPath=##class(%ListOfDataTypes).%New() Set sampleDLL="dev/dotnet/bin/DotNetGatewaySamples.dll" Set samplePath=$SYSTEM.Util.InstallDirectory()_sampleDLL Do classPath.Insert(samplePath) // get a connection handle and connect Set gateway=##class(%Net.Remote.Gateway).%New() Set status=gateway.%Connect(host,port,namespace,timeout,classPath) If 'status Goto Error
Set student=##class(remote.test.Student).%New(gateway,29,"976-01-6712") // get, set Date Write !,"setNextClass returned: " Write student.setNextClass($zd($h,3),$zt($h),"White Hall",3.0,0) Write !,"Next class on: ",$E(student.myGetNextClassDate(),1,10) Write $E(student.getNextClassTime(),11,*),!,! // set a String Do student.mySetName("John","Smith") // set an int Do student.mySetID(27) Write "Name: ",student.myGetName(),! Write "ID: ",student.myGetID(),! Write "SSN: ",student.getSSN(),!,! Write "Static method execute: " Write ##class(remote.test.Person).myStaticMethod(gateway),!,! Do ##class(remote.test.Person).setstaticProperty(gateway,89) Write "Static set/get: " Write ##class(remote.test.Person).getstaticProperty(gateway),!!
Set grades=##class(System.Collections.Hashtable).%New(gateway) Do grades.Add("Biology",3.8) Do grades.Add("French",3.75) Do grades.Add("Spanish",2.75) Do student.mySetGrades(grades) Set grades=student.myGetGrades() Write "Student has completed the following " Write grades.getuCount()," classes:",! Set keys=grades.getuKeys().GetEnumerator() Set values=grades.getuValues().GetEnumerator() while (keys.MoveNext()) { If (values.MoveNext()) Write " ",keys.getuCurrent()," ",values.getuCurrent(),! } Write !,"Highest grade: ",student.myGetHighestGrade()
Write !,"Now taking: Calculus, Chemistry, English Comp",!,! Do student.setGrade("Calculus",3.5) Do student.setGrade("Chemistry",3.92) Do student.setGrade("English Comp",2.5) Write "English Comp Grade: ",student.getGrade("English Comp"),! Set grades=student.myGetGrades() Write !,"Student has completed the following " Write grades.getuCount()," classes:",! Set keys=grades.getuKeys().GetEnumerator() Set values=grades.getuValues().GetEnumerator() while (keys.MoveNext()) { If (values.MoveNext()) Write " ",keys.getuCurrent()," ",values.getuCurrent(),! } Write !,"Highest grade now: " Write student.myGetHighestGrade()
Set sports=##class(System.Collections.ArrayList).%New(gateway) // Example of using Type.GetType; to use it, replace the above line with the // following two lines: (also make sure to import System.Activator) // Set arrayListClass= // ##class(System.Type).GetType(gateway,"System.Collections.ArrayList") // Set sports=##class(System.Activator).CreateInstance(gateway,arrayListClass) Do sports.Add("Basketball") Do sports.Add("Tennis") Do sports.Add("Running") Do sports.Add("Swiming") Do student.mySetFavoriteSports(sports) // set/get a list of Strings Set list=student.myGetFavoriteSports() Write !,"Student's favorite sports are: ",! For i=0:1:list.getuCount()-1 { Write " "_list.getuItem(i),! }
// set an object Set home=##class(remote.test.Address).%New(gateway) Set street=##class(remote.test.Street).%New(gateway) Do street.setname("Memorial Drive") Do street.setnumber("One") Do home.mySetCity("San Diego") Do home.mySetStreet(street) Do home.mySetState("CA") Do home.mySetZip("20098") Do student.sethome(home) // get an object Write !,"Student's address: ",! Set home2=student.gethome() Write " "_student.gethome().getstreet().getname(),! Write " "_home2.myGetCity()_", "_home2.myGetState()_" "_home2.myGetZip(),!,!
Write "Change address",! Set newHome=##class(remote.test.Address).%New(gateway) Set newStreet=##class(remote.test.Street).%New(gateway) Do newStreet.setnumber("456") Do newStreet.setname("Del Monte") Do newHome.mySetCity("Boston") Do newHome.mySetState("MA") Do newHome.mySetStreet(newStreet) Do newHome.mySetZip("40480") Set tempAddress=##class(remote.test.Address).%New(gateway) Do student.getAddressAsReference(.tempAddress) Write "City, before address change: "_tempAddress.myGetCity(),! Do student.changeAddress(home,newHome) Do student.getAddressAsReference(.tempAddress) Write "City, after address change: "_tempAddress.myGetCity(),!
Set list=student.getAddressAsCollection() Write !,"Student's new address is: ",! Write " "_list.GetAt(4),! Write " "_list.GetAt(1)_", "_list.GetAt(2)_" "_list.GetAt(3),! Write !,"Old addresses:",! Set oldAddresses=##class(%ListOfObjects).%New(gateway) Set newAdd=##class(remote.test.Address).%New(gateway) Set add2=student.getOldAddresses(home,.oldAddresses,.newAdd) For i=1:1:oldAddresses.Count() { Set oldAddress=oldAddresses.GetAt(i) Write !,"Address "_i_":",! Write oldAddress.getstreet().getnumber() Write " "_oldAddress.getstreet().getname(),! Write oldAddress.getcity() Write ", "_oldAddress.getstate() Write " "_oldAddress.getzip(),! } Write !,"Most recent Address:",! Write add2.getstreet().getnumber()_" "_add2.getstreet().getname(),! Write add2.getcity() Write ", "_add2.getstate() Write " "_add2.getzip(),! Write !,"Least Recent Address: ",! Write newAdd.getstreet().getnumber()_" "_newAdd.getstreet().getname(),! Write newAdd.getcity() Write ", "_newAdd.getstate() Write " "_newAdd.getzip(),!
// Disconnect Do gateway.%Disconnect() Write !,"Test Successfully Completed" Quit Error ; an error occurred Use 0 If %objlasterror'="" { Write $system.OBJ.DisplayError(%objlasterror) } Else { Write $ze }
The TestArrays() Method
The TestArrays() method demonstrates the use of .NET arrays.
ClassMethod TestArrays(port As %Integer, host As %String = "127.0.0.1") [ Final ] { ///... }
The ObjectScript method code is listed here under the following section headings:
The original source code for the %Net.Remote.DotNet.Test class is available in the InterSystems IRIS class library under in the %SYS namespace.
Set %objlasterror="",$ZT="Error",namespace=$Namespace,timeout=2 Set classPath=##class(%ListOfDataTypes).%New() Set sampleDLL="dev/dotnet/bin/DotNetGatewaySamples.dll" Set samplePath=$SYSTEM.Util.InstallDirectory()_sampleDLL Do classPath.Insert(samplePath) Set gateway=##class(%Net.Remote.Gateway).%New() Set status=gateway.%Connect(host,port,namespace,timeout,classPath) If 'status Goto Error
Set test=##class(remote.test.Person).%New(gateway) // test simple string arrays Set stringArray=##class(%ListOfDataTypes).%New() Do stringArray.Insert("test string one") Do stringArray.Insert("test string two") Do stringArray.Insert("test string three") Do stringArray.Insert("test string four") // test simple string arrays Do test.setStringArray(stringArray) Set outStringArray=test.getStringArray() For i=1:1:outStringArray.Count() { Write "String "_i_" : "_outStringArray.GetAt(i),! }
// test array of objects Set home=##class(remote.test.Address).%New(gateway) Set street=##class(remote.test.Street).%New(gateway) Do street.setname("Memorial Drive") Do street.setnumber("One") Do home.mySetCity("Cambridge") Do home.mySetStreet(street) Do home.mySetState("MA") Do home.mySetZip("02142") Set home2=##class(remote.test.Address).%New(gateway) Set street2=##class(remote.test.Street).%New(gateway) Do street2.setname("Santa Cruz Ave") Do street2.setnumber("4555") Do home2.mySetCity("San Diego") Do home2.mySetStreet(street2) Do home2.mySetState("CA") Do home2.mySetZip("92109")
Set addressArray=##class(%ListOfObjects).%New() Do addressArray.Insert(home) Do addressArray.Insert(home2) Do test.setAddressArray(addressArray) Set addressArray=test.getAddressArray() For i=1:1:addressArray.Count() { Set home=addressArray.GetAt(i) Write !,"Address "_i_":",! Write home.getstreet().getnumber()_" "_home.getstreet().getname(),! Write home.getcity() Write ", "_home.getstate() Write " "_home.getzip(),! }
// byte[] is mapped as %GlobalBinaryStream Write !,"Byte array test:",! Set byteStream=##class(%GlobalBinaryStream).%New() Do byteStream.Write("Global binary stream") // Note that byteStream is passed in by value, so any changes on the DotNet // side will be ignored. The next example will pass the stream by reference // meaning changes on the DotNet side will be reflected here as well Do test.setByteArray(byteStream) Set result=test.getByteArray() Write result.Read(result.SizeGet()),! Set readStream=##class(%GlobalBinaryStream).%New() // we need to 'reserve' a number of bytes since we are passing the stream // by reference (DotNet's equivalent is byte[] ba = new byte[max];) For i=1:1:50 Do readStream.Write("0") Set bytesRead=test.read(.readStream,50) Write readStream.Read(bytesRead),!
Do gateway.%Disconnect() Write !,"Test Successfully Completed" Quit Error Use 0 If %objlasterror'="" { Write $system.OBJ.DisplayError(%objlasterror) } Else { Write $ze } // end of method TestArrays()