В этой статье:

Общие сведения

Создание Fore.NET-сборок

Запуск Fore.NET-сборок

Запуск и отображение Fore.NET-формы

Использование компонентов продукта «Форсайт. Аналитическая платформа»

Сообщения об ошибках

Использование внешних сборок

Связь Fore и Fore.NET

Использование Fore.NET в продукте «Форсайт. Аналитическая платформа»

Номер статьи: KB000021

Общие сведения

Данная статья предназначена для ознакомления прикладных разработчиков с функциональными особенностями использования Fore.NET в «Форсайт. Аналитическая платформа». Также рекомендуется изучить документы:

Примечание. Разработка с использованием языка Fore.NET, как и при использовании Fore, должна производиться на тестовой схеме. Для синхронизации тестового и промышленного репозитория предназначен менеджер обновлений.

Создание Fore.NET-сборок

Первое и принципиальное отличие Fore.NET от Fore заключается в том, что Fore.NET заключён в объект «.NET сборка», то есть Fore.NET-модули и Fore.NET-формы можно создавать и использовать только внутри Fore.NET-сборок.

Рассмотрим простой пример. Откроем интегрированную среду разработки и из навигатора проекта создадим Fore.NET-сборку. В результате будет создано 2 объекта: непосредственно Fore.NET-сборка и Fore.NET-модуль «Program» со следующим кодом:

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;

Это отличается от того, что было в Fore.

Введём определение:

Точка входа в программу на языке Fore.NET - это опубликованный статический метод «Main» класса «Program» пространства имён <Идентификатор запускаемой .NET сборки>.

Точка входа имеет параметр типа StartParams, который содержит в себе ссылку на текущий репозиторий. Данная ссылка заменяет метод MetabaseClass.Active, который в Fore.NET недоступен из-за отсутствия в COM статических методов и свойств. Нужно отметить, что при создании Fore.NET-сборки в список ссылок автоматически добавляется ссылка на сборку «Metabase».

В Fore.NET есть несколько типов сборок: EXE, DLL. EXE в свою очередь разделяется на WindowsApplication и ConsoleApplication. По умолчанию Fore.NET-сборке при создании устанавливается тип DLL, что позволяет запускать её из навигатора объектов в текущем процессе «Форсайт. Аналитическая платформа», а также подключать Fore.NET-сборку по ссылке к другим Fore.NET-сборкам.

Запуск Fore.NET-сборок

В отличие от обычной Fore-сборки сборку Fore.NET можно запустить из навигатора объектов (команда контекстного меню «Открыть»), при этом вызывается её точка входа.

Как и в Fore, Fore.NET-сборку можно запустить на отладку из среды разработки. Отладка так же осуществляется в отдельном процессе платформы. Скорость запуска аналогична скорости в Fore.

Запуск и отображение Fore.NET-формы

В отличие от Fore для запуска только что созданной пустой Fore.NET-формы необходимо написать дополнительный код.

Рассмотрим пример созданной Fore.NET-формы:

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 <Идентификатор_Сборки>
Public Partial Class <Идентификатор_Объекта_Формы>Form: Prognoz.Platform.Forms.Net.ForeNetForm
    Public Constructor <Идентификатор_Объекта_Формы>Form();
    Begin
        InitializeComponent;
    End Constructor;
End Class;
End Namespace;

Для формы автоматически сгенерировался конструктор без параметров, в котором происходит вызов метода InitializeComponent. Если перейти к определению данного метода, то откроется другой модуль со следующим кодом:

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 <Идентификатор_Сборки>
    Public Partial Class <Идентификатор_Объекта_Формы>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 := "<Наименование_Формы>";
            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;

Нетрудно видеть, что в методе InitializeComponent происходит непосредственное создание формы со всеми её компонентами. Это даёт более чёткое представление о том, в какой момент происходит создание компонентов формы.

Данный модуль (<Наименование_Формы>.Designer) является дизайном формы: он хранит в себе размещённые на форме компоненты, их стиль, настройки и т.д. Модуль входит в Fore.NET-сборку точно также как и другие модули и формы, только его содержимое генерируется дизайнером формы автоматически.

При создании Fore.NET-формы определяются два класса с одинаковыми именами: <Идентификатор_Объекта_Формы>Form - один в модуле дизайнера, другой в модуле формы. На самом деле это один и тот же класс, подобная возможность обеспечивается ключевым словом Partial, которое стоит в определении класса формы (подробнее о частичных классах см. «Спецификация языка Fore.NET»).

Логика работы Fore.NET-сборок заключается в том, что запускается сама сборка, а не её отдельные модули или формы, поэтому чтобы запустить форму необходимо её создать и отобразить в точке входа Fore.NET-сборки:

Public Shared Sub Main(Params: StartParams);
Var
    Forma: <Идентификатор_Объекта_Формы>Form = New <Идентификатор_Объекта_Формы> Form() = [<Идентификатор_Объекта_Формы> Form];
Begin
    Forma.Metabase := Params.Metabase;
    Forma.Show(); // либо Forma.ShowDialog();
End Sub;

Данный код создаёт объект формы, затем заполняет для него свойство Metabase и отображает на экране. Таким образом, внутри кода формы вместо MetabaseClass.Active будет использоваться свойство Metabase базового класса ForeNetForm.

Отдельные модули .NET-сборки могут содержать несколько реализаций точек входа, указание той точки, которая будет выполнена при запуске .NET-сборки осуществляется в параметрах сборки. Также в качестве объекта запуска .NET-сборки может быть указана какая-либо форма, в этом случае точки входа игнорируются.

Модальные формы

Для открытия .NET-формы модально относительно другой .NET-формы используется метод ShowDialog. Модальные формы всегда отображаются поверх своих родительских форм. При работе с модальной формой необходимо учитывать следующую особенность: при закрытии модальной формы ее ресурсы не уничтожаются, форма просто скрывается. Ее можно повторно открыть заново вызвав метод ShowDialog. Для уничтожения ресурсов модальной формы необходимо принудительно вызвать метод Dispose или при инициализации модальной формы использовать оператор Using:

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;

Методы ShowModalForm, ShowModalForm1 и ShowModalForm2 открывают модальное окно. Если окно было открыто при вызове метода ShowModalForm, то после его закрытия все ресурсы окна останутся в памяти компьютера. Окно можно будет открыть заново с помощью метода ReuseModalForm. Если окно было открыто при вызове метода ShowModalForm1 или ShowModalForm2, то после его закрытия все ресурсы освобождаются.

Использование компонентов продукта «Форсайт. Аналитическая платформа»

Помимо стандартных .NET-компонентов (это всё, что находится в пространстве имён System.Windows.Forms), Fore.NET позволяет использовать компоненты, известные по Fore. Они расположены в окне «Панель компонентов» на вкладках «Data Access» и «Common Controls». Данные компоненты определены в системной сборке Forms.Net. Работа с ними аналогична Fore, но имеется ряд особенностей.

Рассмотрим на примере компонента RdsDictionaryBoxNet. В нём определены следующие свойства: Columns, CanElementLevelUp, CanElementDown, CanElementUp, FocusedElement, Source, UiSource, CtrlBox. Все свойства, кроме UiSource и CtrlBox, присущи обычному Fore-компоненту RdsDictionaryBox. Такое же соответствие и в событиях. Рассмотрим новые свойства:

Сообщения об ошибках

Ошибки (Exceptions) в Fore.NET условно можно разделить на два типа:

В экземпляре объекта не задана ссылка на объект.
Класс ошибки: NullReferenceException
___________________________________
Стек вызовов:
  в OBJ18283.Program.kuku() в OBJ18284:строка 32
  в OBJ18283.OBJ18762Form.test() в OBJ18761:строка 23

В результате вызова компонента COM возвращена ошибка в формате HRESULT E_FAIL

Если вы получили такой текст ошибки, то следует добавить Defect с примером.

Использование внешних сборок

Fore.NET-сборки можно использовать для хранения внешних .NET-сборок. К примеру, есть готовые классы/компоненты, написанные на C# (или любом другом .NET-совместимом языке) и их можно записать в Fore.NET-сборку, а затем использовать эту сборку по ссылке в других Fore.NET-сборках.

Для загрузки внешней сборки в объект репозитория «Fore.NET-сборка», необходимо использовать метод IForeNetAssembly.LoadExternal(FileName: String):

Sub Test;
Var Asm: IForeNETAssembly; //тип для net-сборки, определён в системной сборке ForeNet
Begin
    Asm := MetabaseClass.Active.ItemById(<Идентификатор_Созданной_NET-сборки>).Edit As IForeNETAssembly;
    Asm.IsExternal := True;
    Asm.LoadExternal(<Путь_К_Внешней_Сборке>);
    If Asm.AssemblyTarget <> 1 Then
        Asm.AssemblyTarget := 1// устанавливаем тип сборки dll
    End If;
    (Asm As IMetabaseObject).Save;
End Sub Test;

Связь Fore и Fore.NET

Для использования в Fore.NET типов, определённых в Fore.NET-сборке (внешней или обычной), в Fore необходимо по ссылке подключить сборку Fore.NET и использовать следующие интерфейсы и типы:

