当前位置: 首页 > news >正文

使用基于 Roslyn 的 Microsoft.CodeAnalysis.PublicApiAnalyzers 来追踪项目的 API 改动,帮助保持库的 API 兼容性

做库的时候,需要一定程度上保持 API 的兼容性


本文内容

    • 第一步:安装 NuGet 包
    • 第二步:创建 API 记录文件
    • 第三步:添加 API 记录
    • 体验 API 的追踪
    • 将警告变成错误
    • 第四步:将 API 打包

第一步:安装 NuGet 包

首先打开你的库项目,或者如果你希望从零开始也可以直接新建一个项目。这里为了博客阅读的简单,我创建一个全新的项目来演示。

打开一个项目

然后,为主要的库项目安装 NuGet 包:

  • NuGet Gallery - Microsoft.CodeAnalysis.PublicApiAnalyzers

安装 NuGet 包

安装完成之后,你的项目文件(.csproj)可能类似于下面这样:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="2.9.3" />
  </ItemGroup>

</Project>

第二步:创建 API 记录文件

在你的项目内创建两个文件:

  • PublicAPI.Shipped.txt
  • PublicAPI.Unshipped.txt

创建 API 记录文件

这就是两个普通的文本文件。创建纯文本文件的方法是在项目上右键 -> 添加 -> 新建项...,然后在打开的模板中选择 文本文件,使用上面指定的名称即可(要创建两个)。

然后,编辑项目文件,我们需要将这两个文件加入到项目中来。

编辑项目文件

如果你看不到上图中的“编辑项目文件”选项,则需要升级项目文件到 SDK 风格,详见:

  • 将 WPF、UWP 以及其他各种类型的旧 csproj 迁移成 Sdk 风格的 csproj - walterlv

然后,将这两个文件添加为 AdditionalFiles

  <Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
      <TargetFramework>netstandard2.0</TargetFramework>
    </PropertyGroup>

    <ItemGroup>
      <PackageReference Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="2.9.3" />
    </ItemGroup>

+   <ItemGroup>
+     <AdditionalFiles Include="PublicAPI.Shipped.txt" />
+     <AdditionalFiles Include="PublicAPI.Unshipped.txt" />
+   </ItemGroup>

  </Project>

如果你把这两个文件放到了其他的路径,那么上面也需要改成对应的路径。

这时,这两个文件内容还是空的。

第三步:添加 API 记录

这个时候,你会看到库中的 public 类、方法、属性等都会发出修改建议,说此符号并不是已声明 API 的一部分。

类型

属性

点击小灯泡,即可将点击所在的 API 加入到 PublicAPI.Unshipped.txt 中。

我将两个 API 都添加之后,PublicAPI.Unshipped.txt 文件中现在是这样的(注意有一个隐式构造函数哦):

Walterlv.PackageDemo.ApiTracking.Class1
Walterlv.PackageDemo.ApiTracking.Class1.Class1() -> void
Walterlv.PackageDemo.ApiTracking.Class1.Foo.get -> string

体验 API 的追踪

现在,我们将 Foo 属性改名成 Foo2 属性,于是就会出现编译警告:

编译警告

RS0016 Symbol ‘Foo2.get’ is not part of the declared API.
RS0017 Symbol ‘Walterlv.PackageDemo.ApiTracking.Class1.Foo.get -> string’ is part of the declared API, but is either not public or could not be found

提示 Foo2 属性不是已声明 API 的一部分,而 Foo 属性虽然是已声明 API 的一部分,但已经找不到了。

这种提示对于保持库的兼容性是非常有帮助的。

将警告变成错误

在分析器的规则上面右键,可以为某项规则设置严重性。

将警告设置为错误

这时,再编译即会报告编译错误。

编译错误

项目中也会多一个规则集文件:

  <Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
      <TargetFramework>netstandard2.0</TargetFramework>
+     <CodeAnalysisRuleSet>Walterlv.PackageDemo.ApiTracking.ruleset</CodeAnalysisRuleSet>
    </PropertyGroup>

    <ItemGroup>
      <PackageReference Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="2.9.3" />
    </ItemGroup>

    <ItemGroup>
      <AdditionalFiles Include="PublicAPI.Shipped.txt" />
      <AdditionalFiles Include="PublicAPI.Unshipped.txt" />
    </ItemGroup>

  </Project>

第四步:将 API 打包

前面我们都是在 PublicAPI.Unshipped.txt 文件中追踪 API。但是如果我们的库需要发布一个版本的时候,我们就需要跟上一个版本比较 API 的差异。

