This chapter describes the mapping between .NET objects and the InterSystems IRIS® proxy classes that represent the .NET objects.
Only classes, methods, and fields marked as public are imported.
This chapter describes mappings of the following types:
Assembly and Class Names
Assembly and class names are preserved when imported, except that each underscore (_) in an original .NET class name is replaced with the character u and each dollar sign ($) is replaced with the character d in the InterSystems IRIS proxy class name. Both the u and the d are case-sensitive (lowercase).
Primitive types and primitive wrappers map from .NET to InterSystems IRIS as shown in the following table.
The result of importing a .NET class is an ObjectScript abstract class. For each .NET property that does not already have corresponding getter and setter methods (imported as is), the Object Gateway engine generates corresponding Object Script getter and setter methods. It generates Setters as setXXX, and getters as getXXX, where XXX is the property name. For example, importing a .NET String property called Name results in a getter method getName() and a setter method setName(%Library.String). The Object Gateway also generates set and get class methods for all static members.
After you perform the Object Gateway import operation, all methods in the resulting InterSystems IRIS proxy class have the same name as their .NET counterparts, subject to the limitations described in the Method Names section. They also have the same number of arguments. The type for all the InterSystems IRIS proxy methods is %Library.ObjectHandle(). The Object Gateway engine resolves types at runtime.
For example, the .NET method test:
public boolean checkAddress(Person person, Address address)
is imported as:
Method checkAddress(p0 As %Library.ObjectHandle, p1 As %Library.ObjectHandle) As %Library.ObjectHandle
While ObjectScript does not support overloading, you can still map overloaded .NET methods to InterSystems IRIS proxy classes. This is supported through a combination of largest method cardinality and default arguments. For example, if you are importing an overloaded .NET method whose different versions take two, four, and five arguments, there is only one corresponding method on the InterSystems IRIS side; that method takes five arguments, all of %ObjectHandleOpens in a new window type. You can then invoke the method on the InterSystems IRIS side with two, four, or five arguments. The Object Gateway engine then tries to dispatch to the right version of the corresponding .NET method.
While this scheme works reasonably well, avoid using overloaded methods with the same number of arguments of similar types. For example, the Object Gateway has no problems resolving the following methods:
test(int i, string s, float f) test(Person p) test(Person p, string s, float f) test(int i)
However, avoid the following:
test(int i) test(float f) test(boolean b) test(object o)
For better results using the Object Gateway, use overloaded .NET methods only when absolutely necessary.
InterSystems IRIS has a limit of 31 characters for method names. Ensure your .NET method names are not longer than 31 characters. If the name length is over the limit, the corresponding InterSystems IRIS proxy method name contains only the first 31 characters of your .NET method name. For example, if you have the following methods in .NET:
thisDotNetMethodHasAVeryLongName(int i) // 32 characters long thisDotNetMethodHasAVeryLongNameLength(int i) // 38 characters long
InterSystems IRIS imports only one method with the following name:
thisDotNetMethodHasAVeryLongNam // 31 characters long
The .NET reflection engine imports the first one it encounters. To find out which method is imported, you can check the InterSystems IRIS proxy class code. Better yet, ensure that logging is turned on before the import operation. The Object Gateway log file contains warnings of all method names that were truncated or not imported for any reason.
Each underscore (_) in an original method name is replaced with the character u and each dollar sign ($) is replaced with the character d. Both the u and the d are case-sensitive (lowercase). If these conventions cause an unintended overlap with another method name that already exists on the InterSystems IRIS side, the method is not imported.
Finally, InterSystems IRIS class code is not case-sensitive. So, if two .NET method names differ only in case, InterSystems IRIS only imports one of the methods and writes the appropriate warnings in the log file.
InterSystems IRIS projects .NET static methods as class methods in the InterSystems IRIS proxy classes. To invoke them from ObjectScript, use the following syntax:
// calls static .NET method staticMethodName(par1,par2,...) Do ##class(className).staticMethodName(gateway,par1,par2,...)
You invoke .NET constructors by calling %New(). The signature of %New() is exactly the same as the signature of the corresponding .NET constructor, with the addition of one argument in position one: an instance of the Object Gateway. The first thing %New() does is to associate the proxy instance with the provided Object Gateway instance. It then calls the corresponding .NET constructor. For example:
// calls Student(int id, String name) .NET constructor Set Student=##class(gateway.Student).%New(Gateway,29,"John Doe")
The Object Gateway projects and imports .NET static final variables (constants) as Final Parameters. It preserves the names when imported, except that it replaces each underscore (_) with the character u and each dollar sign ($) with the character d. Both the u and the d are case-sensitive (lowercase).
For example, the following static final variable:
public const int DOTNET_CONSTANT = 1;
is mapped in ObjectScript as:
Parameter DOTNETuCONSTANT As INTEGER = 1;
From ObjectScript, access the parameter as:
OUT and REF Parameters
The Object Gateway supports passing parameters by reference, by supporting the .NET OUT and REF parameters. Only objects may be used as OUT and REF parameters; scalar values are not supported. For this convention to work, you must preallocate a temporary object of the corresponding type. Then call the method and pass that object by reference. The following are some examples:
public void getAddressAsReference(out Address address)
To call this method from ObjectScript, create a temporary object; there is no need to set its value. Then call the method and pass the OUT parameter by reference, as follows:
Set tempAddress=##class(remote.test.Address).%New(gateway) Do student.getAddressAsReference(.tempAddress)
The following example returns an array of Address objects as an OUT parameter:
void getOldAddresses(out Address address)
To call the previous method from ObjectScript, use the following code:
Set oldAddresses=##class(%ListOfObjects).%New(gateway) Do person.getOldAddresses(.oldAddresses)
Arrays of primitive types and wrappers are mapped as %Library.ListOfDataTypesOpens in a new window. Arrays of object types are mapped as %Library.ListOfObjectsOpens in a new window. Only one level of subscripts is supported.
The Object Gateway projects .NET byte arrays (byte) as %Library.GlobalBinaryStreamOpens in a new window. Similarly, it projects .NET char arrays (char) as %Library.GlobalCharacterStreamOpens in a new window. This allows for a more efficient handling of byte and character arrays.
You can pass byte and stream arrays either by value or by reference. Passing by reference allows changes to the byte or character stream on the .NET side visible on the InterSystems IRIS side as well. For example, using the following:
System.Net.Sockets.Stream.Read(byte buffer, int offset, int size)
byte buffer = new byte[maxLen]; int bytesRead = inputStream.Read(buffer,offset,maxLen);
The equivalent code in ObjectScript:
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)
The following example passes a character stream by value, meaning that any changes to the corresponding .NET char is not reflected on the InterSystems IRIS side:
Set charStream=##class(%GlobalCharacterStream).%New() Do charStream.Write("Global character stream") Do test.setCharArray(charStream)
ObjectScript has limited support for recasting; namely, you can recast only at a point of a method invocation. However, since all InterSystems IRIS proxies are abstract classes, this should be sufficient.
.NET Standard Output Redirection
The Object Gateway automatically redirects any standard .NET output in the corresponding .NET code to the calling InterSystems IRIS session. It collects any calls to System.out in your .NET method calls and sends them to InterSystems IRIS to display in the same format as you would expect to see if you ran your code from .NET. To disable this behavior and direct your output to the standard output device as designated by your .NET code (in most cases that would be the console), set the following global reference in the namespace where the session is running:
Set ^%SYS("Gateway","Remote","DisableOutputRedirect") = 1
Rather than aborting import, the Object Gateway engine silently skips over all the members it is unable to generate. If you repeat the import step with logging turned on, InterSystems IRIS records all skipped members (along with the reason why they were skipped) in the WARNING section of the log file.
The Object Gateway engine always makes an attempt to preserve assembly and method names, parameter types, etc. That way, calling an InterSystems IRIS proxy method is almost identical to calling the corresponding method in .NET. It is therefore important to keep in mind ObjectScript restrictions and limits while writing your .NET code. In a vast majority of cases, there should be no issues at all. You might run into some ObjectScript limits. For example:
.NET method names should not be longer than 30 characters.
You should not have 100 or more arguments.
You should not try to pass String objects longer than 32K.
Do not rely on the fact that .NET is case-sensitive when you choose your method names.
Do not try to import a static method that overrides an instance method.
The Object Gateway cannot generate proxy classes for .NET generic classes. It similarly cannot import .NET classes with generic subclasses or subinterfaces.
.NET Events are not supported — InterSystems IRIS code cannot be called from delegate notifications.
For details on ObjectScript naming conventions, see Variables in Using ObjectScript, Naming Conventions in Defining and Using Classes, and Rules and Guidelines for Identifiers in the Orientation Guide for Server-Side Programming.