Мы используем этот метод в VB.NET в Visual Studio 2008 ...
Во-первых, проект должен знать, чтобы включить «другой» 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
Места этого модуль где-то в вашем проекте и обязательно вызвать метод EnsureInitialized
, чтобы приложить AssemblyResolve
обработчика перед тем вызова любой другой код в вашей библиотеке DLL.
ПРИМЕЧАНИЕ. Вам необходимо заменить [CONTAINER ASSEMBLY] на имя вашей DLL.
Также обратите внимание, что приведенный выше код является урезанной версией того, что мы на самом деле используем, потому что наша система включает log4net протоколирование сообщений в стратегических местах. Журнальные сообщения не нужны для истинной функциональности, поэтому я удалил их для краткости и ясности.
Основная оговорка к этому подходу заключается в том, что обработчик AssemblyResolve
должен быть подключен вручную. Даже если вы не можете настроить так, чтобы EnsureInitialized
вызывается только один раз во время инициализации кода потребления, вы можете вызвать EnsureInitialized
в любом из ваших собственных модулей, для выполнения которого требуется «другая» dll. Это делает код немного более тонким, потому что вы должны помнить, чтобы сделать этот вызов инициализации, но он позволяет вам спать по ночам, зная, что DLL будет доступна, когда вам это нужно.
По моему опыту, некоторые «другие» DLL-устройства плохо воспроизводятся, когда они предусмотрены как встроенные ресурсы, поэтому вам может понадобиться немного поиграть, чтобы заставить все работать.
Заключительное примечание: я никогда не использовал компонент ArcMap, поэтому ваш пробег может варьироваться!
TLS, спасибо. Я обнаружил некоторые странные ошибки в коде, который вы предоставили. «FormatWith» не является членом System.String, «First» не является членом System.Array, а «ToBytes» не является членом System.IO.Stream. Любые идеи, что я мог бы заменить этими функциями? –
Извините! Я очистил его, но не пошел достаточно далеко. В нашем коде есть некоторые методы расширения, которые я забыл перевести обратно в стандартные методы. Я обновил код и добавил определение «ToBytes», чтобы завершить этот пример. – TLS
Мой ответ по существу является конверсией [этого ответа C#] (http://stackoverflow.com/a/97290/475820). Я вижу это после рассмотрения этого ответа после размещения моего. Теперь у нас есть C# и версия VB! – TLS