Как прервать загрузку компонента в его конструкторе? - PullRequest
1 голос
/ 22 декабря 2011

Я хотел бы добавить к моему компоненту условное состояние, когда компонент не может быть загружен, и сообщить его пользователю (разработчику), что этот компонент не может быть загружен во время разработки, и целевого пользователя во время выполнения (как-нибудь безопасно, если это возможно).

Как можно предотвратить загрузку компонента в его конструкторе и как безопасно отображать сообщение (исключение) из конструктора во время разработки и во время выполнения?

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;

Спасибо

Ответы [ 2 ]

6 голосов
/ 22 декабря 2011

Вызовите исключение, например:

constructor TSomeComponent.Create(AOwner: TComponent); 
begin 
  inherited Create(AOwner); 
  if SomeIncompatibleCondition then 
    raise Exception.Create('Incompatible condition detected!');
end; 
2 голосов
/ 22 декабря 2011

Один подход:

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, оставляя объектнаполовину созданный, в неопределенном состоянии, из-за которого вашему деструктору будет трудно понять, сколько нужно уничтожить.

...