"Use of Visibroker for Delphi" (3)

zhaozj2021-02-16  46

"Use of Visibroker for Delphi" (3)

-CORBA technology practice (1)

Yichang City Center People's Hospital Zhao Pu

Email: 3boy@sohu.com

3, array object to pass the simple data object

The previous mentioned some simple data operations, we can imagine, if the CORBA object is the same as the data object of the operation C / S structure, then CORBA is magical, don't know how to read Li Wei's distribution When you have a book of multi-storey application, do you pay attention to Li Wei's evaluation of CORBA, no matter what you have seen

Still haven't seen, I have to tell the friends who are using CORBA programming, CORBA is simpler than COM / COM , and CORBA's cross-platform feature, and the same load balance with COM / COM , it is enough to let us distribute this Technology is applied to the design of the application system, in fact, for the use of Borland's product development, no matter whether you use CORBA or COM / COM , the most core technology is Midas because

You can always see the shadow of Midas in CORBA / COM / COM , so I suggest that you are ready to learn CORBA or learn COM / COM , it is best to learn MIDAS, this article does not involve Midas, about Midas, please see Li Wei's " Delphi5.x Distributed Multi-Layer Application - Systems ".

Why do I have always written IDL from the beginning of the text editor, not Typelibrary

To write IDL, in fact, I think it is just to get some more IDL knowledge to get programmers who have just contacted CORBA. In actual development, you can use TypeLibrary to write interface rules in actual development.

Below I am briefly listing the examples written by several IDLs and the PASCAL code generated using the IDL2PAS.

1, the definition of constant

/ ** IDL writing ** /

Module mycrb {

Const long iMyconst = 1;

Interface myface {

Const long iimyconst = 2;

}

}

/ ** pascal ** /

Unit mycrb_i;

Interface

Uses corba;

Const

iMyconst: integer = 1;

myface_iimyconst = 2;

2,) constant in the interface

/ ** id1 ** /

Module mycrb {

Const long myconst = 1;

}

/ * pascal * /

Unit mycrb_i;

Interface

Const myconst: integer = 1;

3, enumerated type

/ * Id1 * /

Enum mycrbkind {a, b, c, d, ...... ..

/ * pascal * /

Mycrbkind = (A, B, C, D ... ..);

4,) structure

/ * Id1 * /

Struct myStructType {

Long x;

String y;

Boolean Z;

}

/ * pascal * /

//Xxx_i.pas

TYPE mYStructType = interface;

//Xxx_c.pas

MyStructType = Interface

Function _get_x: integer;

Function _get_y: string;

Function _get_z: bolean;

Procedure_set_x (const value: integer);

Procedure_set_y (const value: string);

Procedure_Set_z (Const Value: Boolean);

Property X: Integer Read_Get_x Write_Set_x; Property Y: String Read_Get_y Write_Set_y;

Property Z: Boolean Read_Get_z Write_Set_z;

.......

There are too many code, create a look, don't make a detailed translation in order to save the space.

Let's try the following PASCAL code for the following buds.

5, the uniform

Union UN_EXP Switch (long)

{

Case 1: long x;

Case 2: String Y;

Case 3: ST_EXP Z;

}

6, SEQUENCE (I understand as a dynamic array)

Typedef sequern unboundseq;

Typedef Sequence ShortBoundSeq

7, array

Const long arraybound = 10;

Typedef long longaray [arraybound];

8, abstract interface

Module Exp {

Interface myface {

Long OP (in string s);

}

}

9, multiple inheritance

Module M {

Interface a {

Void A1 ();

Void A2 ();

}

Interface b {

Void B1 ();

Void B2 ();

}

Interface AB: B, A {

Void AB1 ()

Void ab2 ();

}

}

10, cross-model definition

Module m1 {

Interface IF1;

Module M2 {

Interface if2 {

M1 :: if1 getif1 ();

}

Interface if1 {

M2 :: if2 getif2 ()

}

}

}

