繁体   English   中英

COM对象和DLL的不同版本

[英]COM Object and different versions of DLL

我是DLL对象的新手,我到处搜索并且找不到正确的答案。 我对Microsoft RMS所做的工作很少,它会通过IDispach参数从我的dll中自动调用函数Process,并传递当前会话详细信息。

我正在使用QSRules.dll(组件>导入>组件>类型库...添加到项目)中的界面。 它使用所有引用等创建TLB文件。

procedure TRefreshScreenRefreshScreen.Process(const Session: IDispatch);
begin

  CodeSite.Send( csmLevel1, '(Session as SessionClass).Cashier.Name', (Session as SessionClass).Cashier.Name );
  CodeSite.Send( csmLevel1, '(Session as SessionClass).Cashier.Number', (Session as SessionClass).Cashier.Number );

end;

这与软件2.01版完美配合,但是当尝试在2.02版上使用相同功能时,它崩溃并显示“不支持接口”。 QSRules.dll已更新版本,所有类的GUID均不同。

我尝试了休闲代码:

procedure TRefreshScreenRefreshScreen.Process(const Session: IDispatch);
begin

  if Supports(Session, QSRules_TLB_2_0_0_151.SessionClass) then
    Begin
      CodeSite.Send( csmLevel1, '(Session as SessionClass).Cashier.Name', (Session as QSRules_TLB_2_0_0_151.SessionClass).Cashier.Name );
      CodeSite.Send( csmLevel1, '(Session as SessionClass).Cashier.Number', (Session as QSRules_TLB_2_0_0_151.SessionClass).Cashier.Number );
    end else

  if Supports(Session, QSRules_TLB_2_0_0_105.SessionClass) then
    Begin
      CodeSite.Send( csmLevel1, '(Session as SessionClass).Cashier.Name', (Session as QSRules_TLB_2_0_0_105.SessionClass).Cashier.Name );
      CodeSite.Send( csmLevel1, '(Session as SessionClass).Cashier.Number', (Session as QSRules_TLB_2_0_0_151.SessionClass).Cashier.Number );
    end

end;

有4个或5个不同版本的dll,它们的GUID不同,但98%的代码是相同的。 这样做将不必要地增加代码。

有什么办法可以缩短它吗?

我也试过

procedure TRefreshScreenRefreshScreen.Process(const Session: IDispatch);
var
 _Session: SessionClass;
begin

  if Supports(Session, QSRules_TLB_2_0_0_151.SessionClass) then
    _Session = (Session as QSRules_TLB_2_0_0_151.SessionClass)

  else if Supports(Session, QSRules_TLB_2_0_0_105.SessionClass) then
      _Session = (Session as QSRules_TLB_2_0_0_105.SessionClass);

  with _Session do
  Begin
      CodeSite.Send( csmLevel1, '_Session.Cashier.Name', Cashier.Name );
      CodeSite.Send( csmLevel1, '_Session..Cashier.Number', Cashier.Number );
  End;

end;

但这不起作用,因为只能从单元中分配变量类型。

任何帮助表示赞赏!

您说接口在不同版本中具有不同的指导。 只要新的接口是从旧的接口派生的,那是完全可以的。 真的是这样吗? 如果这样做,则可以通过将Session对象强制转换为实际定义Cashier成员的任何接口来简化代码。 除非接口不是彼此派生的,否则无需将其强制转换为每个单独的接口类型。 您可以显示实际的接口声明吗?

v2.0.0.105起的收银员声明

_Cashier = interface(IDispatch)
    ['{AA84B4FB-AA41-4423-A763-59D0723ED52B}']
    function Get_Session: _SessionClass; safecall;
    function Get_CashDrawer: _CashDrawer; safecall;
    function Get_OverShortLimitType: overshortlimitEnum; safecall;
    function Get_MaxOverShortAmount: Currency; safecall;
    function Get_MaxOverShortPercent: Double; safecall;
    function Get_SecurityLevel: Smallint; safecall;
    function Get_HasPrivilege(var CashierPrivilege: cashierprivilegesEnum): WordBool; safecall;
    function Get_FailedLogOnAttempts: Integer; safecall;
    function Get_EmailAddress: WideString; safecall;
    function Get_Messages: _CashierMessages; safecall;
    function Get_UnreadMessageCount: Integer; safecall;
    function Get_Name: WideString; safecall;
    function Get_FirstName: WideString; safecall;
    function Get_LastName: WideString; safecall;
    function Get_ReturnLimit: Currency; safecall;
    function Get_FloorLimit: Currency; safecall;
    function Get_ID: Integer; safecall;
    function Get_CashDrawerNumber: Smallint; safecall;
    function Get_Loaded: WordBool; safecall;
    function Get_Number: WideString; safecall;
    property Session: _SessionClass read Get_Session;
    property CashDrawer: _CashDrawer read Get_CashDrawer;
    property OverShortLimitType: overshortlimitEnum read Get_OverShortLimitType;
    property MaxOverShortAmount: Currency read Get_MaxOverShortAmount;
    property MaxOverShortPercent: Double read Get_MaxOverShortPercent;
    property SecurityLevel: Smallint read Get_SecurityLevel;
    property HasPrivilege[var CashierPrivilege: cashierprivilegesEnum]: WordBool read Get_HasPrivilege;
    property FailedLogOnAttempts: Integer read Get_FailedLogOnAttempts;
    property EmailAddress: WideString read Get_EmailAddress;
    property Messages: _CashierMessages read Get_Messages;
    property UnreadMessageCount: Integer read Get_UnreadMessageCount;
    property Name: WideString read Get_Name;
    property FirstName: WideString read Get_FirstName;
    property LastName: WideString read Get_LastName;
    property ReturnLimit: Currency read Get_ReturnLimit;
    property FloorLimit: Currency read Get_FloorLimit;
    property ID: Integer read Get_ID;
    property CashDrawerNumber: Smallint read Get_CashDrawerNumber;
    property Loaded: WordBool read Get_Loaded;
    property Number: WideString read Get_Number;
  end;