上一个发布版本的 API 就记录在 PublicAPI.Shipped.txt 文件中,这两个文件的差异即是这两个版本的 API 差异。在一个新的版本发布后,就需要将 API 归档到 PublicAPI.Shipped.txt 文件中。


参考资料

  • roslyn-analyzers/Microsoft.CodeAnalysis.PublicApiAnalyzers.md at master · dotnet/roslyn-analyzers

我的博客会首发于 https://blog.walterlv.com/,而 CSDN 会从其中精选发布,但是一旦发布了就很少更新。

如果在博客看到有任何不懂的内容,欢迎交流。我搭建了 dotnet 职业技术学院 欢迎大家加入。

知识共享许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名吕毅(包含链接:https://walterlv.blog.csdn.net/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。

相关文章:

  • Visual Studio 2019 中使用 .NET Core 预览版 SDK 的全局配置文件在哪里?
  • 推荐几款连字字体,在代码编辑器中启用连字字体(Visual Studio Code)
  • 找回你 C 盘丢失的空间(SpaceSniffer)
  • System.InvalidOperationException:“寄宿 HWND 必须是子窗口。”
  • 通过 AppSwitch 禁用 WPF 内置的触摸让 WPF 程序可以处理 Windows 触摸消息
  • 如何为非常不确定的行为(如并发)设计安全的 API,使用这些 API 时如何确保安全
  • 通过 mklink 收集本地文件系统的所有 NuGet 包输出目录来快速调试公共组件代码
  • 设计一个 .NET 可用的弱引用集合(可用来做缓存池使用)
  • 使用 C# 中的 dynamic 关键字调用类型方法时可能遇到的各种问题
  • 程序员可能会使用的各种命名规则
  • System.InvalidOperationException:“BuildWindowCore 无法返回寄宿的子窗口句柄。”
  • System.InvalidOperationException:“寄宿的 HWND 必须是指定父级的子窗口。”
  • 在使用 .NET Remoting 技术开发跨进程通信时可能遇到的各种异常
  • 使用 SetParent 跨进程设置父子窗口时的一些问题(小心卡死)
  • System.ComponentModel.Win32Exception (0x80004005): 无效的窗口句柄。
  • java正则表式的使用
  • Js基础——数据类型之Null和Undefined
  • passportjs 源码分析
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • webpack项目中使用grunt监听文件变动自动打包编译
  • 产品三维模型在线预览
  • 官方新出的 Kotlin 扩展库 KTX,到底帮你干了什么?
  • 经典排序算法及其 Java 实现
  • 前端之Sass/Scss实战笔记
  • 微信小程序实战练习(仿五洲到家微信版)
  • 小程序开发中的那些坑
  • ​云纳万物 · 数皆有言|2021 七牛云战略发布会启幕,邀您赴约
  • #Linux杂记--将Python3的源码编译为.so文件方法与Linux环境下的交叉编译方法
  • (c语言)strcpy函数用法
  • (二)学习JVM —— 垃圾回收机制
  • (附源码)springboot学生选课系统 毕业设计 612555
  • (附源码)ssm高校升本考试管理系统 毕业设计 201631
  • (六)激光线扫描-三维重建
  • (十三)Java springcloud B2B2C o2o多用户商城 springcloud架构 - SSO单点登录之OAuth2.0 根据token获取用户信息(4)...
  • (四)【Jmeter】 JMeter的界面布局与组件概述
  • (五)Python 垃圾回收机制
  • ****Linux下Mysql的安装和配置
  • .cfg\.dat\.mak(持续补充)
  • .net core开源商城系统源码,支持可视化布局小程序
  • .NET Core中的去虚
  • .NET NPOI导出Excel详解
  • .net 使用ajax控件后如何调用前端脚本
  • .NET 应用架构指导 V2 学习笔记(一) 软件架构的关键原则
  • .NET6使用MiniExcel根据数据源横向导出头部标题及数据
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比
  • .net利用SQLBulkCopy进行数据库之间的大批量数据传递
  • .net之微信企业号开发(一) 所使用的环境与工具以及准备工作
  • .so文件(linux系统)
  • [23] GaussianAvatars: Photorealistic Head Avatars with Rigged 3D Gaussians
  • [30期] 我的学习方法
  • [383] 赎金信 js
  • [AIGC] SQL中的数据添加和操作:数据类型介绍
  • [C++]——带你学习类和对象
  • [codevs 1296] 营业额统计
  • [docker]docker网络-直接路由模式