65.9K
CodeProject 正在变化。 阅读更多。
Home

智能指针和 COM 服务器卸载。第 3 部分

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2015年11月21日

CPOL

3分钟阅读

viewsIcon

5450

在本文中,我将介绍一种使用智能指针处理 COM 服务器卸载问题的方法。

引言

我将提醒您,在本系列文章中,我研究了 COM 服务器应用程序未卸载的情况。 在该文章的 上一部分 中,我们研究了可能导致应用程序无法卸载的原因。 在本文的这一部分中,我将介绍智能指针的概念,它可能非常有用。

目录

本文由几部分组成。以下是文章各部分的完整列表

关于智能指针

智能指针的概念起源于 C++ 等语言,在这些语言中,程序员可以深入控制与对象操作相关的内存分配和释放过程。正如维基百科所说,智能指针 是一种抽象数据类型,它模拟指针,同时提供一些附加功能。

Delphi 语言不如 C++ 灵活,但使用当前的语言状态,可以实现具有轻微限制的智能指针。在我的例子中,我想将对入口点接口的所有引用注册到某个全局注册表中。请注意,我谈论的是对入口点接口的引用,而不是入口点对象的实例。我们可以轻松扩展入口点接口对象实现,但扩展入口点接口引用需要一些思考。

好消息是 Delphi 中有可用的智能指针实现。Spring4D 框架。 该框架的源代码可在 BitBucket 上找到。 但目前智能指针不是主分支的一部分,因此您需要找到一个具有此实现的分支。 智能指针实现中没有太多代码,所以我将在这里重现代码

type
  TSmartPointer<T> = class(TInterfacedObject, ISmartPointer<T>)
  private
    fValue: T;
    function Invoke: T; inline;
  public
    constructor Create; overload;
    constructor Create(const value: T); overload;
    destructor Destroy; override;
  end;

implementation
...

constructor TSmartPointer<T>.Create;
begin
  case {$IFDEF DELPHIXE7_UP}System.GetTypeKind(T){$ELSE}GetTypeKind(TypeInfo(T)){$ENDIF} of
    tkClass: PObject(@fValue)^ := TActivator.CreateInstance(TypeInfo(T));
    tkPointer: PPointer(@fValue)^ := AllocMem(GetTypeSize(GetTypeData(TypeInfo(T)).RefType^));
  end;
end;

constructor TSmartPointer<T>.Create(const value: T);
begin
  fValue := value;
end;

destructor TSmartPointer<T>.Destroy;
begin
  FinalizeValue(fValue, 
    {$IFDEF DELPHIXE7_UP}
    System.GetTypeKind(T)
    {$ELSE}
    GetTypeKind(TypeInfo(T))
    {$ENDIF});
  inherited;
end;

function TSmartPointer<T>.Invoke: T;
begin
  Result := fValue;
end;

拥有这样的智能指针,我们可以在许多情况下使用它,当期望指向的类型时。 我们可以通过智能指针间接调用指向对象的方法。 我们可以将智能指针作为参数传递给期望指向类型的函数。 我们甚至可以将智能指针转换为另一个接口,该接口实现了指向对象。 但在某些情况下,不支持透明类型转换。 特别是,我们应该从指向的对象手动创建智能指针,并且如果该字段的类型是智能指针,则应该手动实现指向对象属性的 getter 和 setter 方法。

type
  TDummyClass = class(TObject)
  private
    FApplication: ISmartPointer<ITestUnloadApplication>;
    // Application getter.
    function GetApplication: ITestUnloadApplication;
    // Application setter.
    procedure SetApplication(
      // Application.
      const Value: ITestUnloadApplication);
  public
    // Doesn't work.
    // property Application: ITestUnloadApplication read FApplication write FApplication;
    // Works like this.
    property Application: ITestUnloadApplication read GetApplication write SetApplication;
  end;  

...
procedure DoSomething(const ApplicationIntf: ITestUnloadApplication); 
begin
  ...
end;

procedure TestProcedure;
var
  ApplicationRef: ISmartPointer<ITestUnloadApplication>;
begin
  ApplicationRef := TSmartPointer<ITestUnloadApplication>.Create(
    TTestUnloadApplication.Create as ITestUnloadApplication);
  // ITestUnloadApplication interface method called indirectly through smart pointer.
  ApplicationRef.DoSomething;
  // ITestUnloadApplication function argument is passed indirectly from smart pointer.
  DoSomething(ApplicationRef);
end;

我想现在很明显,我们可以用相当少的修改将指向对象字段替换为智能指针字段。 并且在替换了引用之后,我们可以在我们的智能指针中添加一些额外的逻辑来跟踪接口引用的使用情况。 我将在本文的下一部分中给出完整的示例。

下一步

在本文的这一部分中,我介绍了智能指针的概念,我们可以使用它来扩展标准指针变量的行为。

在文章的下一部分中,我将解释如何使用智能指针来跟踪应用程序卸载情况。 本文的这一部分将是最后一部分。

© . All rights reserved.