首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否可以在delphi中只为设计时间使用一个库?

是否可以在delphi中只为设计时间使用一个库?
EN

Stack Overflow用户
提问于 2014-05-21 13:03:04
回答 2查看 869关注 0票数 4

我正在尝试编写一个组件,它正在从obj文件中加载3D对象。我正在使用ToolsAPI库作为GetActiveProject.FileName。我将designide.dcp添加到bpl中的Requiers部件中。我注册了我的对象,在设计中,当我将这个对象的一个实例放在一个TViewPort3D上时,在一切正常之前,我可以从obj文件中看到这个对象被加载到场景中,但是当我试图编译这个项目时,我会得到一个错误,上面写着ToolsAPI.dcu没有找到。

加载obj文件的过程是( Model变量的类型为TModel3D):

代码语言:javascript
复制
procedure TMyObject.LoadModel(fileName: string);
begin
  if(csDesigning in ComponentState)then
    Model.LoadFromFile(IncludeTrailingPathDelimiter(ExtractFilePath(GetActiveProject.FileName))+'Obj\'+filename)
  else
    Model.LoadFromFile(IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)))+'Obj\'+filename);
end;

此过程用于构造函数,如下所示(TMyObject从TDummy继承):

代码语言:javascript
复制
constructor TMyObject.Create(AOwner:TComponent)
begin
  inherited;
  Model:=TModel3D.Create(Self);
  Model.Parent:=Self;
  LoadModel('Object1.obj');
end;

在组件的主机项目即将编译时,是否仍然要防止使用ToolsAPI库?

我只是在想类似的指令,如下所示。

代码语言:javascript
复制
{$IFDEF DESIGNTIME}    
uses ToolsAPI;    
{$ENDIF}

但做这种事有可能吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-05-21 13:39:06

听起来好像您正在尝试将设计时代码编译到一个运行时项目中。运行时包或可执行文件。这是不允许的您根本无法将任何ToolsAPI单元编译成一个不是设计时包的项目。

当然可以使用条件编译来排除ToolsAPI单元,但是您必须定义自己的条件定义。没有内置的条件,将满足您的需要。

但是使用条件编译可能不是最好的解决方案。通常,您会将使用Tools API的代码分离为不同的单元,并且只在设计时项目中包含这些单元。

因此,您的组件的代码将被分成两个单元。第一个单元,比如uMyComp.pas,包含大部分代码。此单元声明组件并提供其实现。uMyComp.pas中没有任何对ToolsAPI的引用。第二个单元,uMyCompReg.pas说,执行组件注册和任何其他需要ToolsAPI的任务。这些单元之间存在依赖关系,因为uMyCompReg.pas使用uMyComp.pas。然后,您的设计时包将包括两个单元,任何其他不是设计时间的项目都将只包括uMyComp.pas

你可以用条件词达到同样的效果。设计时项目将定义一个条件,以表明这是设计时间。因此,项目设置可能包括一个名为DESIGNTIME的条件的定义。然后,您的组件的所有代码将驻留在一个名为uMyComp.pas的单元中。任何与设计时间相关的代码都将以DESIGNTIME为条件。而包含uMyComp.pas的任何其他项目都不会定义DESIGNTIME,因此只会省略设计时的代码。

虽然这是可能的,但我认为这并不是解决问题的最佳方法。实际上,如果您查看大量的开放源代码组件开发示例,如果您发现使用条件来处理设计时代码与运行时代码的分离,我会感到惊讶。

如何将ToolsAPI代码划分为设计时间单元?下面是问题的方法:

代码语言:javascript
复制
procedure TMyObject.LoadModel(fileName: string);
begin
  if csDesigning in ComponentState then
    Model.LoadFromFile(IncludeTrailingPathDelimiter(
      ExtractFilePath(GetActiveProject.FileName))+'Obj\'+filename)
  else
    Model.LoadFromFile(IncludeTrailingPathDelimiter(
      ExtractFilePath(ParamStr(0)))+'Obj\'+filename);
end;

首先,让我们看看这段代码的共性。首先要注意的是,调用LoadFromFile的外部是相同的。只有在中间,目录的选择,才会有变化。让我们这样写:

代码语言:javascript
复制
procedure TMyObject.LoadModel(fileName: string);
var
  ModelDir: string;
begin
  if csDesigning in ComponentState then
    ModelDir := ExtractFilePath(GetActiveProject.FileName)
  else
    ModelDir := ExtractFilePath(ParamStr(0));
  Model.LoadFromFile(IncludeTrailingPathDelimiter(ModelDir)+'Obj\'+filename);
end;

问题是如何将GetActiveProject.FileName移动到设计时代码中。为此,需要使用依赖项注入(DI)。允许另一方提供逻辑。您需要让TMyObject不了解这个特定的细节。您可以使用DI框架来完成这一任务,但这可能是一个小重量级的任务。因此,让我们声明一个包含函数指针的类变量:

代码语言:javascript
复制
type
  TMyObject = class(...)
  ...
  public
    class var GetModelDir: TFunc<string>;
  end;

此功能点允许类外部的其他各方指定模型目录的位置。现在,LoadModel变成:

代码语言:javascript
复制
procedure TMyObject.LoadModel(fileName: string);
var
  ModelDir: string;
begin
  if Assigned(GetModelDir) then
    ModelDir := GetModelDir()
  else
    ModelDir := ExtractFilePath(ParamStr(0));
  Model.LoadFromFile(IncludeTrailingPathDelimiter(ModelDir)+'Obj\'+filename);
end;

此时,您的代码现在可以在设计时包之外使用。下一步是添加代码,以便在设计时指定GetModelDir。此代码只在设计时注册组件的单元。代码的明显位置在该单元的初始化部分。看起来是这样的:

代码语言:javascript
复制
initialization
  TMyObject.GetModelDir := 
    function: string
    begin
      Result := GetActiveProject.FileName;
    end;

我在这里使用过匿名方法,但您也可以使用object方法,也可以使用普通的旧函数类型,这取决于Delphi版本。

票数 2
EN

Stack Overflow用户

发布于 2014-05-21 13:43:57

是的,但是最好不要有条件的定义,因为这样会造成比它更多的复杂和限制。

  • 您需要根据代码是设计时代码还是运行时代码,将代码划分为不同的单元。
    • 例如,对于单个组件,大部分(不依赖ToolsAPI )进入一个单元。
    • 第二个单元执行组件注册,并可能为组件提供自定义设计时编辑器。
    • 第二个单元使用第一个单元,您可以在没有条件定义的情况下进行干净的分离。

  • 然后创建两个单独的包:设计时和运行时。
  • 设计时包将依赖于ToolsAPI。
  • 确保没有任何运行时单元使用任何设计时单元。
  • 如果任何设计时单元使用运行时单元(很可能),则设计时包将需要运行时包。

有了上面的包结构,使用新组件的应用程序应该只依赖于运行时单元。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23783993

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档