在编译时以后期格式引用 COM 库



我有一个不寻常的情况,我需要使用第三方库。

该库与产品的最后 3 个版本一起打包。通常这意味着我的软件可以与所有这些软件一起使用,我会引用三个版本中最古老的版本(在编译时),它将适用于所有三个版本。然而,情况并非如此,这意味着如果我想使用对库的适当"引用",我需要为每个版本单独编译。

我的第一个选择是将所有特定于类型的代码转换为使用后期绑定格式例如。

Dim item as new documentItem          ' this is not real code, just pseudo...

Dim item as object = createobject("clsid.documentItem")

绝对讨厌做这种后期绑定格式并丢失编译时检查。特别是因为这个库很大而且非常复杂。

第二种方法似乎是不可能的,即安装所有 3 个产品并分别引用所有库。似乎他们"尝试"使其兼容,并且COM组件的唯一标识符是相同的。除非有人可以解释如何在同一个 DLL 中导入具有重叠 CLSID 和名称的相同库 3 次。(这也意味着需要大量安装或代码修改,以便为每个目标应用程序使用不同的包装器)

问题:有谁知道处理这种情况的其他方法吗?我的目标是保留编译时检查和自动完成。可能是在客户端创建互操作库的某种方法。

更新:我已经通过自己的包装器 DLL 完成了对该库的所有访问,以将函数合并到一个项目中。因此,我暂时将我创建的整个包装库复制到新的 DLL 中,并使用正则表达式对后期绑定格式进行大规模对话。使用相同的根命名空间,我可以轻松地在它们之间切换。在这种格式中,我可以针对一个使用严格编译器规则的版本进行大部分开发。由于更改在那里完成并得到证明,我将副本移动到后期绑定库并删除所有特定引用。到目前为止,这似乎是处理它的最佳方法。为了发布,我将库切换到后期绑定版本。到目前为止,这似乎是在程序中保持尽可能多的编译时间检查的好方法,到目前为止,这是相当少量的额外工作,尽管它也很烦人。

我找到了解决自己问题的方法。

我所做的是注册 COM 组件的每个版本并重新生成我的项目。这导致 .NET 为 COM 组件创建互操作库。

然后,我将新的"interop.component.dll"复制到一个子目录中,在那里我将其重命名为"Version1.Component.dll"

重复这些步骤,直到创建所有 4 个互操作库,例如

  • "版本1.组件.dll"
  • "版本2.组件.dll"
  • "版本3.组件.dll"
  • "版本4.组件.dll"

将每个资源标记为主 DLL 中的嵌入资源

在引用中为 COM 库设置"复制本地 = FALSE"。现在,当在代码中请求组合类时,当 .NET 尝试按需加载互操作库时,这将找不到互操作库。

在主 DLL 的模块中,我添加了以下代码...

Public WithEvents CurDomain As AppDomain = AppDomain.CurrentDomain
Private Function AssemblyResolve(sender As Object, args As System.ResolveEventArgs) As System.Reflection.Assembly Handles CurDomain.AssemblyResolve
Dim resourceName As String = New Reflection.AssemblyName(args.Name).Name & ".dll"
Dim curAsm As Reflection.Assembly = Reflection.Assembly.GetExecutingAssembly
If resourceName.EndsWith("Component.dll") Then
    'supply the correct resource
    resourceName = ver & "." & resourceName  ' ver is set to the currently desired version.
    Using stc As IO.Stream = curAsm.GetManifestResourceStream(resourceName)
        Dim bt(CInt(stc.Length - 1)) As Byte
        stc.Read(bt, 0, CInt(stc.Length))   'get to a new byte array
        Return Reflection.Assembly.Load(bt) 'load actual assembly from decompressed stream data.
    End Using
End If
End Function

每当 .NET 无法解析允许您手动提供 DLL 时,就会触发上述代码。

现在,互操作库的所有 4 个略有不同的版本都将与计算机上注册的任何版本的 COM 组件一起使用。

最新更新