当前位置 : 主页 > 编程语言 > c语言 >

VB.NET嵌入式DLL在另一个DLL中作为嵌入式资源?

来源:互联网 收集:自由互联 发布时间:2021-06-24
我已经在C#中看到了这一点,比如 here,虽然我似乎无法弄清楚如何在VB.NET中做到这一点.对于某些背景,我创建了一个自定义ComboBox控件作为.dll,我需要在另一个.dll(ArcMap组件)中实现它. 遗憾
我已经在C#中看到了这一点,比如 here,虽然我似乎无法弄清楚如何在VB.NET中做到这一点.对于某些背景,我创建了一个自定义ComboBox控件作为.dll,我需要在另一个.dll(ArcMap组件)中实现它.

遗憾的是,ArcMap不允许将“第三方”DLL与组件一起加载,因为没有选项可以为您的加载项引用任何第三方程序集.

如果有人能指出我正确的方向,那将是非常值得赞赏的.

我们在Visual Studio 2008中的VB.NET中使用这种技术…

首先,项目需要知道将“其他”dll包含为嵌入式资源.在解决方案资源管理器中,将dll作为文件添加到项目中(而不是作为参考).然后,打开文件的“属性”,并将“构建操作”设置为“嵌入式资源”.建议您在项目结构中创建dll文件的本地副本,而不是链接到其他位置.一旦项目包含dll文件,您就可以添加对该dll副本的引用,以便您可以在设计时使用其内容.

这确保了“其他”dll包含在已编译的dll中,但它不会在需要时自动加载.这就是以下代码的来源:

Public Module Core

Private _initialized As Boolean

Public Sub EnsureInitialized()
  If Not _initialized Then
    AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf AssemblyResolve
    _initialized = True
  End If
End Sub

Private Function AssemblyResolve(ByVal sender As Object, ByVal e As ResolveEventArgs) As Assembly
  Dim resourceFullName As String = String.Format("[CONTAINER ASSEMBLY].{0}.dll", e.Name.Split(","c)(0))
  Dim thisAssembly As Assembly = Assembly.GetExecutingAssembly()
  Using resource As Stream = thisAssembly.GetManifestResourceStream(resourceFullName)
    If resource IsNot Nothing Then Return Assembly.Load(ToBytes(resource))
    Return Nothing
  End Using
End Function

Private Function ToBytes(ByVal instance As Stream) As Byte()
    Dim capacity As Integer = If(instance.CanSeek, Convert.ToInt32(instance.Length), 0)

    Using result As New MemoryStream(capacity)
        Dim readLength As Integer
        Dim buffer(4096) As Byte

        Do
            readLength = instance.Read(buffer, 0, buffer.Length)
            result.Write(buffer, 0, readLength)
        Loop While readLength > 0

        Return result.ToArray()
    End Using
End Function

End Module

将此模块放在项目中的某个位置,并确保在调用dll中的任何其他代码之前调用EnsureInitialized方法来附加AssemblyResolve处理程序.

注意:您需要将[CONTAINER ASSEMBLY]替换为您的dll名称.

另请注意,上面的代码是我们实际使用的精简版本,因为我们在战略位置包含log4net日志消息.记录消息对于真正的功能不是必需的,因此为了简洁和清晰起见,我删除了它们.

这种方法的主要警告是必须手动附加AssemblyResolve处理程序.即使您无法进行设置以便在初始化消费代码期间仅调用一次EnsureInitialized,您也可以在任何需要“其他”dll执行的模块中调用EnsureInitialized.这使得代码更加精细,因为你必须记住进行初始化调用,但它确实允许你在晚上睡觉,因为知道dll在你需要的时候可用.

根据我的经验,当一些“其他”dll作为嵌入式资源提供时,它们不能很好地运行,所以你可能需要玩一些才能让事情发挥作用.

最后注意:我从未使用过ArcMap组件,因此您的里程可能会发生变化!

网友评论