.NET运行时获取类库信息

Intro

在我们向别的开源项目提 issue 的时候,可能经常会遇到别人会让我们提供使用的版本信息,如果别的开源项目类库集成了 source link,我们可以从程序集信息中获取到版本以及对应的 commit 信息,这样我们就可以直接找到对应版本的 commit 对应的代码版本,这样也就可以更加方便的了解对应源码了

那我们是不是也可以在运行时获取类库的 commit 信息呢,答案是肯定的.

Sample

我们集成了 source link 的话,在程序集信息中是可以获取到 git 相关的信息, source link 的单步调试也是基于此来扩展的调试时下载对应源文件的

这里是我集成了 source link 的一个开源项目,反编译 dll 的时候可以看到一些 git 相关的信息

.NET运行时获取类库信息

AssemblyInfomationVersion 中的信息由两部分组成,一部分是原始的 package 版本号,另外一部分是对应 commit hash,我们结合 RepositoryUrl 就可以很方便的找到对应的代码了

RepositoryUrl 则是在一个 AssemblyMetadata 的 attribute 中

Implement

我们可以定义一个 model 来表示程序集的信息,这样以后扩展起来也会更加的方便,示例如下:

public class LibraryInfo
{
    public required Version LibraryVersion { get; init; }
    public required string LibraryHash { get; init; }
    public required string RepositoryUrl { get; init; }
}

然后通过反射从程序集中获取程序集的信息

public static LibraryInfo GetLibraryInfo(Assembly assembly)
{
    Guard.NotNull(assembly);
    var assemblyInformation = assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>();
    var repositoryUrl = assembly.GetCustomAttributes<AssemblyMetadataAttribute>()
        .FirstOrDefault(x => nameof(LibraryInfo.RepositoryUrl).Equals(x.Key))?.Value ?? string.Empty;
    if (assemblyInformation is not null)
    {
        var informationalVersionSplit = assemblyInformation.InformationalVersion.Split('+');
        if (Version.TryParse(informationalVersionSplit[0], out var version))
        {
            return new LibraryInfo()
            {
                LibraryVersion = version,
                LibraryHash = informationalVersionSplit.Length > 1 ? informationalVersionSplit[1] : string.Empty,
                RepositoryUrl = repositoryUrl
            };
        }
    }
    return new LibraryInfo()
    {
        LibraryVersion = assembly.GetName().Version!,
        LibraryHash = string.Empty,
        RepositoryUrl = repositoryUrl
    };
}

为了使用方便添加一个根据类型获取的 overload

public static LibraryInfo GetLibraryInfo(Type type) => GetLibraryInfo(Guard.NotNull(type).Assembly);

More

使用 dotnet-exec  来测试一下

dotnet-exec 'ApplicationHelper.GetLibraryInfo(typeof(WeihanLi.Npoi.CsvHelper))' --reference "nuget:WeihanLi.Npoi,2.4.2"

.NET运行时获取类库信息

从输出结果我们可以看到我们已经拿到 commit hash 和 RepositoryUrl 信息了,对应的 Github commit 地址就是:https://github.com/WeihanLi/WeihanLi.Npoi/tree/8e2c1dee6efee9b7b4b12f16272f266c9ad09233

最后还是建议大家在自己开源类库项目中集成 source link,不仅方便调试,还可以比较方便准确的获取对应版本的 commit 信息,这样别人使用遇到问题的话也会比较方便的进行 debug 和查找源代码。