.NET 类库开发详细指南c_dotnet publish includeallcontentforselfextract

文章目录
- .NET DLL 引用所有依赖进行生成的可行方案
 - 
- 1. 使用 .NET 原生单文件发布 (推荐)
 - 
- 实现步骤:
 - 特点:
 
 - 2. 使用 ILMerge (传统 .NET Framework)
 - 
- 实现步骤:
 - 特点:
 
 - 3. 使用 Fody/Costura (嵌入依赖为资源)
 - 
- 实现步骤:
 - 特点:
 
 - 4. 使用 .NET 的 AssemblyLoadContext (高级方案)
 - 各方案比较
 - 最佳实践建议
 - 疑难解答
 
 
 
 
开发步骤
1. 创建项目
dotnet new classlib -n MyLibrary
或使用 Visual Studio 创建类库项目
2. 项目结构规划
MyLibrary/├── src/ # 主代码├── tests/  # 单元测试├── samples/ # 使用示例└── docs/  # 文档
3. 编写代码
- 设计清晰的命名空间结构
 - 遵循单一职责原则
 - 添加适当的XML文档注释
 
///  /// 提供数据处理功能/// public class DataProcessor{ ///   /// 处理输入数据 ///  /// 输入字符串 /// 处理后的结果 public string Process(string input) { return input.ToUpper(); }}
4. 添加依赖
- 通过NuGet包管理器添加必要依赖
 - 尽量保持依赖最少化
 
dotnet add package Newtonsoft.Json
5. 编写单元测试
创建测试项目并添加引用:
dotnet new xunit -n MyLibrary.Testsdotnet add MyLibrary.Tests reference MyLibrary
6. 配置项目文件
编辑.csproj文件,添加必要元数据:
<Project Sdk=\"Microsoft.NET.Sdk\"> <PropertyGroup> <TargetFramework>net8.0</TargetFramework> <GeneratePackageOnBuild>true</GeneratePackageOnBuild> <PackageId>MyCompany.MyLibrary</PackageId> <Version>1.0.0</Version> <Authors>Your Name</Authors> <Description>A useful library for data processing</Description> </PropertyGroup></Project>
7. 构建和打包
dotnet builddotnet pack
注意事项
1. API设计原则
- 保持API简洁一致
 - 遵循最小惊讶原则
 - 提供适当的默认值
 - 考虑向后兼容性
 
2. 版本控制
- 遵循语义化版本控制(SemVer)
 - 重大变更需要主版本号升级
 - 公共API变更要谨慎
 
3. 文档
- 为所有公共成员添加XML文档注释
 - 考虑提供README和使用示例
 - 记录重大变更和迁移指南
 
4. 性能考虑
- 避免不必要的内存分配
 - 考虑提供异步API
 - 对大对象实现IDisposable
 
5. 安全性
- 验证输入参数
 - 处理敏感数据时要小心
 - 考虑提供安全审计文档
 
6. 跨平台兼容性
- 避免使用平台特定API
 - 在不同OS上测试
 - 使用.NET Standard以获得最大兼容性
 
打包依赖到DLL
1. 独立部署 (Self-contained deployment)
可以将依赖打包到单个DLL中:
<PropertyGroup> <PublishSingleFile>true</PublishSingleFile> <SelfContained>true</SelfContained> <RuntimeIdentifier>win-x64</RuntimeIdentifier></PropertyGroup>
2. IL合并工具
使用工具如ILMerge或Fody.Costura将所有依赖合并到主DLL中:
- 安装Fody.Costura:
 
dotnet add package Fodydotnet add package Costura.Fody
- 添加FodyWeavers.xml文件:
 
<Weavers> <Costura/></Weavers>
3. 注意事项
- 合并后的DLL可能增大体积
 - 某些许可证可能不允许合并
 - 调试可能变得更困难
 - 考虑使用.NET Core的\"单文件发布\"功能作为替代
 
最佳实践
- 强命名:考虑对库进行强命名以便在GAC中使用
 - 多目标框架:支持多个.NET版本
 
<TargetFrameworks>netstandard2.0;net6.0;net8.0</TargetFrameworks>
- CI/CD集成:设置自动化构建和测试
 - 代码分析:启用静态代码分析
 