ForeNETAssemblyClass, IForeNetAssembly, IForeNetAssemblyRuntime, IForeNetForm, IForeNetRuntimeType и т.д.

Например, есть класс, написанный на Fore.NET и сохраненный, в какой-либо .NET-сборке:

Imports System;
Imports System.Windows.Forms;

Public Class Foo
    Public Sub Test();
    Begin
        MessageBox.Show("Fore.NET метод");
    End Sub;
End Class;

Рассмотрим пример вызова метода Test из Fore:

Sub Button1OnClick(Sender: Object; Args: IMouseEventArgs);
Var run: IForeNETRuntime;
    asm: IForeNETRuntimeAssembly;
    typeFoo: IForeNETRuntimeType;
    obj: IForeNETRuntimeObjectInstance;
    res: Variant;
Begin
    run := ForeNETAssemblyClass.Runtime; //Получаем Runtime, в котором будет выполняться net код
    asm := run.Assembly(MetabaseClass.Active.ItemById("<Идентификатор_NET-сборки>").Bind As IForeNETAssembly); //Получаем скомпилированную .NET-сборку
    typeFoo := asm.Type("<Идентификатор_NET-сборки>.Foo"); //Получаем класс Foo
    obj := typeFoo.CreateInstance; //Создаём объект класса Foo
    res := typeFoo.InvokeMethod("Test", obj, New Variant[0]); //Вызываем метод данного класса
End Sub Button1OnClick;

Для использования типов, определённых в Fore-модулях/формах, в Fore.NET необходимо подключить сборку Fore и использовать следующие интерфейсы и типы:

IForeClass, IForeObject, IForeAssembly, IForeSub и т.д.

Например, есть класс и метод, написанные на Fore:

Public Class Foo: Object
    Public Constructor CreateEx(X: Integer; Y: Integer);
    Begin
        
    End Constructor CreateEx;
    
    Public Sub Test;
    Begin
        WinApplication.InformationBox("Fore-метод");
    End Sub Test;
    
    Public Sub TestWithParams(X: Integer; Y: Integer);
    Begin
        WinApplication.InformationBox("Fore-метод с параметрами");
    End Sub TestWithParams;
End Class Foo;

Рассмотрим пример вызова двух методов через Fore.NET:

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

Public Class Program
    //Вызов процедуры Test
    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; //Получаем объект для работы с Fore
        rnt := svc.GetRuntime(); //Получаем Runtime, в котором будут выполняться методы Fore
        rnt.LoadAssembly("<Идентификатор_Модуля_Fore>"); //Загружаем модуль Fore
        assm := rnt.BindToAssembly("<Идентификатор_Модуля_Fore>"); //Получаем скомпилированную сборку
        ifc := assm.BindToClass("Foo"); //Получаем Fore класс
        ifo := ifc.CreateObject(); //Создаём объект класса Foo
        ifs := ifc.BindToMethod("Test"); //Получаем метод этого класса
        ifs.Self := ifo; //Указываем объект
        ifs.Invoke(); //Вызываем метод Fore
    End Sub;
    //Вызов функции TestWithParams с передачей значений двух параметров
    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; //Получаем объект для работы с Fore
        rnt := svc.GetRuntime(); //Получаем Runtime, в котором будут выполняться методы Fore
        rnt.LoadAssembly("<Идентификатор_Модуля_Fore>"); //Загружаем модуль Fore
        assm := rnt.BindToAssembly("<Идентификатор_Модуля_Fore>"); //Получаем скомпилированную сборку
        ifc := assm.BindToClass("Foo"); //Получаем Fore-класс
        ifo := ifc.CreateObject(); //Создаём объект класса Foo
        //Конструктор
        ifconst := ifc.BindToMethod("CreateEx");
        ifconst.Self := ifo;
        ifconst.Params.Item(0).Value := -1//Указываем первый параметр
        ifconst.Params.Item(1).Value := -1//Указываем второй параметр
        ifconst.Invoke();
        //Метод
        ifs := ifc.BindToMethod("TestWithParams"); //Получаем метод этого класса
        ifs.Params.Item(0).Value := x; //Указываем первый параметр
        ifs.Params.Item(1).Value := y; //Указываем второй параметр
        ifs.Self := ifo; //Указываем объект
        ifs.Invoke(); //Вызываем метод Fore
        result := ifs.ResultValue; //Получаем результат выполнения
    End Sub;

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

Возможности прямого доступа (раннего связывания) между Fore и Fore.NET нет, то есть подключать по ссылке сборки Fore и Fore.NET друг к другу и использовать типы, определённые в них, на этапе компиляции нельзя.

См. также:

База знаний разработчиков | Интегрированная среда разработки | Компоненты дизайнера форм .NET | Раннее и позднее связывание