I introduced some of the definition specifications for data, but we need not only such a more abstract interface definition rule. We must apply the law to the actual development, then we use these laws, for the interface Description Language Translated I speaking directly using IDL2PAS, I don't talk about how to convert it in the following chapters. Below we practice:

Writing Interface Defines a method of returning to floating point types, entered as a short-intensive variable array object

Typedef Short ArrayType [3];

// Customize the array of length 3

Interface account {

Float InputArray (In ArrayType MyArray); / / Enter a plastic array, return type FLOAT method

}

// Service server processing XXX_IMPL.PAS

Interface

Uses

SYSUTILS,

Corba,

Account_i,

Account_c;

Type

Taccount = Class;

Taccount = Class (TinterFaceDObject, Account_i.account)

protected

// ******************

public

Constructor crete;

Function INPUTARRAY (const myarray): Single;

END;

IMPLEMENTATION

Uses ServerMain;

Constructor taccount.create;

Begin

inherited;

END;

Function Taccount. INPUTARRAY (const myarray): Single;

VAR

J: integer;

Begin

// Account_i.ArrayType refers to our custom array type in the Account_i unit for J: = 0 to 2 DO

Begin

Form1.Memo1.Lines.Add ('MyArray [ INTSTOSTR (J) '] = ' INTOSTR (MyArray [J]));

/ / Accept the array variable passed from the client and sequentially add it to the main form of MEMO

END;

Result: = random * 100; // Return a random number

END;

INITIALIZATION

Randomize;

End.

// Service server main unit

UNIT ServerMain;

Interface

Uses

Windows, Messages, Sysutils, Classes, Graphics, Controls, Forms, Dialogs, CORBA,

Account_i, Account_c, Account_s, Account_Impl, Stdctrls;

Type

TFORM1 = Class (TFORM)

Memo1: TMEMO;

Procedure formcreate (Sender: TOBJECT);

Private

{Private Declarations}

protected

{Protected Declarations}

Acct: account; // skellon object

Procedure Initcorba;

public

{public declarations}

END;

VAR

FORM1: TFORM1;

IMPLEMENTATION

{$ R * .dfm}

Procedure TFORM1.INITCORBA;

Begin

Corbainitialize;

// Add Corba Server Code Here

Acct: = Taccountskeleton.create ('Array Server', Taccount.create);

Boa.objisready (ACCT AS _OBJECT);

END;

Procedure TFORM1.FormCreate (Sender: TOBJECT);

Begin

Initcorba;

Memo1.Lines.Add ('Account Object Created ...');

Memo1.Lines.Add ('Server Is Ready');

END;

End.

/ / Client program

Unit clientmain;

Interface

Uses

Windows, Messages, Sysutils, Classes, Graphics, Controls, Forms, Dialogs,

Corba, stdctrls, account_i, account_c;

Type

TFORM1 = Class (TFORM)

Button1: tbutton;

Label1: TLABEL;

Procedure formcreate (Sender: TOBJECT);

Procedure Button1Click (Sender: TOBJECT);

Private

{Private Declarations}

protected

{Protected Declarations}

Acct: Account;

MyArray: ArrayType;

Procedure Initcorba;

public

{public declarations}

END;

VAR

FORM1: TFORM1;

IMPLEMENTATION

{$ R * .dfm}

Procedure TFORM1.INITCORBA;

Begincorbainitialize;

Acct: = taccounthelper.bind;

END;

Procedure TFORM1.FormCreate (Sender: TOBJECT);

VAR

J: integer;

Begin

Initcorba;

For j: = 0 to 2 do

MyArray [J]: = (J 1) * 100;

END;

Procedure TFORM1.BUTTON1CLICK (Sender: TOBJECT);

Begin

