是否可以根据组件属性包含文件(链接)?

时间:2009-01-13 19:17:27

标签: delphi pascal conditional-compilation

德尔福2007/2009奇怪的问题:

基于设计时定义的组件属性,是否可以在链接中包含文件或保留文件?

示例:如果我将SomeProperty保留为true,则在编译时,单元SomeUnit将包含在我的项目中。否则它将不包括在内。

我遇到这个问题的第二个方法是部署第二个组件,当在表单中删除时(或不在表单中)将包含该单元的uses子句。但如果可以用财产来做,那就更好了。

我想通过IFDEF避免条件编译,因为这会强制每次构建项目时构建组件。或者不是?

我正在努力实现在项目中包含一些单元的简单方法,然后这些单元将为特定数据库提供支持。将这些选项放在连接组件中将非常简单:检查支持并完成。取消选中,并在已编译的APP中获得更少的KB。

编辑:我将继续使用组件方式。我知道IFDEF方法和事情,但这会强制每次构建项目时构建组件。或者不是?

我试图通过简单的方法将一些单元包含在项目中,然后这些单元将为特定数据库提供支持。将这些选项放在连接组件中将非常简单:检查支持并完成。取消选中,并在已编译的APP中获得更少的KB。

6 个答案:

答案 0 :(得分:6)

没有

你想要解决什么?

您可以添加一个后编译步骤,该步骤可选地包含基于组件属性的某些资源 - 但您必须进行一些编码才能实现此类功能。

答案 1 :(得分:4)

您可以使用{$ IFDEF youridentifier}可选代码{$ ENDIF}方法有条件地将数据编译到您的应用程序中,然后启用它只需转到您的项目选项并在相应的选项字段中输入您的标识符。另一种方法是将以下内容添加到单元的顶部(或包含文件中):

{$ DEFINE youridentifier}

会强制你的标识符。要禁用,只需在$:

之前放置一个句点

{。$ DEFINE youridentifier}

使用这些技术,它很容易有条件地引入代码或用每次编译替换代码。

答案 2 :(得分:3)

编写IDE加载项。处理“编译前”通知并检查项目中的任何表单或数据模块是否具有您感兴趣的类型的组件,然后检查其属性。根据您在那里找到的内容,您可以尝试修改单元的内容以使用您选择的其他单元。这当然听起来不容易,但似乎有可能。

你的第二个想法很容易。例如,它正是TXPManifest组件所做的。请注意,从表单中删除此类组件“不使用”关联的单元。

要有条件地添加对不同数据库的支持,您可以考虑使用运行时包。 (毕竟,这就是IDE如何设法支持这么多不同类型的组件。)将每个数据库的自定义代码放入不同的包中。然后,您支持的数据库就是那些在运行时可用包的数据库。无需编译时或设计时配置。然而,障碍是管理哪些软件包可用,并确定哪些软件包是提供数据库支持的软件包。

答案 3 :(得分:1)

您的第二种方法不一定按您希望的方式运作。当您将组件拖放到表单上时,Delphi将有用地将必要的单元添加到您的使用列表中,但在删除组件时它不会删除该单元。即使您不使用该部件或该部件的任何其他导出权利,当初始化最终确定部分单位。不幸的是,这种情况经常发生,即使可以按需初始化内容。

答案 4 :(得分:1)

没有办法按照您的要求进行操作,但您可能不知道的是,您的使用列表中包含但未被引用的单元对可执行文件的大小影响最小。 Delphi中的智能链接器可以很好地删除从未使用过的代码。如果你注意组件引用的“可选单元”,并且没有任何全局执行的代码(一切都是自包含在一个或多个类中)那么它是否无关紧要在使用条款中,未使用,或根本不在使用条款中。

这很容易让你做我认为你想做的事情,那就是将一个组件放在一个表单上,该表单包含一个可以链接到你的应用程序的单元。移除组件会产生不在单元中链接的效果。但是,我相信,使用过的单元中的任何资源(例如$ R指令中包含的表单或其他项目)仍将包含在可执行文件中。

答案 5 :(得分:1)

您可以使用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;