Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 是否可以基于零部件特性包含文件(链接)?_Delphi_Pascal_Conditional Compilation - Fatal编程技术网

Delphi 是否可以基于零部件特性包含文件(链接)?

Delphi 是否可以基于零部件特性包含文件(链接)?,delphi,pascal,conditional-compilation,Delphi,Pascal,Conditional Compilation,德尔福2007/2009奇数问题: 基于在设计时定义的组件属性,是否可以在链接中包含文件或将其保留 示例:如果我将SomeProperty保留为true,则在编译时,单元SomeUnit将包含在我的项目中。否则将不包括在内 我解决这个问题的第二种方法是部署第二个组件,当以表单形式(或不以表单形式)删除该组件时,它将包括unitinuses子句。但是如果可以用一个房产来做,那就更好了 我希望避免通过IFDEF进行条件编译,因为这会强制在每次构建项目时构建组件。还是不 我试图实现一种简单的方法,将一

德尔福2007/2009奇数问题:

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

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

我解决这个问题的第二种方法是部署第二个组件,当以表单形式(或不以表单形式)删除该组件时,它将包括unitinuses子句。但是如果可以用一个房产来做,那就更好了

我希望避免通过IFDEF进行条件编译,因为这会强制在每次构建项目时构建组件。还是不

我试图实现一种简单的方法,将一些单元包括在项目中,然后这些单元将为特定的数据库提供支持。在连接组件处,将这些设置为一个选项将非常简单:检查支持,这就完成了。取消选中,并在编译的应用程序中获得更少的KBs

编辑:例如,我将使用组件方式。我知道IFDEF方法和其他东西,但这迫使每次构建项目时都要构建组件。还是不

我试图实现一种简单的方法,将一些单元包括在项目中,然后这些单元将为特定的数据库提供支持。在连接组件处,将这些设置为一个选项将非常简单:检查支持,这就完成了。取消选中,在编译后的应用程序中获得更少的KBs。

你想解决什么问题


您可以添加一个后编译步骤,该步骤可以根据组件属性选择性地包含一些资源,但是您必须进行一些编码来实现这样的功能。

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

你的第二个想法很简单。例如,
TXPManifest
组件就是这样做的。请注意,从表单中删除此类组件不会“使用”相关单元


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

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

{$DEFINE youridentifier}

这将迫使你的标识符。要禁用,只需在$之前放置一个句点:

{.$DEFINE youridentifier}


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

您的第二种方法不一定能按您希望的方式工作。当您将组件放到表单上时,Delphi将有助于将必要的单元添加到用户列表中,但当您删除组件时,Delphi不会删除该单元。即使您不使用组件或从该单元导出的任何其他实体,当单元的初始化终结部分中存在代码时,该单元也有可能链接到您的应用程序。不幸的是,这种情况经常发生,即使可以按需初始化内容。

没有办法满足您的要求,但您可能不知道的是,包含在使用列表中但从未被引用的单元对可执行文件的大小影响很小。Delphi中的智能链接器能够很好地删除从未使用过的代码。如果您对组件引用的“可选单元”非常小心,并且其中没有全局执行的代码(所有代码都包含在一个或多个类中),那么它是否在uses子句中且未被使用,或者根本不在uses子句中都不重要


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

您可以使用DesignIntf.RegisterSelectionEditor注册选择编辑器(请参阅Delphi源代码中有关ISelectionEditor的注释),然后使用requireUnits过程在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;

+1,这似乎是有条件地包含文件的最佳方式。它还有一个额外的好处,就是可以用于命令行生成/自动生成。实际上应该有一种比这更简单的方法,可以很容易地将TComponent的单元添加到uses子句中,但只要它是在设计时动态创建的Tpersist,或者是组件类中某个单元中不存在的事件中的类型,那么添加起来就困难多了。什么时候才会调用选择编辑器?只有当开发人员在表单上删除一个新组件时?在这种情况下,SampleProperty仍将具有defa