You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何类库中引用的外部DLL仍需在调用项目中添加?

问题分析

你遇到的核心问题是:即使将继承外部类的类型设为Friend/Private,.NET运行时在实例化该类型时,仍需加载其基类所在的外部程序集。这是因为.NET的类型系统要求,创建子类实例时必须解析并加载所有父类的程序集,无论子类的访问修饰符是什么。

解决方案

方案1:用适配器模式彻底隔离外部依赖(推荐)

不要让封装类直接继承外部类,而是在内部持有外部类的实例,通过委托调用其方法。这样外部程序集的依赖会被完全封装在类库内部,调用方无需引用或部署它。

修改后的代码示例:

Public Class MyCaller
    Public Shared Function UserLogin(ByVal username As String, ByVal password As String) As Boolean
        Return MyFunctions.Instance.UserLogin(username, password)
    End Function
End Class

Imports ExternalLibrary

Friend Class MyFunctions
        Private Shared instanceField As MyFunctions = Nothing
        ' 内部持有外部类实例,不对外暴露
        Private ReadOnly _externalService As ExternalClass

        Friend Shared ReadOnly Property Instance As MyFunctions
            Get
                If instanceField Is Nothing Then
                    instanceField = New MyFunctions()
                End If
                Return instanceField
            End Get
        End Property

        ' 私有构造函数,确保仅内部实例化
        Private Sub New()
            _externalService = New ExternalClass()
        End Sub

        Public Function UserLogin(ByVal username As String, ByVal password As String) As Boolean
            ' 将调用委托给外部类方法
            Return _externalService.UserLogin(username, password)
        End Function
End Class

方案2:将外部程序集嵌入类库(适用于必须继承外部类的场景)

如果因业务需求必须继承外部类,可以把外部DLL嵌入到类库的资源中,在运行时动态加载,避免调用方部署该DLL。

步骤如下:

  1. 将ExternalLibrary.dll添加到类库项目,设置:
    • 复制到输出目录:不复制
    • 生成操作:嵌入的资源
  2. 在封装类的静态构造函数中添加动态加载逻辑:
Imports System.Reflection
Imports ExternalLibrary

Friend Class MyFunctions
    Inherits ExternalClass

    ' 静态构造函数,在类第一次被访问时加载外部程序集
    Shared Sub New()
        ' 替换为你的类库命名空间,确保资源名称正确
        Dim resourceName = "YourClassLibraryNamespace.ExternalLibrary.dll"
        Using stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)
            Dim assemblyBytes = New Byte(stream.Length - 1) {}
            stream.Read(assemblyBytes, 0, assemblyBytes.Length)
            Assembly.Load(assemblyBytes)
        End Using
    End Sub

    ' 其余原有代码保持不变...
    Private Shared instanceField As MyFunctions = Nothing
    Friend Shared ReadOnly Property Instance As MyFunctions
        Get
            If instanceField Is Nothing Then
                instanceField = New MyFunctions()
            End If
            Return instanceField
        End Get
    End Property

    Public Function UserLogin(ByVal username As String, ByVal password As String) As Boolean
        Return MyBase.UserLogin(username, password)
    End Function
End Class
关键原理说明

.NET运行时在创建对象实例时,会递归解析该类型的所有基类、接口及依赖类型,并加载对应的程序集。即使子类是Friend/Private,只要在调用方进程中被实例化,就必须能找到基类所在的程序集——这就是你之前方案失败的根本原因。

内容的提问来源于stack exchange,提问作者Farhan Iqbal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 08:26:08