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:

1. Reference the assembly for the Synergy routine. See Synergy runtime and build libraries.
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,

1. Reference the assembly for the Synergy routine. See Synergy runtime and build libraries.
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:

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:
3. Set project properties as necessary. See Synergy/DE project properties and Interop page of Visual Studio project properties (Synergy .NET).
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,

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).