In this article:

General Information

Creating Fore.NET Assemblies

Starting Fore.NET Assemblies

Starting and Displaying Fore.NET Form

Using Foresight Analytics Platform Components

Error Messages

Using External Assemblies

Linking Fore and Fore.NET

Using Fore.NET in Foresight Analytics Platform

Article number: KB000021

General Information

The article is used to introduce application developers to functionalities and features of using Fore.NET in Foresight Analytics Platform. It is also recommended to study the following:

NOTE. The development by means of the Fore.NET language, as well as the Fore language, must be performed in the test schema. Test and production repository are synchronized by means of update manager.

Creating Fore.NET Assemblies

The first and fundamental difference of Fore.NET and Fore is that Fore.NET is enclosed in the .NET assembly object, that is Fore.NET units and Fore.NET can be created and used only within Fore.NET assemblies.

Consider a simple example. Open integrated development environment from the project navigator and create a Fore.NET assembly. Two objects are created: a Fore.NET assembly itself and a Fore.NET unit "Program" with the following code:

Imports System;
Public Class StartParams

    Private m_Metabase: Prognoz.Platform.Interop.Metabase.IMetabase;
    Public Property Metabase: Prognoz.Platform.Interop.Metabase.IMetabase
        Get
        Begin
            Return m_Metabase
        End Get
        Set
        Begin
            m_Metabase := Value;
        End Set
    End Property Metabase;
End Class;

Public Class Program

    [STAThread]
    Public Shared Sub Main(Params: StartParams);
    Begin
        
    End Sub;

End Class;

This differs from the situation in Fore.

Introduce a definition:

An input point in Fore.NET is a published static method Main of the Program class of the <Identifier of the started .NET assembly> namespace.

An input point has a parameter of the StartParams type which contains a link to the current repository. This link is used instead of the MetabaseClass.Active method which is unavailable in Fore.NET as COM does not contain static method and properties. When a Fore.NET assembly is created a link to the Metabase assembly is automatically added to the list of links.

Fore.NET has several types of assemblies: EXE, DLL. EXE in its turn is divided into WindowsApplication and ConsoleApplication. The DLL type is assigned to the Fore.NET assembly by default when it is created, which enables the user to run it from the object navigator in the current process of Foresight Analytics Platform, and connect this Fore.NET assembly to other Fore.NET assemblies using links.

Starting Fore.NET Assemblies

Unlike a simple Fore assembly, a Fore.NET assembly can be started from the object navigator (context menu option: Open), input point of the assembly is called.

Like in Fore, a Fore.NET assembly can be started for debugging from the development environment. Debugging is also performed in a separate platform process. Start up speed is the same as in Fore.

Starting and Displaying Fore.NET Form

Unlike in Fore, you need to write additional code to start a newly created empty Fore.NET form.

See the following example of a created Fore.NET form:

Imports System;
Imports System.Collections.Generic;
Imports System.ComponentModel;
Imports System.Data;
Imports System.Drawing;
Imports System.Text;
Imports System.Windows.Forms;
Imports Prognoz.Platform.Forms.Net;

Namespace <Assembly_Identifier>
Public Partial Class <Form_Object_Identifier>Form: Prognoz.Platform.Forms.Net.ForeNetForm
    Public Constructor <Form Object Identifier>Form();
    Begin
        InitializeComponent;
    End Constructor;
End Class;
End Namespace;

A designer without parameters is generated for the form, where the InitializeComponent method is called. Going to the definition of this method opens another unit with the following code:

Imports System;
Imports System.Collections.Generic;
Imports System.ComponentModel;
Imports System.Data;
Imports System.Drawing;
Imports System.Text;
Imports System.Windows.Forms;
Imports Prognoz.Platform.Forms.Net;