v2.0.0.151起的收银员声明

_Cashier = interface(IDispatch)
    ['{39B2C128-00F1-4834-B1A4-05197C708BD9}']
    function Get_Session: _SessionClass; safecall;
    function Get_CashDrawer: _CashDrawer; safecall;
    function Get_OverShortLimitType: overshortlimitEnum; safecall;
    function Get_MaxOverShortAmount: Currency; safecall;
    function Get_MaxOverShortPercent: Double; safecall;
    function Get_SecurityLevel: Smallint; safecall;
    function Get_HasPrivilege(var CashierPrivilege: cashierprivilegesEnum): WordBool; safecall;
    function Get_FailedLogOnAttempts: Integer; safecall;
    function Get_EmailAddress: WideString; safecall;
    function Get_Messages: _CashierMessages; safecall;
    function Get_UnreadMessageCount: Integer; safecall;
    function Get_Name: WideString; safecall;
    function Get_FirstName: WideString; safecall;
    function Get_LastName: WideString; safecall;
    function Get_ReturnLimit: Currency; safecall;
    function Get_FloorLimit: Currency; safecall;
    function Get_ID: Integer; safecall;
    function Get_CashDrawerNumber: Smallint; safecall;
    function Get_Loaded: WordBool; safecall;
    function Get_Number: WideString; safecall;
    function Get_PasswordAge: Integer; safecall;
    function Get_ReminderPeriod: Integer; safecall;
    function Get_PasswordResetFlag: WordBool; safecall;
    function Get_IsPasswordChanged: WordBool; safecall;
    procedure Set_IsPasswordChanged(var Param1: WordBool); safecall;
    function Get_TimecardID: Integer; safecall;
    procedure Set_TimecardID(var Param1: Integer); safecall;
    function ValidatePassword(var Password: WideString): WordBool; safecall;
    function IsPwdDuplicated(var CashierNumber: Integer; var Password: WideString): WordBool; safecall;
    property Session: _SessionClass read Get_Session;
    property CashDrawer: _CashDrawer read Get_CashDrawer;
    property OverShortLimitType: overshortlimitEnum read Get_OverShortLimitType;
    property MaxOverShortAmount: Currency read Get_MaxOverShortAmount;
    property MaxOverShortPercent: Double read Get_MaxOverShortPercent;
    property SecurityLevel: Smallint read Get_SecurityLevel;
    property HasPrivilege[var CashierPrivilege: cashierprivilegesEnum]: WordBool read Get_HasPrivilege;
    property FailedLogOnAttempts: Integer read Get_FailedLogOnAttempts;
    property EmailAddress: WideString read Get_EmailAddress;
    property Messages: _CashierMessages read Get_Messages;
    property UnreadMessageCount: Integer read Get_UnreadMessageCount;
    property Name: WideString read Get_Name;
    property FirstName: WideString read Get_FirstName;
    property LastName: WideString read Get_LastName;
    property ReturnLimit: Currency read Get_ReturnLimit;
    property FloorLimit: Currency read Get_FloorLimit;
    property ID: Integer read Get_ID;
    property CashDrawerNumber: Smallint read Get_CashDrawerNumber;
    property Loaded: WordBool read Get_Loaded;
    property Number: WideString read Get_Number;
    property PasswordAge: Integer read Get_PasswordAge;
    property ReminderPeriod: Integer read Get_ReminderPeriod;
    property PasswordResetFlag: WordBool read Get_PasswordResetFlag;
    property IsPasswordChanged: WordBool read Get_IsPasswordChanged write Set_IsPasswordChanged;
    property TimecardID: Integer read Get_TimecardID write Set_TimecardID;
  end;

如您所见,在更高版本中几乎没有添加任何东西,但是毫无疑问,在调用它们的功能时,我需要检查软件版本。 收银员只是那里25-30种类型中的一种,因此如果我必须为所有版本编写相同的基本实现....大任务,以及在以后阶段进行修改的可怕代码。

终于把它整理好了! 只是分享答案,以防其他任何人寻找它。

成功的关键是“后期绑定”,这意味着您不使用界面。

procedure TRefreshScreenRefreshScreen.Process(const Session: IDispatch);
var
 _Session: Variant;
begin

  _Session := Session;

  CodeSite.Send( csmLevel1, '_Session.Cashier.Name', _Session.Cashier.Name );
  CodeSite.Send( csmLevel1, '_Session.Cashier.Number', _Session.Cashier.Number );

end;

使用variant变量时,功能不会由编译器检查,而是在运行时检查,因此必须确保拼写正确,因为intellisense不会检查它。

像梦一样工作!

谢谢大家!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM