如何中断组件在其构造函数中的加载?

Posted

技术标签:

【中文标题】如何中断组件在其构造函数中的加载?【英文标题】:How to interrupt component from loading in its constructor? 【发布时间】:2012-01-25 18:43:38 【问题描述】:

我想在组件无法加载时向我的组件添加条件状态,并通知其用户(开发人员)该组件无法在设计时加载并在运行时以目标用户为目标(如果可能,以某种方式安全)。

如何防止组件在其构造函数中加载,以及如何在设计时和运行时安全地显示来自构造函数的消息(异常)?

constructor TSomeComponent.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);

  if csDesigning in ComponentState then
    if SomeIncompatibleCondition then
      begin
        // how to display message (exception) about the wrong 
        // condition and interrupt the loading of the component ?
      end;

  // is it possible to do the same at runtime ?
end;

谢谢

【问题讨论】:

您的测试在构造函数中(不在 Loaded 方法中),因为在开始从 DFM 加载属性之前需要该消息,对吗? 【参考方案1】:

一种方法:

Public 
   Property CreatedOK: boolean read fCreatedOK;

constructor TSomeComponent.Create(AOwner: TComponent);
begin
  ...
  fCreatedOK := ThereIsAnIncompatibleCondition;
end;

然后,程序员通过以下方式创建对象:

MyObject := TSomeComponent.Create(Self);
if (NOT MyObject.CreatedOK) then
  ... deal with it...

我们更喜欢这个,因为它避免了很多异常代码,这些异常代码可能很麻烦,并且在调试时很麻烦。 (不过那是另一个话题了!)

我们使用的另一种方法是,如果构造函数有很多工作,则将工作转移到用户在构造后必须调用的另一个方法。这还有一个好处,就是让我们可以轻松地将许多值传递给对象。

public
  constructor Create...
  function InitAfterCreate:boolean;
end;

调用者这样做:

MyObject := TSomeComponent.Create
if (NOT MyObject.InitAfterCreate) then
   ... deal with it ...

或者,如果您使用 InitAfterCreate 来传递值,您可以将其定义为

function InitAfterCreate( Value1: Integer, etc.):boolean

然后InitAfterCreate可以检查对象的状态并返回结果。

这些方法的一个缺点是程序员必须记住调用 InitAfterCreate 或检查 MyObject.CreatedOk。为了防止他们不这样做,您可以将一些 Asserts 放在对象的其他一些方法的开头,例如:

procedure TForm.FormShow
begin
  Assert(fCreatedOK, "Programmer failed to check creation result.")
  ...
end;

在所有情况下,一个挑战是不终止 Create 使对象处于半创建状态,处于不确定状态,这可能会使您的析构函数难以知道要销毁多少。

【讨论】:

【参考方案2】:

引发异常,例如:

constructor TSomeComponent.Create(AOwner: TComponent); 
begin 
  inherited Create(AOwner); 
  if SomeIncompatibleCondition then 
    raise Exception.Create('Incompatible condition detected!');
end; 

【讨论】:

以上是关于如何中断组件在其构造函数中的加载?的主要内容,如果未能解决你的问题,请参考以下文章

如何允许组件中的函数访问构造函数中导入的工厂?

在其派生类C++的构造函数中调用基类的构造函数[重复]

我应该在其构造函数中还是在 app.component 的 ngOnInit 方法中初始化 Angular 服务?

如何在其构造函数中获取使用依赖注入的类的实例

无法通过构造函数将组件注入组件?

当我的服务在其构造函数中有可注入对象时,如何将服务注入我的测试?