Performing Common Synergy .NET Coding Tasks
The following sections briefly describe how to perform coding tasks that are common when creating Synergy .NET applications and when enhancing traditional Synergy code for Synergy .NET.
Instantiating and using a .NET class
To use functionality from a .NET Framework or Synergy .NET class in a Synergy .NET method,
|
1.
|
In your source file, add an IMPORT statement to import the namespace that contains the .NET class to be used. |
import SomeNamespace
|
2.
|
Declare a local variable of that class type using the following syntax within a method: |
record
var, @SomeClass
|
3.
|
Instantiate the class by calling its constructor and assigning it to a local variable. For example, |
var = new SomeClass(SomeParams)
|
4.
|
Call an accessible method from the .NET class using the local variable. For example, |
var.SomeMethod(SomeParams)
Inheriting and overriding a .NET class
To override a method in a .NET Framework or Synergy .NET class with different functionality,
|
1.
|
In your source file, add an IMPORT statement to import the namespace that contains the .NET base class definition. |
import SomeNameSpace
|
2.
|
Add the .NET base class name to the class declaration using the EXTENDS keyword. |
class MyClass extends System.Object
|
3.
|
Add a method declaration and implementation to the class for any base class method to be overridden. The signature of the method must match the base class method signature. |
Creating a Synergy .NET interface
To create a new Synergy .NET interface and compile it into a Synergy application for use by .NET applications,
|
1.
|
In your source file, declare an interface within a namespace declaration using the INTERFACE statement. For example, |
interface IMyInterface ;Put interface members here
endinterface
|
2.
|
Add one or more method prototype declarations within the class declaration. Each method prototype declaration specifies the method’s name, return type, and parameter signature. For example, |
interface IMyInterface
method mymethod, i4
p1, i4
end
endinterface
Writing an implementation for a .NET interface
To write an implementation for an interface described in a .NET assembly,
|
1.
|
In your source file, add an IMPORT statement to import the namespace that contains the .NET interface to be implemented. For example, |
import SomeNamespace
|
2.
|
Add the .NET interface to a Synergy .NET class declaration using the IMPLEMENTS keyword in the CLASS statement. For example, |
class MyClass implements IDisposable, IDisposable2
|
3.
|
Add methods to the Synergy .NET class to implement all methods of the .NET interface. The Synergy .NET method signature must match the signature as defined in the interface. For example, |
class MyClass implements IDisposable,IDisposable2
public method IDisposable.Dispose, void
proc ;Add logic to release resources here
mreturn
endmethod
public method IDisposable2.Dispose, void
proc ;Add logic to release resources here
mreturn
endmethod
endclass
Creating a Synergy .NET class that uses generics
Generics enable you to substitute types dynamically into parameters, fields, or anywhere else a type is used in a class. To add a new generic Synergy .NET class and compile it into a Synergy .NET assembly,
|
1.
|
Create a new file, and add a generic class declaration. (Generic types are added as type parameters. In the example below, <T> is the type parameter.) |
class MyClass<T>
|
2.
|
Add a method declaration that uses the generic type into the class declaration. The generic type can be used as a method’s return type, parameter type, or local variable type. |
class MyClass<T>
public mymethod, T
p1, T
proc
mreturn p1
endmethod
endclass
|
3.
|
Add member fields that use the generic type to the class declaration. |
class MyClass<T>
public myfield, T
endclass
Using a generic .NET class
To use a generic .NET class in a Synergy .NET application,
|
1.
|
In your source file, add code to use the generic class by first instantiating the generic class and providing another type as a substitute for the type parameter. This substitute type must meet all of the type parameter constraints declared in the generic class. |
c1, @MyClass
c1 = new MyClass<SomeOtherClass> ()
|
2.
|
Write code to use the instantiated class just like any other normal Synergy .NET class. |
Declaring and using a delegate
A delegate enables you to pass a method as a parameter value. To add a delegate to a Synergy .NET class and use it in an application,
|
1.
|
Create a Synergy .NET class. |
|
2.
|
Add a delegate to the class by defining a delegate class member that defines a method prototype. |
class class1
public delegate mydelegate, i4
p1, i4
enddelegate
endclass
|
3.
|
Define a method that uses the delegate as a parameter value. (See the Examples section for the DELEGATE statement for an example of steps 3, 4, and 5). |
class class1
public method mymethod, i4
p1, @mydelegate
record
v1, i4
proc
v1 = p1(5) ;call the delegate passing in a 5
mreturn v1
endmethod
endclass
|
4.
|
Define a method that will be passed as the parameter value in place of the delegate when calling the above method. The signature of this routine must match the delegate. For example, |
class class1
public method subthis, i4
p1, i4
proc
mreturn p1 * 2
endmethod
endclass
|
5.
|
Call the routine in step 3, passing in the method as a parameter value to substitute for the delegate. |
c1, @class1
md, @class1.mydelegate
v1, i4
c1 = new class1()
md = new class1.mydelegate(c1.subthis)
v1 = c1.mymethod(md)
Declaring and using an event
Events are usually used to provide notifications and are used heavily in forms. To add an event to a Synergy .NET class and use it in an application,
|
1.
|
Create a Synergy .NET class. |
|
2.
|
Add a delegate declaration to the class. |
class class1
public delegate mydelegate, void
msg, a
enddelegate
endclass
|
3.
|
Add an event to the class by defining an event class member and using the previously defined delegate. For example, |
class class1
public event myevent, @mydelegate
endclass
|
4.
|
Add a method to register for the event. The signature of this method must match the delegate. |
class class1
public method mymethod, void
msg, a
proc
open(2,o,"tt:")
writes(2,"in mymethod "+msg)
close(2)
mreturn
endmethod
endclass
|
5.
|
Register the method as an event handler for the event by adding a call to ADDHANDLER. |
c1, @class1
c1 = new class1()
addhandler(c1.myevent, c1.mymethod)
|
6.
|
Add a call to RAISEEVENT to raise the event, which causes all registered event handlers to be executed. Note that parameter values to be passed to RAISEEVENT are passed on to the registered event handlers. |
raiseevent(c1.myevent, "pass this message")
Calling a routine in a Synergy assembly from another assembly
A Synergy routine in a .NET assembly can be called from another Synergy .NET assembly or from a .NET assembly created with another language. Requirements vary depending on the types of passed data and whether the calling assembly was created with Synergy.
Calling from a Synergy assembly
The simplest case is to call a Synergy routine from another Synergy .NET assembly. To do this, do the following in the calling assembly:
|
2.
|
If the Synergy routine is part of an explicitly declared namespace, import the namespace. |
|
3.
|
If the routine is a part of a class, call it as a class method. For example, |
MyClass MyClassInstance = new MyClass()
MyClassInstance.Mysubroutine(arg1, arg2)
If the Synergy routine is not part of a class, call it as an external subroutine or function. For example,
xcall MySubroutine(arg1, arg2)
var1 = MyFunction(arg3, arg4)
MySubroutine2(arg5)
Calling from a non-Synergy assembly and passing .NET types
When calling a Synergy routine from a non-Synergy .NET assembly, the method you’ll use depends on the type of data passed. If only .NET types are passed, follow the steps below; otherwise see Calling from a non-Synergy assembly and passing structures or non-.NET types. (.NET types are value types that correspond to .NET System.type types. For information, see “Understanding .NET data types.)
In the calling assembly,
|
2.
|
Import the namespace for the Synergy routine. (For example, use a “using” statement in C#.) If the Synergy routine is not in an explicitly defined namespace, it is assigned to the default namespace, _NS_name, where name is the name of the assembly. |
|
3.
|
Call the Synergy routine as a class method. If the Synergy routine is not part of a class, the routine is considered a static method of the default class, _CL. |
For example, the Synergy code below includes a subroutine (MySubroutine) and a function (MyFunction) that are not part of a namespace or class:
import System
import System.Collections.Generic
import System.Text
subroutine MySubroutine
required out int1 ,int // .NET
required in string1 ,string // types
proc
open(1, o, "tt:")
writes(1, string1)
int1 = 1
sleep Int1
close(1)
return
endsubroutine
function MyFunction
required out int1 ,int // .NET
required in string1 ,string // types
record
result ,int ,0
proc
open(1, o, "tt:")
writes(1, string1)
int1 = 2
sleep 1
close(1)
freturn (result)
endfunction
To call the routines in the Synergy code above, the following C# program imports the default namespace (for this example, _NS_MyDll) and calls the routines as methods of the default class _CL:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using _NS_MyDll; //Import namespace (in this case, the default namespace).
namespace InteropConsoleApp
{
class Program
{
static int arg1;
static string arg2 = "A string";
static int freturn;
static void Main(string[] args)
{
_CL.MySubroutine(out arg1, arg2); //Call subroutine as a method.
Console.WriteLine(arg1);
freturn = _CL.MyFunction(out arg1, arg2); //Call function as a method.
Console.WriteLine(arg1);
Console.WriteLine(freturn);
Console.ReadLine();
}
}
}
Calling from a non-Synergy assembly and passing structures or non-.NET types
If a Synergy routine has a parameter or return value that accepts or passes a structure or a data type that is not a .NET type, do one of the following to call it from a non-Synergy assembly:
- Use a Synergy/DE interop project to create the assembly for the Synergy routine. When you use an interop project, wrapper classes with data type mappings and classes for passed structures are generated when the project is built.
- Create your own mappings for types that are not .NET types and for passing Synergy structures.
- Use Synergy PintypeDesc() classes in the assembly that calls the Synergy routine. See Using Synergy data type classes in non-Synergy assemblies.
We recommend the first method, using a Synergy/DE interop project, which will include code and generated classes that automate data type mapping and record-to-class mappings for structures. Note, however, that the interop project type was designed for converting xfServerPlus routines for native .NET access (see Converting xfServerPlus routines for native .NET access). Consequently, code that you write for use with an interop project must adhere to many of the same requirements as code written for use with xfServerPlus. For example, it must be written in the form of a subroutine or function (not a method) and must not be included in a class.
If you are not familiar with writing code for use with xfServerPlus, you may want to review Preparing Your Synergy Server Code particularly the information on passing data when using a .NET client, including the sections below:
To use an interop project to access a Synergy routine,
|
1.
|
Create a Synergy/DE interop project by selecting Synergy/DE > Interop in the New Project window in Visual Studio. |
|
2.
|
Write and attribute the Synergy code. Generated classes that wrap the Synergy code are based on routine definitions in the code and on attributes when necessary. For example, the interface property of the xfMethod attribute is used for the name of the generated wrapper class, and the method name defaults from the routine name. See Using attributes to define Synergy methods, and note the following: |
- The interop project will include the SynergyRoutines.dbl file, which has utility routines needed for date conversions and for compatibility with xfNetLink .NET clients. Do not make changes to this file or remove it from the project. Add your Synergy routines to a new DBL code file (Project > Add New Item > Code File).
- Do not put the Synergy routine in a class. Other Synergy routines can be in classes, but code that you attribute (i.e., routines for which class wrappers will be generated) should not be in a class.
- Structures passed as ordinary parameters or arrays must be .INCLUDEd from the repository and defined as a structfield in your code. Passed structures become classes in generated code, and fields in the structure become properties of these classes. In addition to see Passing structures as parameters,” listed above, for more information see Using structures in xfNetLink .NET, and note that the Original property is not supported for interop projects.
|
4.
|
Build the Synergy assembly. This generates wrapper classes and adds them to the project. A class will be generated for each interface defined in the project and for each structure. |
|
5.
|
In the calling assembly, |
- reference the Synergy Interop assembly.
- import the namespace for the class that wraps the Synergy routine.
- call the class method that corresponds to the Synergy routine you wrote in step 2.
| Along with the method that corresponds to your Synergy routine, the Object Browser and IntelliSense for Visual Studio will display several methods that you shouldn’t use in your code: connect, disconnect, Equals, GetHashCode, GetType, getUserString, setCallTimeout, and setUserString. These items are for internal use by the generated classes and for compatibility with xfNetLink .NET clients. |
The following example Synergy code includes an i argument (arg1), which is not a .NET type. If this code is added to a .dbl file in an interop project, the interop project will wrap the Synergy routine in a class that maps the i argument to a .NET type (int).
import System.Collections.Generic
import System.Texts
{xfMethod(interface="InteropTest")} ;Attributing is required for interop project
subroutine MySubroutine
required out arg1 ,i ;Not a .NET type
required in arg2 ,String
proc
open(1, o, "tt:")
writes(1, arg2)
sleep 3
close(1)
arg1 = 5
return
endsubroutine
The following is a C# program that calls the Synergy routine above. The C# code imports the namespace (which for this example is InteropProjSynDll) and creates an instance of the InteropTest class (the generated wrapper class) to access the MySubroutine method:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using InteropProjSynDll; //Namespace for generated class
namespace InteropProjConsoleApp
{
class Program
{
static int arg1; //Corresponds to i parameter in Synergy routine.
static string arg2 = "A string";
static void Main(string[] args)
{
InteropTest tst = new InteropTest(); //Synergy routine (MySubroutine) called
tst.MySubroutine(ref arg1,arg2); // as method of InteropTest class wrapper
Console.WriteLine(arg1);
Console.ReadLine();
}
}
}
Using Synergy data type classes in non-Synergy assemblies
If you import Synergex.SynergyDE and add a reference to Synergy runtime libraries (see Synergy runtime and build libraries), you can use the following classes in a non-Synergy assembly to pass Synergy alpha, decimal, implied decimal, and integer data when calling a Synergy routine. You can use these classes unless structures or other non-.NET types are passed (in which case, you will need to do the mappings yourself or use a Synergy/DE interop project).
- PinAlphaDesc(size)
- PinDecimalDesc(size)
- PinImpliedDecimalDesc(size, precision)
- PinIntegerDesc(size)