COM设计与实现范例
原创作者: 小王志东,王健。
创作日期:2002年4月5日星期五
组件对象模型是一种跨平台技术,是现代面向对象分析与设计的技术实现手段之一,就现实系统应用来看,COM技术有着很强的实用价值。
OOA -> OOD -> OOP 用纯面向对象技术分析设计实现系统
现就给出一个简单的范例来展示其魅力。系统描述:本系统是一个多用户登录管理系统。要求用户通过输入用户编号和密码登录系统,如登录成功则显示成功消息,否则显示错误消息。系统分析:类的抽取,根据关键词抽取出用户类,根据用户类衍生出用户管理员类。
COM接口定义
unit UnionComs_TLB;
// ************************************************************************ //
// WARNING
// -------
// The types declared in this file were generated from data read from a
// Type Library. If this type library is explicitly or indirectly (via
// another type library referring to this type library) re-imported, or the
// 'Refresh' command of the Type Library Editor activated while editing the
// Type Library, the contents of this file will be regenerated and all
// manual modifications will be lost.
// ************************************************************************ //
// PASTLWTR : $Revision: 1.130 $
// File generated on 2002-4-5 11:34:29 from Type Library described below.
// ************************************************************************ //
// Type Lib: D:\stevenbob\exmines\UnionComGroup\Coms\UnionComs.tlb (1)
// LIBID: {A5265797-1AE4-4465-B5BA-67CB3E5F615E}
// LCID: 0
// Helpfile:
// DepndLst:
// (1) v2.0 stdole, (C:\WINNT\System32\stdole2.tlb)
// (2) v4.0 StdVCL, (C:\WINNT\System32\STDVCL40.DLL)
// ************************************************************************ //
{$TYPEDADDRESS OFF} // Unit must be compiled without type-checked pointers.
{$WARN SYMBOL_PLATFORM OFF}
{$WRITEABLECONST ON}
interface
uses ActiveX, Classes, Graphics, StdVCL, Variants, Windows;
// *********************************************************************//
// GUIDS declared in the TypeLibrary. Following prefixes are used:
// Type Libraries : LIBID_xxxx
// CoClasses : CLASS_xxxx
// DISPInterfaces : DIID_xxxx
// Non-DISP interfaces: IID_xxxx
// *********************************************************************//
const
// TypeLibrary Major and minor versions
UnionComsMajorVersion = 1;
UnionComsMinorVersion = 0;
LIBID_UnionComs: TGUID = '{A5265797-1AE4-4465-B5BA-67CB3E5F615E}';
IID_IUserGroup: TGUID = '{D168EB08-8C53-41F7-9B4C-B1EA0120C1DA}';
CLASS_UserGroup: TGUID = '{91648D17-4920-48A1-BC8E-94E6A70AA31B}';
IID_IUser: TGUID = '{8CC77A6A-0D6B-4646-8DD2-D3E3853C46B7}';
CLASS_User: TGUID = '{EA6025AF-6F8C-4201-8DF4-BE5DB86D061A}';
type
// *********************************************************************//
// Forward declaration of types defined in TypeLibrary
// *********************************************************************//
IUserGroup = interface;
IUser = interface;
IUserDisp = dispinterface;
// *********************************************************************//
// Declaration of CoClasses defined in Type Library
// (NOTE: Here we map each CoClass to its Default Interface)
// *********************************************************************//
UserGroup = IUserGroup;
User = IUser;
// *********************************************************************//
// Interface: IUserGroup
// Flags: (4096) Dispatchable
// GUID: {D168EB08-8C53-41F7-9B4C-B1EA0120C1DA}
// *********************************************************************//
IUserGroup = interface(IDispatch)
['{D168EB08-8C53-41F7-9B4C-B1EA0120C1DA}']
function CreateUser(ID: Integer; const UserName: WideString; const UserPwd: WideString;
out ppUser: User): HResult; stdcall;
function GetCount(out plCount: Integer): HResult; stdcall;
end;
// *********************************************************************//
// Interface: IUser
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {8CC77A6A-0D6B-4646-8DD2-D3E3853C46B7}
// *********************************************************************//
IUser = interface(IDispatch)
['{8CC77A6A-0D6B-4646-8DD2-D3E3853C46B7}']
function Get_Name: WideString; safecall;
procedure Set_Name(const Value: WideString); safecall;
function Get_ID: Integer; safecall;
procedure Set_ID(Value: Integer); safecall;
function Get_Password: WideString; safecall;
function ChangePassword(const OldPwd: WideString; const NewPwd: WideString;
const CfmPwd: WideString): Integer; safecall;
property Name: WideString read Get_Name write Set_Name;
property ID: Integer read Get_ID write Set_ID;
property Password: WideString read Get_Password;
end;
// *********************************************************************//
// DispIntf: IUserDisp
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {8CC77A6A-0D6B-4646-8DD2-D3E3853C46B7}
// *********************************************************************//
IUserDisp = dispinterface
['{8CC77A6A-0D6B-4646-8DD2-D3E3853C46B7}']
property Name: WideString dispid 2;
property ID: Integer dispid 3;
property Password: WideString readonly dispid 4;
function ChangePassword(const OldPwd: WideString; const NewPwd: WideString;
const CfmPwd: WideString): Integer; dispid 5;
end;
// *********************************************************************//
// The Class CoUserGroup provides a Create and CreateRemote method to
// create instances of the default interface IUserGroup exposed by
// the CoClass UserGroup. The functions are intended to be used by
// clients wishing to automate the CoClass objects exposed by the
// server of this typelibrary.
// *********************************************************************//
CoUserGroup = class
class function Create: IUserGroup;
class function CreateRemote(const MachineName: string): IUserGroup;
end;
// *********************************************************************//
// The Class CoUser provides a Create and CreateRemote method to
// create instances of the default interface IUser exposed by
// the CoClass User. The functions are intended to be used by
// clients wishing to automate the CoClass objects exposed by the
// server of this typelibrary.
// *********************************************************************//
CoUser = class
class function Create: IUser;
class function CreateRemote(const MachineName: string): IUser;
end;
implementation
uses ComObj;
class function CoUserGroup.Create: IUserGroup;
begin
Result := CreateComObject(CLASS_UserGroup) as IUserGroup;
end;
class function CoUserGroup.CreateRemote(const MachineName: string): IUserGroup;
begin
Result := CreateRemoteComObject(MachineName, CLASS_UserGroup) as IUserGroup;
end;
class function CoUser.Create: IUser;
begin
Result := CreateComObject(CLASS_User) as IUser;
end;
class function CoUser.CreateRemote(const MachineName: string): IUser;
begin
Result := CreateRemoteComObject(MachineName, CLASS_User) as IUser;
end;
end.
COM接口的实现
unit uUnionComsImpl;
{$WARN SYMBOL_PLATFORM OFF}
interface
uses
// ActiveX, Mtsobj, Mtx, ComObj, UnionComs_TLB, StdVcl;
Windows, ActiveX, Classes, ComObj, UnionComs_TLB, StdVcl;
type
TUserRec = record
Intf: IUser;
bUsed: Boolean;
end;
TUserGroup = class(TAutoObject, IUserGroup)
private
FUserArray: array of TUserRec;
protected
function CreateUser(ID: Integer; const UserName, UserPwd: WideString;
out ppUser: User): HResult; stdcall;
function GetCount(out plCount: Integer): HResult; stdcall;
public
destructor Destroy; override;
procedure Initialize; override;
end;
implementation
uses ComServ;
function TUserGroup.CreateUser(ID: Integer; const UserName,
UserPwd: WideString; out ppUser: User): HResult;
var
AIntf: IUser;
begin
SetLength(FUserArray, Length(FUserArray) + 1);
AIntf := CoUser.Create as IUser;
FUserArray[Length(FUserArray) - 1].Intf := AIntf;
FUserArray[Length(FUserArray) - 1].bUsed := True;
AIntf.Name := UserName;
AIntf.ID := ID;
ppUser := FUserArray[Length(FUserArray) - 1].Intf;
end;
destructor TUserGroup.Destroy;
var
i: Integer;
begin
for i := Low(FUserArray) to High(FUserArray) do
begin
FUserArray[i].Intf := nil;
FUserArray[i].bUsed := False;
end;
SetLength(FUserArray, 0);
inherited Destroy;
end;
function TUserGroup.GetCount(out plCount: Integer): HResult;
begin
plCount := Length(FUserArray);
end;
procedure TUserGroup.Initialize;
begin
inherited;
end;
initialization
TAutoObjectFactory.Create(ComServer, TUserGroup, Class_UserGroup,
ciMultiInstance, tmApartment);
end.
客户端程序的实现
Create User Button 的代码实现
procedure TForm1.Button1Click(Sender: TObject);
var
AUserGroup: IUserGroup;
AUser: IUser;
begin
AUser := nil;
AUserGroup := CoUserGroup.Create;
AUserGroup.CreateUser(10, 'WZD', '912', AUser);
ShowMessage(AUser.Name);
Auser.ChangePassword('', '912', '912');
ShowMessage(AUser.Password);
end;