動態加載內嵌類庫文件的方法

有時候咱們引用了一個小型的類庫文件,可是若是發佈程序,就須要帶一個類庫文件,感受有點累贅,那該怎麼辦?
一些第三方的混淆工具自帶類庫集成,是一個不錯的解決辦法。
可是若是我只想使用本身的解決方法,那麼能夠嘗試將類庫文件以資源嵌入的方式,集成入程序集內!工具

可是我在測試這個辦法的時候,常常會發現程序沒法正確加載類庫。
以下面的代碼,實際上每次在執行時都會發生錯誤:測試

Sub Main()

    Dim dllName As String = "程序命名空間.類庫文件.dll"
    Dim dllStream As IO.Stream = Reflection.Assembly.GetEntryAssembly.GetManifestResourceStream(dllName)

    Dim dllbytes(dllStream.Length - 1) As Byte
    dllStream.Read(dllbytes, 0, dllStream.Length)
    dllStream.Close()

    Reflection.Assembly.Load(dllbytes)

    Application.EnableVisualStyles()
    Application.Run(New Main)

End Sub

 

當執行以上代碼,程序能夠正確加載位於程序集內部的類庫文件,在啓動時不會發生任何錯誤。
可是當咱們在窗體內執行類庫內的代碼,就會發生沒法引用類庫的錯誤。
究竟錯在了哪裏?讓我百思不得其解。google


後來我google了一下問題緣由,發現.NET程序並非在使用時纔開始解析並生成本地代碼,而是在以前就已經生成了各類對象的引用指針。
可是在引用時,若是發現對象並不存在,則會引起一個 AppDomain.AssemblyResolve 事件,所以能夠經過 AssemblyResolve 來在發生類庫引用錯誤時,動態地返回類庫程序集實例。spa

因此咱們只須要將加載事件改動到 AssemblyResolve 中就能夠了。ssr

Sub main()
    AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf assresolve

    Application.EnableVisualStyles()
    Application.Run(New Form1)
End Sub

Private Function assresolve(ByVal sender As Object, ByVal args As ResolveEventArgs) As Assembly
    Dim aName As String = New Reflection.AssemblyName(args.Name).FullName
    If aName = "類庫完整描述名" Then
        Dim dllName As String = "程序命名空間.類庫文件.dll"
        Dim dllStream As IO.Stream = Reflection.Assembly.GetEntryAssembly.GetManifestResourceStream(dllName)
        Dim dllbytes(dllStream.Length - 1) As Byte
        dllStream.Read(dllbytes, 0, dllStream.Length)
        dllStream.Close()
        Return Reflection.Assembly.Load(dllbytes)
    End If

    Return Nothing
End Function

這樣,當加載類庫發生錯誤之時,就會自動的加載內嵌的DLL文件到程序中。指針

相關文章
相關標籤/搜索