【问题标题】:Adding new members and extending methods in an external API interface在外部 API 接口中添加新成员和扩展方法
【发布时间】:2021-12-15 09:22:57
【问题描述】:

我正在使用 SOLIDWORKS API 在 Visual Studio 中构建 VB.NET 应用程序 - 我的应用程序通过 COM 连接到 SOLIDWORKS 应用程序,并使用各种 API 调用在其中执行一些操作。通过将项目参考添加到 SOLIDWORKS .dll 文件来访问 API。出于法律原因,这些文件必须嵌入到我的应用程序的可执行文件中。

这个问题并不特定于那个 API,但我会尝试解释我想要做什么。有一个名为 Body2 的 SOLIDWORKS API 接口,用于控制 3D 空间中模型对象(实体)的操作。例如,Body2 接口提供了一个方法ApplyTransform,该方法允许通过对其应用MathTransform(一个变换矩阵)来移动或旋转某个物体:

ModelBody.ApplyTransform(rotationMatrix) 'rotates the body

现在,Body2 对象不存储这些转换矩阵 - 它们被应用并被遗忘。但是,在我的应用程序中,我需要持久存储该信息,以便在某个时候,我可以反转所有转换,并将主体返回到它的原始位置。

因此,我想扩展 Body2 接口,给它添加一个新的属性,叫做“CombinedTransformMatrix”,这样每次调用ApplyTransform,我也可以更新这个属性的值,例如:

ModelBody.ApplyTransform(rotationMatrix)
ModelBody.CombinedTransformMatrix.Multiply(rotationMatrix)
ModelBody.ApplyTransform(translationMatrix)
ModelBody.CombinedTransformMatrix.Multiply(translationMatrix)

当我最终想将身体恢复到原来的位置时,我可以调用:

ModelBody.ApplyTransform(ModelBody.CombinedTransformMatrix.Inverse)
ModelBody.CombinedTransformMatrix = New MathTransform 'reset matrix

理想情况下,扩展ApplyTransform 方法会非常好,这样它会自动更新CombinedTransformMatrix,例如:

Overrides Function ApplyTransform(Xform As MathTransform) As Boolean
   'Do whatever SOLIDWORKS does in this function

   'My additional code:
   Me.CombinedTransformMatrix.Multiply(Xform)
End function

(我知道我应该做一个扩展而不是覆盖,但我不知道怎么做)

如果可以的话,我可以简化身体转换的代码,因为 CombinedTransformMatrix 会自动更新:

'Rotate and move
ModelBody.ApplyTransform(rotationMatrix)
ModelBody.ApplyTransform(translationMatrix)

'Return to original position
ModelBody.ApplyTransform(ModelBody.CombinedTransformMatrix.Inverse)
ModelBody.CombinedTransformMatrix = New MathTransform 'reset matrix

我非常喜欢这种解决方案,而不是从Body2 创建一些派生类,或者制作某种将CombinedTransformMatrix 存储在Body2 对象之外的包装类。我想将该位存储在对象本身内。至于派生类,Visual Studio 甚至不允许我从Body2 继承 - 说“当其程序集配置为嵌入互操作类型时,不允许使用'Body2Class'。”。而且我必须嵌入这些 .dll 文件,否则我将不得不将它们与我的应用程序的 .exe 一起发送,这是 SOLIDWORKS 法律禁止的。

我想要的可能吗?我可以在不创建派生类的情况下将CombinedTransformMatrix 添加到Body2 接口吗?是否可以在不知道该方法是如何实现的情况下使用我的附加代码扩展该 ApplyTransform 方法?

如果不是,实现我想要的下一个最佳解决方案是什么?就像我说的,我非常希望避免 Body2 之外的包装器或其他变量,因为会有很多这些 Body2 对象,它们将在应用程序的整个生命周期中持续存在,每个都会有不同的转换,所以有将他们的转换信息存储在自己之外会严重地使我的代码复杂化。

【问题讨论】:

  • 要创建一个扩展方法,你的方法需要在一个共享的上下文中(我知道Module 确实有效,我怀疑Shared Class 也可以),它需要@ 987654345@属性,第一个参数需要是被扩展的类型。
  • @Craig 感谢您提供的信息。但是主要问题是什么,向 API 提供的接口添加一个新属性?
  • 据我所知,扩展只能作为子/功能。但是你当然可以在任何接口上放置一个扩展方法——参见 Linq,它在IEnumerable(Of T) 上完全实现为扩展方法。
  • @Craig 我明白了,谢谢。但是我需要在那个 Body2 对象上存储一些数据,而一个方法无法存储它......我需要以某种方式附加一个属性。
  • 在这种情况下,您需要某种封装。也许那是继承,也许是某种包装(组合)。

标签: vb.net api solidworks solidworksapi


【解决方案1】:

没有通用的方法来做到这一点。您可以使用 COM 对象(例如本例中的 IBody2)作为键,将附加参数(标签)作为值来维护单独的字典。当指针被销​​毁时,您将需要手动更新字典以删除数据。然而,有一些特定的软件接口确实有一些方法来关联自定义数据(类似于标签)。例如,IBody2 有 IBody2::AddPropertyExtension2 允许将自定义数据与主体本身相关联,IEntity 有 IEntity::CreateStringAttributeDefinition(注意,这不是文档化方法)等等。

但是对于 Windows 控件没有通用 System::Windows::Forms::Tag 属性或 COM 类的 DependencyObjects 的依赖属性。

【讨论】:

    猜你喜欢
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-23
    • 2019-08-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多