如何将NuGet包嵌入公共类库DLL,避免客户端重复安装依赖?
可行方案(原生实现,无需外部工具)
方案1:嵌入依赖并通过AssemblyResolve加载(生成单个DLL)
这是原生实现单DLL合并的核心方法,步骤如下:
配置依赖项嵌入规则
在公共类库的.csproj文件中,对每个需要嵌入的NuGet依赖添加如下配置,确保依赖不会传递给客户端,同时被打包为嵌入资源:<ItemGroup> <!-- 示例配置Newtonsoft.Json --> <PackageReference Include="Newtonsoft.Json" Version="13.0.3"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> <!-- 其他依赖项重复上述配置 --> </ItemGroup> <!-- 将依赖DLL嵌入为资源 --> <ItemGroup> <EmbeddedResource Include="$(OutputPath)\Newtonsoft.Json.dll"> <LogicalName>Newtonsoft.Json.dll</LogicalName> </EmbeddedResource> <!-- 其他依赖DLL同理添加 --> </ItemGroup>注:
$(OutputPath)为项目输出目录,若路径不符可手动指定NuGet包内的DLL路径(如..\packages\Newtonsoft.Json.13.0.3\lib\net6.0\Newtonsoft.Json.dll)。添加自动加载逻辑
在公共类库中添加静态初始化类,通过AssemblyResolve事件捕获CLR的依赖加载请求,从嵌入资源中读取并加载依赖:using System; using System.Reflection; namespace YourCommonLibrary { public static class LibraryBootstrapper { static LibraryBootstrapper() { AppDomain.CurrentDomain.AssemblyResolve += ResolveEmbeddedAssembly; } private static Assembly? ResolveEmbeddedAssembly(object sender, ResolveEventArgs args) { var assemblyFileName = new AssemblyName(args.Name).Name + ".dll"; var resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(assemblyFileName); if (resourceStream == null) return null; using (resourceStream) { var assemblyBytes = new byte[resourceStream.Length]; resourceStream.Read(assemblyBytes, 0, assemblyBytes.Length); return Assembly.Load(assemblyBytes); } } } }客户端仅需引用你的公共类库DLL,无需安装任何依赖,依赖会在运行时自动从嵌入资源加载。
方案2:打包为包含所有依赖的NuGet包(客户端一键引用)
如果允许生成NuGet包而非单DLL,这是最符合.NET生态的简洁方案:
- 配置项目打包属性
在公共类库的.csproj中添加以下配置,将依赖项打包到NuGet包内,客户端安装时自动复制所有依赖到输出目录:<PropertyGroup> <PackageId>Your.Common.Library</PackageId> <Version>1.0.0</Version> <Authors>YourName</Authors> <Description>内置所有依赖的公共类库</Description> <GeneratePackageOnBuild>true</GeneratePackageOnBuild> <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> </PropertyGroup> <ItemGroup> <!-- 标记依赖为私有资产,不传递给客户端项目 --> <PackageReference Include="Newtonsoft.Json" Version="13.0.3"> <PrivateAssets>all</PrivateAssets> </PackageReference> <!-- 其他依赖项重复上述配置 --> </ItemGroup> - 打包分发
构建项目后,bin\Release目录会生成.nupkg文件。客户端只需通过NuGet安装该包,所有依赖DLL会自动同步到输出目录,无需手动安装任何依赖包。
方案3:手动同步依赖到输出目录(生成多个独立DLL)
若不需要单DLL,仅需避免客户端手动安装NuGet依赖,可采用此方案:
- 配置依赖自动复制
在公共类库的.csproj中设置依赖项复制到输出目录:<ItemGroup> <PackageReference Include="Newtonsoft.Json" Version="13.0.3"> <PrivateAssets>all</PrivateAssets> <CopyLocal>true</CopyLocal> </PackageReference> <!-- 其他依赖项重复上述配置 --> </ItemGroup> - 分发完整DLL集合
构建后,将输出目录下的所有DLL(你的类库+所有依赖DLL)一起分发给客户端。客户端只需引用你的主DLL,其余依赖DLL放在同一目录下即可自动加载,无需安装NuGet包。
注意事项
- 若依赖为强命名DLL,嵌入加载时需确保签名兼容,可选择使用同一密钥签名,或禁用依赖的强命名(若允许)。
- 方案1需覆盖所有直接和间接依赖,可通过查看项目输出目录确认需要嵌入的DLL清单。
- 方案2的NuGet包方式是最推荐的,既符合.NET包管理规范,又能最大程度简化客户端操作。
内容的提问来源于stack exchange,提问作者Miguel Mesquita Alfaiate
相关产品推荐
相关产品推荐

