0

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

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

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

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

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

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

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

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

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

4

1 回答 1

0

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

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

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

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

  • “版本 1.Component.dll”
  • “版本 2.Component.dll”
  • “版本 3.Component.dll”
  • “版本 4.Component.dll”

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

在 References 中为 COM 库设置 Copy Local = 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 组件一起使用。

于 2013-04-17T17:54:36.460 回答