Создайте TDataModule только один раз

Я пытаюсь создать procedure, который создает TDataModule в Application в качестве своего родителя.

Проблема в том, что во второй раз, когда я вызываю procedure, параметр dm все еще nil. Я ожидаю чего-то другого от nil, учитывая, что он был создан раньше.

Вот код, который я пытаюсь:

procedure UseDataModule(dm : TDataModule; cClass:TcomponentClass);
begin
    if dm = nil then
        cClass.Create(Application);
end;

Есть некоторые требования, которые я хочу для этого procedure:

  1. Данный TDataModule должен быть создан один раз

  2. Он должен быть создан procedure, потому что я хочу иногда использовать его, поэтому я не помещаю его в формы автоматического создания.

  3. Его родителем всегда будет Application

person WellingtonD    schedule 04.01.2019    source источник
comment
Вы упускаете возможность присвоить результат cClass.Create(Application) чему-либо. Если вы хотите, чтобы результат был назначен dm, тогда, а также ваш код, выполняющий фактическое назначение, dm должен быть параметром var, иначе результат будет отброшен после выхода из UseDataModule.   -  person MartynA    schedule 04.01.2019


Ответы (2)


Попробуйте изменить свой код на это:

procedure UseDataModule(var dm : TDataModule; cClass:TcomponentClass);
//  the `var` qualifier is to allow the value of `dm` to be retained 
//  after `UseDataModule` exits, otherwise the Created instance will be discarded
//  and you will have a memory leak
begin
  if dm = nil then
    dm := cClass.Create(Application);
end;

Имо, было бы лучше закодировать UseDataModule как функцию, но это во многом дело вкуса. Обратите также внимание, что вы можете написать if notAssigned(dm) вместо if dm = Nil.

Из вашего комментария я понял, что вы решили использовать следующий код вместо моего первоначального предложения:

  procedure UseDataModule(var dm : TDataModule; cClass:TcomponentClass);   
  begin 
    if dm = nil then begin 
      dm := cClass.Create(Application) as TDataModule; 
    end; 
  end;

что мне кажется хорошо.

person MartynA    schedule 04.01.2019
comment
dm = nil следует заменить на not assigned(), что более подробно. - person whosrdaddy; 05.01.2019
comment
С уважением, я не согласен, это должно быть вопросом личных предпочтений, imo. = Nil прозрачен и самодокументирован, unassigned непрозрачен и, как вы говорите, многословен.. - person MartynA; 05.01.2019
comment
Цель Assigned: проверить, назначен ли метод/функция. Подробнее читайте по адресу: docwiki.embarcadero.com/Libraries/Tokyo/en/System. Назначено - person Zam; 06.01.2019
comment
@MartynA Спасибо за ваш ответ. Я немного изменил ваш код, приведя созданный объект к типу TDataModule. Это то, что мне нужно. procedure UseDataModule(var dm : TDataModule; cClass:TcomponentClass); begin if dm = nil then begin dm := cClass.Create(Application) as TDataModule; end; end; Пожалуйста, измените свой код, чтобы я мог принять его как правильное решение - person WellingtonD; 07.01.2019
comment
Обновлено, как было предложено. - person MartynA; 07.01.2019

Другой вариант — использовать тот же код, что и для автоматического создания форм, с проверкой, создана ли она уже.

  // Create data module if it doesn't already exist
  if DM = nil then Application.CreateForm(TDM, DM); 
person Brian    schedule 04.01.2019
comment
Благодарю за ваш ответ. Я пробовал ваше решение раньше, и оно дало мне тот же результат. Параметр DM остается равным нулю, независимо от того, сколько раз я вызываю процедуру. - person WellingtonD; 07.01.2019