<EnableNETAnalyzers>true</EnableNETAnalyzers>
- NuGet发布:考虑将库发布到NuGet以便广泛使用
 
通过遵循这些步骤和注意事项,您可以开发出高质量、可维护且易于使用的.NET类库。
.NET DLL 引用所有依赖进行生成的可行方案
在 .NET 中,将 DLL 及其所有依赖打包成一个独立文件有几种可行方案,以下是详细的实现方法:
1. 使用 .NET 原生单文件发布 (推荐)
这是 .NET Core 3.0+ 和 .NET 5+ 提供的官方解决方案。
实现步骤:
- 修改项目文件 (.csproj):
 
<PropertyGroup>  <PublishSingleFile>true</PublishSingleFile>  <IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>  <SelfContained>true</SelfContained>  <RuntimeIdentifier>win-x64</RuntimeIdentifier>  <EnableCompressionInSingleFile>true</EnableCompressionInSingleFile></PropertyGroup>
- 发布命令:
 
dotnet publish -c Release -r win-x64 --self-contained true
特点:
- 官方支持,兼容性好
 - 生成单个可执行文件(DLL 会被嵌入到 exe 中)
 - 可选择是否包含 .NET 运行时
 
2. 使用 ILMerge (传统 .NET Framework)
适用于 .NET Framework 项目。
实现步骤:
- 安装 ILMerge NuGet 包:
 
Install-Package ILMerge -Version 3.0.41
- 修改项目文件添加后期生成事件:
 
<Target Name=\"PostBuild\" AfterTargets=\"PostBuildEvent\"> <Exec Command=\""$(ILMergeConsolePath)" /out:"$(TargetDir)merged\\$(TargetName).dll" "$(TargetPath)" "$(TargetDir)*.dll" /targetplatform:v4 /internalize\" /></Target>
- 或在构建后手动运行:
 
ILMerge /out:merged.dll MyLibrary.dll Newtonsoft.Json.dll OtherDependency.dll
特点:
- 适用于 .NET Framework
 - 合并后可能遇到依赖冲突问题
 - 需要处理强名称程序集
 
3. 使用 Fody/Costura (嵌入依赖为资源)
将依赖 DLL 作为资源嵌入到主 DLL 中。
实现步骤:
- 安装 NuGet 包:
 
dotnet add package Fodydotnet add package Costura.Fody
- 添加 
FodyWeavers.xml文件: 
<Weavers> <Costura IncludeDebugSymbols=\"false\" DisableCleanup=\"false\" DisableCompression=\"false\" CreateTemporaryAssemblies=\"true\" IncludeAssemblies=\"*.dll\" ExcludeAssemblies=\"System.*;Microsoft.*\" /></Weavers>
特点:
- 运行时自动解压和加载依赖
 - 支持 .NET Core 和 .NET Framework
 - 不会真正合并 IL,只是嵌入资源
 
4. 使用 .NET 的 AssemblyLoadContext (高级方案)
手动控制程序集加载。
using System.Runtime.Loader;var resolver = new AssemblyDependencyResolver(Assembly.GetExecutingAssembly().Location);AssemblyLoadContext.Default.Resolving += (context, assemblyName) =>{ string assemblyPath = resolver.ResolveAssemblyToPath(assemblyName); if (assemblyPath != null) { return context.LoadFromAssemblyPath(assemblyPath); } return null;};
各方案比较
最佳实践建议
- 对于新项目:优先使用 .NET 的单文件发布功能
 - 必须生成纯DLL时:
- .NET Framework:ILMerge
 - .NET Core:Fody/Costura
 
 - 注意许可证问题:确保合并的第三方库允许这种操作
 - 测试兼容性:合并后在不同环境下充分测试
 
疑难解答
- 
依赖冲突:
- 使用 
Aliases解决同名程序集问题 - 考虑使用 
extern alias 
 - 使用 
 - 
强名称问题:
- 重新签名合并后的程序集
 - 使用 
-keyfile参数指定密钥 
 - 
性能问题:
- 单文件发布在首次运行时会有解压开销
 - 考虑预编译 NGEN 或 ReadyToRun
 
 
选择哪种方案取决于您的具体需求、目标框架和部署环境。


