【问题标题】:Generate text file of public API of .NET library for versioning and compatibility tracking生成 .NET 库的公共 API 的文本文件,用于版本控制和兼容性跟踪
【发布时间】:2022-08-16 00:39:19
【问题描述】:

我维护了太多的 NuGet 包,我试图找到一个工具,为每个程序集生成公共 API 表面的纯文本文件(如构建后步骤)。每个命名空间、类、接口、结构、方法签名、成员、字段都是一行,全部按字母顺序排序。

每当我更改公共 API 表面时,更改 src/PublicAPIs.txt 文件会非常棒 - github diff 会立即向我显示我修改、删除或添加的内容,并且该文件对于跟踪 API 随时间的变化非常宝贵。

我认为,我不太可能意外暴露私有 API 或破坏现有 API。

我觉得这一定已经存在,我只是错过了什么?我知道 Telerik JustAssembly 用于基本的 .dll 比较,但我正在寻找能够自动将文件写入 git 存储库的东西,因此我不必记得打开工具,并且会弹出任何重大更改在我的正常工作流程中。

标签: c# .net system.reflection


【解决方案1】:

Microsoft 有几个可以在这里使用的工具:Microsoft.DotNet.ApiCompatMicrosoft.CodeAnalysis.PublicApiAnalyzers

Microsoft.CodeAnalysis.PublicApiAnalyzers

包含Microsoft.CodeAnalysis.PublicApiAnalyzers 的包引用将生成文本文件,以便轻松识别 API 中的重大更改。

OpenTelemetry 有一个使用different text files for different target frameworks 的例子

Microsoft.DotNet.ApiCompat

ApiCompat 也可用于测试两个 .NET 程序集之间的 API 兼容性。

不幸的是,this project is not on nuget.org 还没有,但它被用于各种 Microsoft 项目之外至少AutomapperOpenTelemetry

这是一个blog post,它对添加包做了一个很好的演练,我将简要总结一下,而不试图复制太多内容:

  1. .NET Core Tools nuget feed 添加到您的 nuget.config
  2. 为“Microsoft.DotNet.ApiCompat”添加包引用
  3. 添加对程序集先前主要版本副本的引用(或use a script 获取它)

    当您进行重大更改时,默认设置应该会导致构建损坏,但您可以通过 additional settings 更改此行为,例如可用的 BaselineAllAPICompatErroras Automapper has

【讨论】:

  • 这是一个非常有趣的工具。对于我的用例,我认为文本文件会更好。我确实进行了重大更改——我只需要了解它们,并以一种简单的方式在 git 历史中一目了然。
  • @LilithRiver 抱歉,我看到 ApiCompat 并认为它也处理了文本文件,我可能只是遗漏了一些东西......更新了推荐 Microsoft.CodeAnalysis.PublicApiAnalyzers 的答案,因为这似乎正是你正在寻找的
  • @Tim 这正是 AM 与 ApiCompat 一起工作的方式。
  • 感谢@LucianBargaoanu 指出这一点,你是绝对正确的。我已经更新了答案以指示改变该行为的特定属性。在这一点上,我认为这两种工具都应该起作用。
【解决方案2】:

为此,您应该考虑使用PublicApiGenerator NuGet 包。

它提供了一种非常简单的方法来生成包含来自一个或多个程序集的公共 API 的 string

以下示例(取自项目的 README)展示了如何使用该包创建一个在公共 API 更改时将失败的单元测试:

[Fact]
public void my_assembly_has_no_public_api_changes()
{
    var publicApi = typeof(Library).Assembly.GeneratePublicApi();

    var approvedFilePath = "PublicApi.approved.txt";
    if (!File.Exists(approvedFilePath))
    {
        // Create a file to write to.
        using (var sw = File.CreateText(approvedFilePath)) { }
    }

    var approvedApi = File.ReadAllText(approvedFilePath);

    Assert.Equal(approvedApi, publicApi);
}

上面的测试将迫使您在重大更改时重新生成已批准的 API,因此重大更改将是一个有意识的决定。

