接口版本控制

Ken*_*ran 10 delphi com dll interface version

在我工作的地方,我们刚刚发布了一个使用dll的功能,该功能严重依赖于接口.dll和所有客户端应用程序都是用Delphi编写的.无需注册.这个DLL不是一个合适的com服务器.唯一的限制是dll和客户端应用程序都可以访问包含接口的单元.这允许我们将复杂数据传递给使用此dll的应用程序,而不需要求助于记录指针,数组或极其繁重的函数签名,也不需要bpl或完全兼容的COM服务器引入的包袱.

看起来它解决了我们遇到的一个没有缺点的重大问题.不幸的是有一个缺点.接口发布后对接口的任何更改都需要随后重新编译该接口的任何使用者.这对于属于同一发布周期的项目来说很好,但是我们的一些项目有不同的发布计划.

我对此进行了一些研究,看起来通常的做法是引入一个继承自之前发布的接口的新接口,而不是修改原始接口.

type
  IOriginalInterface = interface
  ['{8B598EC1-AD92-4144-A1BE-9062C5EA0748}']
    procedure DoSomething;
  end;

  INewInterface = interface(IOriginalInterface)
  ['{DD9D9DE0-0F87-4BC5-803C-74C8AB0F3E39}']
    procedure DoSomethingElse;
  end;
Run Code Online (Sandbox Code Playgroud)

这可确保针对原始接口编译的旧可执行文件继续有效.

我注意到使用RAD Studio打开工具api时,只要引入了新的接口,就会重命名接口.因此,不是为最新的界面提供新名称,而是最新的界面获取原始界面的名称,并重命名原始界面.

type
  IOldInterface = interface
  ['{8B598EC1-AD92-4144-A1BE-9062C5EA0748}']
    procedure DoSomething;
  end;

  IOriginalInterface = interface(IOldInterface)
  ['{DD9D9DE0-0F87-4BC5-803C-74C8AB0F3E39}']
    procedure DoSomethingElse;
  end;
Run Code Online (Sandbox Code Playgroud)

这显然适用于RAD Studio团队以及第三方扩展供应商.这可确保任何重新编译的客户端都将使用最新的接口,而无需更改任何代码.我认为这是有效的,因为名称是无关紧要的,并且在编译代码之后剩下的只是接口定义,使用GUID解析.

说了这么多,这是我们现在面临的界面版本问题的一个很好的解决方案吗?还有其他问题需要注意吗?

All*_*uer 10

让我解释一下您使用ToolsAPI观察到的逻辑,然后您可以确定它如何适用于您的情况.你的推理非常接近.

对于那些意在接口消耗的插件和扩展IDE,你对其中的接口版本,并命名的方式是正确的.我们的想法是现有代码将引用特定的接口名称,因为该接口上也存在所有现有方法.由于旧代码根本无法引用任何新方法,因此将它们包含在新接口中是安全的.

但是,如果仔细观察,对于要通过插件或IDE扩展实现的接口,您将看到相反的情况.新接口获得新名称,所有旧的现有接口保持不变.这是因为,作为接口的实现者,您必须实现接口的所有方法.根据定义,现有代码将不会实现新方法.当IDE需要调用用户实现的方法时,它将始终通过查询引入该方法的接口版本来进行该调用,这可能不是该接口的最新版本.因此,应该将所有祖先接口列为在实现类上实现.

总之,IDE的ToolsAPI的规则是,对于插件使用的接口,最新版本的接口始终获取无版本名称.对于插件实现的接口,新接口始终获得新名称.