Namespace <Assembly_Identifier>
    Public Partial Class <Form_Object_Identifier>Form: Prognoz.Platform.Forms.Net.ForeNetForm

        Private components: System.ComponentModel.IContainer = null;

        Protected Override Sub Dispose(disposing: boolean);
        Begin
            If (disposing And (components <> null)) then
                components.Dispose();
            End If;
            Inherited Dispose(disposing);
        End Sub;

        Private Sub InitializeComponent();
        Begin
            Self.components := New Container();
            Self.Text := "<Form_Name>";
            Self.Font := New System.Drawing.Font("Microsoft Sans Serif", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((204As Byte));
            Self.ResumeLayout(False);
        End Sub;
    End Class;
End Namespace;

You can see that a form with all its components is actually created in the InitializeComponent method. This gives a more clear idea of the moment when the form components are created.

This unit (<Form_Name>.Designer) is the form's design: it stores the components positioned on the form, their style and settings and so on. This unit is included into the Fore.NET assembly as well as other units and forms, but its content is generated automatically by the form designer.

When creating a Fore.NET form, two classes with the same names are defined: <Form_Object_Identifier>Form. One of them is included into the designer unit, another is in the form unit. This is actually one and the same class, this possibility is provided by the keyword Partial included into the definition of form class (for further information on partial classes see. Specification of the Fore.NET language).

The Fore.NET assemblies work as follows: the assembly itself is started and not its individual units and forms. So, to start a form, you need to create it and display in the input point of the Fore.NET assembly:

Public Shared Sub Main(Params: StartParams);
Var
    Forma: <Form_Object_Identifier>Form = New <Form_Object_Identifier> Form() = [<Form_Object_Identifier> Form];
Begin
    Forma.Metabase := Params.Metabase;
    Forma.Show(); // or Forma.ShowDialog();
End Sub;

This code creates a form object, then fills in the Metabase property for this object and displays it on the screen. Thus, the Metabase property of the ForeNetForm basic class is used within the form code instead of MetabaseClass.Active.

Single .NET assembly units may contain several implementations of entry points; the point which will be executed on .NET assembly startup is specified in assembly parameters. Some form can also be specified as a .NET assembly startup object, in this case entry points are ignored.

Modal Forms

A .NET form can be opened modally relative to another .NET form by using the ShowDialog method. Modal forms are always shown in front of their parent forms. On working with a modal form consider the following: on closing a modal form its resources are not deleted. The form can be reopened by calling the ShowDialog method. To delete modal form resources, force call the Dispose method or use the Using operator on initializing the modal form:

Public Partial Class TESTForm: Prognoz.Platform.Forms.Net.ForeNetForm
    Public Constructor TESTForm();
    Begin
        InitializeComponent();
    End Constructor;

    about: ForeNetForm;

    Public Sub ShowModalForm();
    Begin
        about := New CustomDialogForm();
        about.ShowDialog();
    End Sub;
    
    Public Sub ShowModalForm1();
    Begin
        Using about := New CustomDialogForm() Do
            about.ShowDialog();
        End Using;
    End Sub;
    
    Public Sub ShowModalForm2();
    Begin
        about := New CustomDialogForm();
        about.ShowDialog();
        about.Dispose();
    End Sub;
    
    Public Sub ReuseModalForm();
    Begin
        If (about <> NullAnd (Not about.IsDisposed) Then
            about.ShowDialog();
        End If;
    End Sub;

End Class;

The ShowModalForm, ShowModalForm1 and ShowModalForm2 methods open a modal window. If the window is opened by calling the ShowModalForm method, all resources remain in the computer memory after closing the window. The window can be reopened by calling the ReuseModalForm method. If the window is opened by calling the ShowModalForm1 or ShowModalForm2 methods, all resources are freed after closing the window.

Using Foresight Analytics Platform Components

The Fore.Net enables to use standard .NET components (everything included into the System.Windows.Forms namespace). The Fore.NET enables to use components used in the Fore. To find the, open the Data Access and Common Controls tabs in the Components Panel window. These components are defined in the system assembly Forms.Net. You can work as in Fore, though there are some features.

Consider the RdsDictionaryBoxNet component as an example. The following properties are defined in this component: Columns, CanElementLevelUp, CanElementDown, CanElementUp, FocusedElement, Source, UiSource, CtrlBox. All properties except UiSource and CtrlBox are used in the standard Fore component RdsDictionaryBox. The events match as well. let us consider the new properties:

Error Messages

Errors (Exceptions) in the Fore.NET can be divided into two types:

Object reference is not set to an object instance.
Error class: NullReferenceException
___________________________________
Calls stack:
  in OBJ18283.Program.kuku() in OBJ18284:row 32
  in OBJ18283.OBJ18762Form.test() in OBJ18761:row 23

An error in the HRESULTE_FAIL format is returned as the result of calling a COM component

If you have received this error text you should add a Defect with an example.

Using External Assemblies

Fore.NET assemblies can be used to store external .NET assemblies. For example, ready-made classes and components written in C# (or another .NET-compatible language) can be copied into a Fore.NET assembly, and then you can use this assembly through a link in other Fore.NET assemblies.

Use the IForeNetAssembly.LoadExternal(FileName: String) method to load an external assembly into the Fore.NET Assembly object of the repository:

Sub Test;
Var Asm: IForeNETAssembly; //type for net-assembly, defined in system assembly ForeNet
Begin
    Asm := MetabaseClass.Active.ItemById(<Identifier_Of_Created_NET-assembly>).Edit As IForeNETAssembly;
    Asm.IsExternal := True;
    Asm.LoadExternal(<Path_To_External_Assembly>);
    If Asm.AssemblyTarget <> 1 Then
        Asm.AssemblyTarget := 1// set assembly type dll
    End If;
    (Asm As IMetabaseObject).Save;
End Sub Test;

Linking Fore and Fore.NET

To use types defined in a Fore.NET assembly (external or standard), you need to connect the Fore.NET assembly using a reference and use the following interfaces and types:

ForeNETAssemblyClass, IForeNetAssembly, IForeNetAssemblyRuntime, IForeNetForm, IForeNetRuntimeType and so on.

For example, there is a class written in Fore.NET and saved in a .NET assembly:

Imports System;
Imports System.Windows.Forms;

Public Class Foo
    Public Sub Test();
    Begin
        MessageBox.Show("Fore.NET method");
    End Sub;
End Class;

Consider an example of calling the Test method from Fore:

Sub Button1OnClick(Sender: Object; Args: IMouseEventArgs);
Var run: IForeNETRuntime;
    asm: IForeNETRuntimeAssembly;
    typeFoo: IForeNETRuntimeType;
    obj: IForeNETRuntimeObjectInstance;
    res: Variant;
Begin
    run := ForeNETAssemblyClass.Runtime; //obtain Runtime, where net code is to be executed
    asm := run.Assembly(MetabaseClass.Active.ItemById("<NET-assembly_Identifier>").Bind As IForeNETAssembly); // obtain compiled NET assembly
    typeFoo := asm.Type("<NET assembly_Identifier>.Foo"); //Obtain class Foo
    obj := typeFoo.CreateInstance; //Create object of Foo class
    res := typeFoo.InvokeMethod("Test", obj, New Variant[0]); //call method &nbsp; of &nbsp; this class
End Sub Button1OnClick;

To use the types defined in Fore units and forms in Fore.NET, connect the Fore assembly and use the following interfaces and types:

IForeClass, IForeObject, IForeAssembly, IForeSub and so on.

For example, there is a class and method written in the Fore language:

Public Class Foo: Object
    Public Constructor CreateEx(X: Integer; Y: Integer);
    Begin
        
    End Constructor CreateEx;
    
    Public Sub Test;
    Begin
        WinApplication.InformationBox("Fore method");
    End Sub Test;
    
    Public Sub TestWithParams(X: Integer; Y: Integer);
    Begin
        WinApplication.InformationBox("Fore method with parameters");
    End Sub TestWithParams;
End Class Foo;

Consider an example of calling two methods via Fore.NET:

Imports System;
Imports Prognoz.Platform.Interop.Metabase;
Imports Prognoz.Platform.Interop.Fore;

Public Class Program
    //Calling Test procedure
    Private Shared Sub InvokeMethod(mb: IMetabase);
    Var
        svc: IForeServices;
        rnt: IForeRuntime;
        assm: IForeAssembly;
        ifs: IForeSub;
        ifc: IForeClass;
        ifo: IForeObject;
        result: object;
    Begin
        svc := Mb As IForeServices; //Obtain object for work with Fore
        rnt := svc.GetRuntime(); //Obtain Runtime, in which Fore methods will be executed 
        rnt.LoadAssembly("<Fore_Unit_Identifier>"); //Load Fore unit
        assm := rnt.BindToAssembly("<Fore_unit_identifier>"); //Obtain  compiled assembly
        ifc := assm.BindToClass("Foo "); //Obtain Fore class
        ifo := ifc.CreateObject(); //Create object class Foo
        ifs := ifc.BindToMethod("Test"); //Get method of this class
        ifs.Self := ifo; //set object
        ifs.Invoke(); //Call method Fore
    End Sub;
    //Calling TestWithParams function with passing values of two parameters
    Private Shared Sub InvokeMethodWithParams(MB: IMetabase; x: integer; y: integer);
    Var
        svc: IForeServices;
        rnt: IForeRuntime;
        assm: IForeAssembly;
        ifconst, ifs: IForeSub;
        ifc: IForeClass;
        ifo: IForeObject;
        result: object;
    Begin
        svc := Mb As IForeServices; //Obtain object for work with Fore
        rnt := svc.GetRuntime(); //Obtain Runtime, in which Fore methods will be executed 
        rnt.LoadAssembly("<Fore_Unit_Identifier>"); //Load Fore unit
        assm := rnt.BindToAssembly("<Fore_unit_identifier>"); //Obtain  compiled assembly
        ifc := assm.BindToClass("Foo "); //Obtain Fore class
        ifo := ifc.CreateObject(); //Create object class Foo
        //Designer
        ifconst := ifc.BindToMethod("CreateEx");
        ifconst.Self := ifo;
        ifsconst.Params.Item(0).Value := -1; //Specify the first parameter
        ifsconst.Params.Item(1).Value := -1; //Specify the second parameter
        ifconst.Invoke();
        //Method
        ifs := ifc.BindToMethod("TestWithParams"); //Obtain method of this class
        ifs.Params.Item(0).Value := x; //Specify the first parameter
        ifs.Params.Item(1).Value := y; //Specify the second parameter
        ifs.Self := ifo; //Specify object
        ifs.Invoke(); //Call method Fore
        result := ifs.ResultValue; //Obtain execution result
    End Sub;

    [STAThread]
    Public Shared Sub Main(Params: StartParams);
    Begin
        InvokeMethod(Params.Metabase);
        InvokeMethodWithParams(Params.Metabase, 1100);
    End Sub;
End Class;

There is no direct access (early binding) between Fore and Fore.NET. Thus, you cannot connect Fore and Fore.NET assemblies to each other using a reference and use types defined in these assemblies on the compilation stage.

See also:

Developers Knowledge Base | Integrated Development Environment | Components of .NET Form Designer | Early and Late Bindong