我希望我的库能够使用各种版本的NuGet包,并在更改之间对API进行重大更改。我还没有进一步调查,但这条路看起来很有希望:
虽然这可能看起来很复杂,但它比在单独的程序集中支持每个版本的更直接的方法有很多好处:
然而,目前尚不清楚它是否可行。甚至在获得代理和检测当前版本之前,我就已经坚持了基础知识。
我甚至无法向我的.csproj添加多个PackageReference
节点,只有一个参考实际上有效。有一个workaround for adding extern aliases直接由NuGet支持,但我无法达到这一点,因为我无法获得两个引用。如果我以某种方式得到两个,我就无法区分它们。
我正在使用CsConsoleFormat库来格式化控制台输出。我想直接支持流行的命令行软件包的所有相关版本,这样无论使用什么命令行解析库,都可以添加相当多的命令行帮助和类似的东西,几乎不需要编码。
我想宣布"我只支持最新版本"在我的情况下有点可以接受,但即使它更复杂,我也会得到更广泛的支持。理想情况下,我想要一个NuGet包,它声明对最低支持版本的依赖,但支持最新版本的所有内容。
我有点工作,但有很多问题。有关详细信息,请参阅issue on GitHub NuGet Home。
答案 0 :(得分:4)
如果你坚持使用extern别名 - 你可以直接添加多个版本引用,如dll文件,而不是nuget包。
假设我想依赖于Newtonsoft.Json包10.0.3+版。
但是,如果用户安装了版本11,我想使用仅在此版本中可用的通用JsonConverter<T>
类(11)。然后我的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有时不喜欢这种方法,并且在实际上一切都编译得很好时会显示智能感知错误。
编译时可能会出现“版本冲突”警告。
答案 1 :(得分:3)
NuGet只解析单个软件包版本。
如果声明对最低支持版本的依赖性,则任何引用项目都可以将依赖项升级到较新版本。
只要依赖包的作者不引入重大更改,它应该可以找到。
即使您使用反射来查看所使用的实际程序集版本,您会发现许多程序包作者不会在发行版之间更改程序集版本。这是为了避免在经典.NET Framework项目中绑定重定向的需要,因为所有版本都相同,并且NuGet将根据使用项目的已解析包版本选择正确的DLL。同样,只要不存在重大变化,这就有好处。
您可以用来支持不同包的模式是提供许多消费者可以选择的“平台”包。然后,特定于平台的包将引用具有可共享逻辑的公共包。
然后,“平台”将是例如“MyLogic.XUnit”或“MyLogic.NUnit”(假设测试助手为例)引用“MyLogic.Common”
答案 2 :(得分:1)
这不是一个完整的答案,但我在你的GitHub issue page注意到你在项目中引用了.NET Standard和.NET Framework库。众所周知这是行不通的。
引用.NET标准团队的announcement,
..另一个症状是关于程序集版本的构建时警告。
这可能是你遇到的。