[英]Supporting multiple versions of NuGet package in one library / NuGet package
我希望我的库能够使用一系列版本的 NuGet 包,并在这些更改之间对 API 进行重大更改。 我没有进一步调查,但这条路看起来很有希望:
虽然这看起来很复杂,但与在单独的程序集中支持每个版本的更直接的方法相比,它有很多好处:
但是,目前尚不清楚这是否可能。 甚至在使用代理和检测当前版本之前,我都坚持使用基础知识。
我什至无法将多个PackageReference
节点添加到 my.csproj,实际上只有一个引用有效。 有一种解决方法可以添加 NuGet 不直接支持的外部别名,但我无法做到这一点,因为我无法获得两个引用。 如果我以某种方式得到两个,我将无法区分它们。
我正在使用 CsConsoleFormat 库来格式化控制台输出。 我想直接支持流行的命令行包的所有相关版本,这样漂亮的命令行帮助和类似的东西几乎不需要编码就可以添加,不管使用什么命令行解析库。
我想声明“我只支持最新版本”在我的情况下是可以接受的,但我宁愿得到更广泛的支持,即使它更复杂。 理想情况下,我想要一个 NuGet 包,它声明对最低支持版本的依赖,但支持最新版本的所有内容。
我有点让它工作,但有很多问题。 有关详细信息,请参阅GitHub NuGet 主页上的问题。
如果您坚持使用外部别名 - 您可以直接添加多个版本引用,作为 dll 文件,而不是作为 nuget 包。
假设我想依赖 Newtonsoft.Json 包版本 10.0.3+。 但是,如果用户安装了版本 11 - 我想使用仅在此版本 (11) 中可用的通用JsonConverter<T>
类。 然后我的 csproj 可能看起来像这样:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Version>1.0.4</Version>
</PropertyGroup>
<ItemGroup>
<!-- Nuget reference -->
<!-- Only this one will be included as dependency to the packed nuget -->
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
</ItemGroup>
<ItemGroup>
<!-- Direct reference to the specific version -->
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
<!-- Path to v11 dll -->
<HintPath>Newtonsoft.Json.v11.dll</HintPath>
<Aliases>js11</Aliases>
<SpecificVersion>true</SpecificVersion>
</Reference>
</ItemGroup>
</Project>
然后我有代理接口:
public interface ISerializer {
string Serialize<T>(T obj);
}
还有两个实现,v10(使用全局的、非别名的命名空间):
using System;
using global::Newtonsoft.Json;
namespace NugetRefMain {
internal class Js10Serializer : ISerializer
{
public string Serialize<T>(T obj)
{
Console.WriteLine(typeof(JsonConvert));
return JsonConvert.SerializeObject(obj);
}
}
}
和 v11
extern alias js11;
using System;
using js11::Newtonsoft.Json;
namespace NugetRefMain {
internal class Js11Serializer : ISerializer {
public string Serialize<T>(T obj) {
// using JsonConverter<T>, only available in v11
Console.WriteLine(typeof(JsonConverter<T>));
return JsonConvert.SerializeObject(obj);
}
}
}
最后是根据当前可用的 json.net 版本创建序列化程序的工厂:
public static class Serializers {
public static ISerializer Create() {
var version = typeof(JsonConvert).Assembly.GetName().Version;
if (version.Major == 10)
return new Js10Serializer();
return new Js11Serializer();
}
}
现在,如果我将其打包为 nuget - 它将对Newtonsoft.Json
版本10.0.3
具有单一依赖性,仅此而已。 但是,如果用户安装版本 11 的Newtonsoft.Json
- 它将使用此版本中可用的功能。
缺点:
Visual Studio \ Resharper intellisense 有时不喜欢这种方法,并且在实际上一切都编译得很好时显示 intellisense 错误。
您可能会在编译时收到“版本冲突”警告。
NuGet 仅解析单个包版本。
如果你声明对最低支持版本的依赖,任何引用项目都可以将依赖升级到更新的版本。
只要依赖包的作者不引入重大更改,它就应该可以找到。
即使您使用反射查看实际使用的程序集版本,您也会发现许多包作者不会在发布之间更改程序集版本。 这是为了避免在经典 .NET Framework 项目中绑定重定向的需要,因为所有版本都相同,并且 NuGet 将根据使用项目的已解析包版本选择正确的 DLL。 同样,只要没有重大变化,这就很好。
您可以用来支持不同包的模式是提供许多消费者可以从中选择的“平台”包。 然后,特定于平台的包将引用具有可共享逻辑的通用包。
“平台”将是例如“MyLogic.XUnit”或“MyLogic.NUnit”(假设以测试助手为例)引用“MyLogic.Common”
这不是一个完整的答案,但我在您的GitHub 问题页面上注意到您在项目中引用了 .NET Standard 和 .NET Framework 库。 已知这无法正常工作。
引用 .NET Standard 团队的公告,
.. 另一个症状是在构建时关于程序集版本的警告..
这可能是你遇到的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.