遗憾的是,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组件,因此您的里程可能会发生变化!