【讨论】:

    【解决方案3】:

    如果我理解正确,您只想检查 API 是否有重大更改并警告是否有。我建议对您的 API 使用 swagger,以便轻松探索 API。但它也可用于检查/测试重大更改:

    https://swagger.io/blog/api-development/using-swagger-to-detect-breaking-api-changes/

    例如:

    $ gem install swagger-diff
    $ wget https://raw.githubusercontent.com/swagger-api/swagger-spec/master/examples/v2.0/json/petstore-minimal.json
    
    $ wget https://raw.githubusercontent.com/swagger-api/swagger-spec/master/examples/v2.0/json/petstore-expanded.json
    
    $ swagger-diff petstore-minimal.json petstore-expanded.json
    

    所以你只需要在构建时保存 swagger 文件

    例如:https://medium.com/@woeterman_94/how-to-generate-a-swagger-json-file-on-build-in-net-core-fa74eec3df1

    如果您还没有使用 swagger:https://docs.microsoft.com/en-us/aspnet/core/tutorials/web-api-help-pages-using-swagger?view=aspnetcore-6.0

    希望这可以帮助 :)

    【讨论】:

    • 我们谈论的是 .NET 类、接口和成员,而不是 Web api 表面。我不认为招摇做 .dll 接口?
    • @LilithRiver > 你的权利:D 对不起,误解了这个问题
    【解决方案4】:

    为了满足这些 DLL 内容跟踪要求,您需要开发一个控制台应用程序,该应用程序需要在构建后 stepd 中调用,该应用程序需要包含以下例程:

    要读取托管 DLL,您可以遵循以下方法: Assembly.LoadFrom MethodUsing Reflection to load unreferenced assemblies at runtime in C#

    要读取非托管 DLL: Platform Invoke (P/Invoke)PInvoke.net

    在同一个控制台应用程序中,读取 DLL(s) 内容后,您可以使用以下方法编写这些内容:How to write to a text file (C# Programming Guide)

    我想就是这样。

    【讨论】:

    • 我知道如何构建这样的工具;但我正在寻找的是已经创建和优化的东西。
    【解决方案5】:

    ILSpyCmd 是我能找到的最接近的

    1. 是一个 CLI 工具,用于轻松进行构建后集成。
    2. 可以选择转储您想要的一些实体:

      -l|--list <entity-type(s)> Lists all entities of the specified type(s). Valid types: c(lass), i(nterface), s(truct), d(elegate), e(num)

      1. nuget package。但是,它是通过dotnet tool install -g 安装的,这应该与您所期望的有所不同。

      输出如下所示:

      正如您所看到的,它仍然缺少一些详细信息,例如类中的方法和字段,但是所有详细信息(方法签名、枚举成员等)都应该已经反编译为 ListContent() 方法中的 decompiler 对象987654329@。您可以克隆存储库,然后添加几行来遍历它并以您喜欢的格式打印。

    【讨论】:

      【解决方案6】:

      这是一个非常好的问题,首先让我分享一些有关 NuGet 包的背景知识,以及大致分为三个部分的功能:common, sender & receivers,您可以从各种 repo 提供商处轻松获得这些功能,请参见下面的图片。

      因此,我认为Webhooks 是专门构建的并且很好地服务于该目的,尤其是接收器和自定义接收器。如果我不是介于/寻找工作之间,我会很快模拟一些有趣的东西:)

      我推荐这个设计非常适合有两个原因,当我为免费的替代品做类似的事情时,1) 因为它们/Webhooks 是原生内置的,来自 Nuget Ref -> "...Nuget Receivers: 一组支持从其他人那里接收 WebHooks 的包..." 您可以通过简单的请求来利用该数据流。

      2) 现在,您可以在应用程序、lib 或一些 VSIX 存储库扩展中轻松处理您的 webhook。

      public class MyNugetApiChangesHandler : WebHookHandler
      {
          public MyNugetApiChangesHandler ()
          {
              // let them know
              this.Receiver = "PublicApisChanged";
          }
      
          public override Task ExecuteAsync(string generator, WebHookHandlerContext context)
          {
              CustomNotifications notifications = context.GetDataOrDefault<CustomNotifications>();
              foreach (var notification in notifications.Notifications)
              {
                  // parse out the text and raise out the handler
                  ...
              }
              return Task.FromResult(true);
          }
      }
      

      您还可以在下面观察允许您订阅各种 repos 的 dll 是已经可用给你。


      您可以直接从 Github 执行此操作


      您也可以使用Bitbucket 执行此操作

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-07-17
        • 1970-01-01
        • 2017-06-28
        • 2020-12-16
        • 2017-03-15
        • 1970-01-01
        • 2013-04-08
        • 2020-05-25
        相关资源
        最近更新 更多