Label1.caption: = formatfloat ('INPUTARRAY = $ #, ## 0.00', acct.inputArray (MyArray);

END;

End.

The above program instance is very simple, I will not explain, let's take a look at an instance of a data access.

// idl

Interface Employee {

Any getEmployeesbyName (in string name);

}

Interface method declaration unit

//Xxx_impl.pas

Interface

Uses

SYSUTILS,

Corba,

EMPLOYEE_I,

EMPLOYEE_C;

Type

Temployee = Class;

Temployee = Class (TinterFaceDObject, Employee_i.employee)

public

Constructor crete;

Function geTemployeesbyName (const name): Any;

END;

IMPLEMENTATION

Uses DMemPloyee, Dmpooler, Provider, DSINTF, ServerMain

Constructor temploye.create;

Begin

inherited;

END;

Function Temployee.GeTemPloyeesbyName (const name: ansistring): Any;

VAR

DM: TDMEMPLOY;

RECSOUT: Integer;

Options: TgetRecordOptions;

Begin

Options: = [grmetadata, grreset]; // Must Specify Meta Data

DM: = modulepooler.getModule As TdMemploy; // Get Instance of DataModule from pool

Try

DM.QRYEMPLOYE.CLOSE;

DM.QRYEMPLOYEE.PARAMBYNAME ('Name'). Asstring: = name '%';

// Display the number of connected servers

INC (Form1.hitcount);

Form1.label1.caption: = format ('hit count =% d', [form1.hitcount]);

DM.QRYEMPLOYE.OPEN

Result: = dm.proemployee.getRecords (-1, recsout, byte (options));

DM.QRYEMPLOYE.CLOSE;

Finally

ModulePooler.FreeModule (DM); // Return Instance of DataModule To Pool

END;

END;

INITIALIZATION

// put the TDMemPloy object into the shared pool

ModulePooler.ModuleClass: = TDMEMPLOY;

End.

// Mean of shared pool

Mainly describes how to provide a multi-customer access data to provide Unit Dmpooler;

Interface

Uses Sysutils, Classes, Forms, Syncobjs, Windows

Type

// This unit is used to provide a separate DataModule object for each customer, equivalent to the same functionality as we choose to create in the previous CORBA DATAMODULE.

TDataModuleClass = Class of TdataModule; // Defining class

TPOOLEDMODULE = Record // Declaration Record Type

Module: tdataModule; // Inherited standard TDATAMODULE

Inuse: boolean; / / indicate whether TDATAMODULE is inherited above

END;

TMODULEPOOLER = Class

Private

FCsect: tcriticalsection; // Allow threads to change FModules yourself

FmoduleClass: TDataModuleclass; // Medium TDATAModule in shared pool

FModules: array of tpooledModule; / / Define a dynamic object record array

FSEMAPHORE: THANDLE; / / Limit the user rules for simultaneous use

public

Property ModuleClass: TDataModuleclass Read FmoduleClass Write Fmoduleclass;

Constructor crete;

DESTRUCTOR DESTROY; OVERRIDE;

Function getModule: TDATAModule;

Procedure FreeModule (DATAModule: tdataModule);

END;

Const

Poolsize = 5;

VAR

ModulePooler: TModulePooler = NIL;

IMPLEMENTATION

Uses dialogs;

{TMODULEPOOL}

Constructor TModulePooler.create;

Begin

Ismultithread: = true;

FCsect: = TcriticalSection.create;

FSemaphore: = CreateSemaphore (NIL, PoolSize, Poolsize, NIL);

END;

DESTRUCTOR TMODULEPOOLER.DESTROY;

Begin

Fcsect.free;

CloseHandle (FSEMAPHORE);

END;

Procedure TModulePooler.FreeModule (DATAModule: TDataModule);

VAR

I: integer;

Begin

Fcsect.enter;

Try

For i: = 0 to Length (FModules) - 1 DO

IF fmodules [i] .Module = DATAMODULE THEN

Fmodules [i] .inuse: = false;

ReleaseSemaphore (FSemaphore, 1, NIL);

Finally

Fcsect.Leave;

END;

END;

Function TModulePooler.getModule: TDATAMODULE;

VAR

I: integer;

Begin

Result: = NIL;

IF WaitforsingleObject (fsemaphore, 5000) = Wait_timeout then

Raise Exception.create ('Server Too Bussy');

FCsect.Enter; Try

if Length (FModules) = 0 THEN

Begin

SETLENGTH (FModules, poolsize);

For i: = 0 to poolsize - 1 do

Begin

Fmodules [i] .inuse: = false;

FModules [i] .Module: = fmoduleclass.create (Application);

END;

END;

For i: = 0 to Length (FModules) - 1 DO

IF not fModules [i] .inuse kil

Begin

Fmodules [i] .inuse: = true;

Result: = fmodules [i] .Module

Break;

END;

Finally

Fcsect.Leave;

END;

/ / Check if it is connected

IF not assigned (result) THEN

Raise Exception.create ('Pool Is Out of Capacity');

END;

INITIALIZATION

ModulePooler: = TModulePooler.create;

Finalization

ModulePooler.Free;

End.

// This unit is a universal method unit, of course, you can also use other methods to complete such a function.

// DataModule unit

Unit DMemPloyee;

Interface

Uses

Windows, Messages, Sysutils, Classes, Graphics, Controls, Forms, Dialogs,

DB, DBTABLES, Provider;

Type

TDMEMPLOY = Class (TDATAModule)

SESSION1: TSESSION;

Employeedatabase: TDATABASE;

QRYEMPLOYEE: TQuery;

ProEmployee: TDataSetProvider;

Private

{Private Declarations}

public

{Public declarations}

END;

VAR

DMemploy: TDMEMPLOY;

IMPLEMENTATION

{$ R * .dfm}

End.

// server main unit

UNIT ServerMain;

Interface

Uses

Windows, Messages, Sysutils, Classes, Graphics, Controls, Forms, Dialogs,

Grids, DBGRIDS, DB, DBTABLES, STDCTRLS, CORBA, EMPLOYE_I, EMPLOYEE_C,

Employee_s, EmployeE_Impl;

Type

TFORM1 = Class (TFORM)

Label1: TLABEL;

Procedure formcreate (Sender: TOBJECT);

Private

{Private Declarations}

Procedure Corbainit;

public

{Public declarations}

Hitcount: integer;

END;

VAR

FORM1: TFORM1;

MYDBSERVER: Employee;

IMPLEMENTATION

{$ R * .dfm}

Procedure TFORM1.CORBAINIT;

Begin

Corbainitialize;

Mydbserver: = Temployeeskeleton.create ('MyServer', Temploye.create); Boa.objisready (MyDBServer As _Object);

END;

Procedure TFORM1.FormCreate (Sender: TOBJECT);

Begin

Corbainit;

END;

End.

/ / Client program

Interface

Uses

Windows, Messages, Sysutils, Classes, Graphics, Controls, Forms, Dialogs,

Stdctrls, Grids, Corba, Employee_i, Employee_c, DB, DBCLIENT, EXTCTRLS,

DBCTRLS, DBGRIDS;

Type

TFORM1 = Class (TFORM)

Button1: tbutton;

DBGRID1: TDBGRID;

CDSemPloyee: TclientDataSet;

DataSource1: TDataSource;

Edtemployeename: tedit;

Memo1: TMEMO;

Label1: TLABEL;

Procedure formcreate (Sender: TOBJECT);

Procedure Button1Click (Sender: TOBJECT);

Private

{Private Declarations}

myemployee: Employee;

public

{Public declarations}

END;

VAR

FORM1: TFORM1;

IMPLEMENTATION

{$ R * .dfm}

Procedure TFORM1.FormCreate (Sender: TOBJECT);

Begin

MyEmployee: = TemployeeHelper.bind;

END;

Procedure TFORM1.BUTTON1CLICK (Sender: TOBJECT);

Begin

CDSemPloyee.Data: = myemployee.getemployeesbyname (edTemPloyeename.Text);

CDSemPloye.Open;

END;

End.

I think everyone should understand the above program. If you don't understand it, don't matter, the next time I will launch a series of problems around this example and compare the same time in COM / MIDAS, in order to let everyone leave a thinking I haven't said it here. Still the next time next time

My philosophy: "Whether it is CORBA or COM vast or EJB, etc.

转载请注明原文地址:https://www.9cbs.com/read-27063.html

New Post(0)