Можно ли включать файлы (связывать) на основе свойства компонента?

Delphi 2007/2009 странный вопрос здесь:

Возможно ли, на основе свойства компонента, определенного во время разработки, включать файлы в компоновку или оставлять их?

Пример: Если я оставлю SomeProperty true, то при компиляции модуль SomeUnit будет включен в мой проект. В противном случае он не будет включен.

Мой второй подход к этой проблеме заключается в развертывании второго компонента, который при удалении в форме (или без него) будет включать в себя блок использования. Но если это можно сделать с собственностью, это будет лучше.

Я хочу избежать условной компиляции через IFDEF, потому что это заставляет компонент собираться каждый раз при сборке проектов. Или не?

Я пытаюсь найти простой способ включения некоторых модулей в проект, а затем эти модули будут поддерживать определенные базы данных. Иметь их в качестве опции в компоненте подключения будет идеально просто: проверьте поддержку, и все готово. Снимите флажок и получите меньше КБ в скомпилированном приложении.

edit: например, я останусь с компонентным способом. Я знал метод IFDEF и все такое, но это заставляет компонент собираться каждый раз при сборке проектов. Или не?

Я пытался найти простой способ включения некоторых модулей в проект, а затем эти модули будут поддерживать определенные базы данных. Иметь их в качестве опции в компоненте подключения будет идеально просто: проверьте поддержку, и все готово. Снимите флажок и получите меньше КБ в скомпилированном приложении.


person Gustavo Ciello    schedule 13.01.2009    source источник


Ответы (6)


No.

Что вы пытаетесь решить?

Вы можете добавить шаг посткомпиляции, который может включать некоторый ресурс на основе свойства компонента, но для реализации такой функции вам придется написать код.

person gabr    schedule 13.01.2009

Вы можете использовать метод дополнительного кода {$IFDEF youridentifier} {$ENDIF} для условной компиляции данных в ваше приложение, а затем, чтобы включить его, просто перейдите к параметрам вашего проекта и введите свой идентификатор в соответствующее поле параметра. Другой способ сделать это — добавить следующее в верхнюю часть вашего устройства (или во включаемый файл):

{$DEFINE ваш идентификатор}

который принудительно включит ваш идентификатор. Чтобы отключить, просто поставьте точку прямо перед $:

{.$DEFINE ваш идентификатор}

Используя эти методы, легко условно ввести код или заменить код при каждой компиляции.

person skamradt    schedule 13.01.2009
comment
+1, это кажется лучшим способом условного включения файлов. У него есть дополнительное преимущество, заключающееся в том, что его можно использовать для сборки из командной строки/автоматической сборки. - person mghie; 14.01.2009

Напишите надстройку IDE. Обработайте уведомление «перед компиляцией» и проверьте, есть ли в каких-либо формах или модулях данных в проекте компоненты интересующего вас типа, а затем проверьте их свойства. Основываясь на том, что вы там найдете, вы можете попробовать изменить содержимое модуля, чтобы использовать другой модуль по вашему выбору. Это, конечно, звучит непросто, но кажется возможным.

Ваша вторая идея очень проста. Например, это именно то, что делает компонент TXPManifest. Имейте в виду, что удаление такого компонента из формы не "отменяет использование" связанного с ним модуля.

Чтобы условно добавить поддержку разных баз данных, вы можете рассмотреть возможность использования пакетов времени выполнения. (В конце концов, именно поэтому IDE удается поддерживать так много различных типов компонентов.) Поместите пользовательский код каждой базы данных в отдельный пакет. Тогда базы данных, которые вы поддерживаете, — это просто те, у которых есть пакеты, доступные во время выполнения. Не требуется настройка времени компиляции или времени разработки. Однако препятствием для этого является управление доступными пакетами и определение того, какие из них являются пакетами, обеспечивающими поддержку базы данных.

person Rob Kennedy    schedule 13.01.2009

Ваш второй подход не обязательно будет работать так, как вы хотите. В то время как Delphi услужливо добавит необходимую единицу в ваш список использований, когда вы перетащите компонент на форму, она не удалит единицу при удалении компонента. И даже если вы не используете компонент или любую другую экспортированную сущность из этого модуля, возможно, что модуль все равно будет связан с вашим приложением, когда есть код в инициализации или >доработка часть устройства. К сожалению, это происходит очень часто, даже когда можно было бы инициализировать вещи по требованию.

person mghie    schedule 14.01.2009

Невозможно сделать то, что вы просите, но вы можете не знать о том, что единицы, которые включены в ваш список использования, но никогда не упоминаются, окажут минимальное влияние на размер вашего исполняемого файла. Интеллектуальный компоновщик в Delphi отлично справляется с удалением кода, который никогда не используется. Если вы осторожны с вашим «необязательным модулем», на который ссылается компонент, и в нем нет кода, который выполняется глобально (все содержится в классе или классах), тогда не имеет значения, если это в предложении Uses и не используется, или вообще не в предложении Uses.

Это легко позволит вам сделать то, что, как я думаю, вы хотите сделать, а именно поместить компонент в форму, которая включает модуль, который затем можно связать с вашим приложением. Удаление компонента приведет к отсутствию связи в модуле. Однако я считаю, что любые ресурсы (например, формы или другие элементы, включенные в директиву $R), которые находятся в используемом модуле, все равно будут включены в исполняемый файл.

person skamradt    schedule 16.01.2009

Вы можете использовать DesignIntf.RegisterSelectionEditor, чтобы зарегистрировать редактор выбора (см. комментарии в исходном коде Delphi об ISelectionEditor), а затем использовать процедуру RequiresUnits для включения дополнительных единиц в предложение uses.

TMySelectionEditor = class(TSelectionEditor)
public
  procedure RequiresUnits(Proc: TGetStrProc); override;
end;

procedure Register;

implementation

procedure TMySelectionEditor.RequiresUnits(Proc: TGetStrProc);
var
  comp: TMyComponent;
  I: Integer;
begin
  inherited RequiresUnits(Proc);
  Proc('ExtraUnit');  
  // might be a better way of doing the code from here onwards?
  if (Designer=nil)or(Designer.Root=nil) then Exit;

  for I := 0 to Designer.Root.ComponentCount - 1 do
  begin
      if (Designer.Root.Components[i] is TMyComponent) then
      begin
        comp := TMyComponent(Designer.Root.Components[i]);
        if comp.SampleProperty = True then
            Proc('ExtraUnit2');
        Proc(comp.ObjProperty.UnitName);
      end;
  end;
end;

procedure Register;
begin
  RegisterSelectionEditor(TMyComponent, TMySelectionEditor);
end;
person Dan Bartlett    schedule 10.07.2010
comment
На самом деле должен быть более простой способ, легко добавить модуль TComponent в предложение uses, но как только это TPersistent, созданный динамически во время разработки, или тип события, который не существует ни в одном из единиц в классе компонента, то добавить его становится намного сложнее. - person Dan Bartlett; 10.07.2010
comment
Когда будет вызываться редактор выбора - только когда разработчик бросает на форму новый компонент? В этом случае SampleProperty по-прежнему будет иметь значение по умолчанию, и изменение на другое значение не будет иметь никакого эффекта. - person mjn; 10.07.2010
comment
Нет, похоже, он вызывается только при компиляции (один раз для каждого компонента), так что это будет зависеть от значения свойства в это время. Кажется, нет способа сослаться на обрабатываемый компонент, поэтому этот код зацикливается на всех компонентах, размещенных в форме (вам может потребоваться изменить, чтобы разрешить подсвойства) - person Dan Bartlett; 10.07.2010