在core之前,要使一个项目支持多个Frame版本,那么可行的办法就是创建多个版本的项目,然后以一个项目为主体,其它版本以添加--现有项--添加为链接的方式将代码文件添加到对应版本中,如果代码不同,则需要使用#if标签,而在core之后,如果需要发布多版本,可以不再需要创建多个项目,这里以VS2017为例
首先我们创建一个项目,可以是Standard类库,也可以是Core应用,这里我选择创建一个Standard类库,新建后的项目大致如下
在VS的解决方案管理器中选择项目,然后右键,点击 编辑StandardMultiTargetsDemo.csproj
这时可以打开csproj的编辑界面,默认信息如下
netstandard2.0
可以看到当前类库默认为netstandard2.0,而此时其xml标签为TargetFramework,比我们标题中的单词少了个s,表示当前项目只支持netstandard2.0,而我们现在稍作调整,将csproj文件的配置信息改为如下,表示支持netstandard2.0以及net40,注意现在是TargetFrameworks
netstandard2.0;net40
改完后,切记点击保存按钮,这时会跳出一个确定对话框
点击“全部重载”,VS会自动关闭csproj编辑界面,然后手快眼快的话,可以看到项目依赖项那里会有感叹号,再稍等一个会,感叹号会消失,这时在“解决方案管理器”中点开依赖项,可以看到当前项目以及支持多版本
此时生成项目,我们就可以在对应目录下看到有多个版本输出
好了目前我们已经可以多版本输出,但实际情况下,我们还需要解决以下问题
1、条件编译符
2、引用
3、Nuget
4、XML文档输出
5、DEBUG
这时我们再打开csproj编辑界面,添加如下语句
NETFULL
这表示在net40中,我定义了一个自定的条件编译符NETFULL,当然默认的条件编译符NET40还是有效的,如果你还需要定义其它条件编译符,切记多个条件编译符需以冒号(;)分割
下面我们开始添加引用,点击项目,然后添加引用,这时如果你完全按照前面的步骤,那么会打开如下界面
这是netstandard2.0时的引用界面,当然这时你点击项目属性时,打开的也都是netstandard2.0相关的配置信息,那要如何才能添加net40的引用呢?据说有个版本切换的选项,但我没找到,所以我采用下面的笨方式
回到csproj编辑界面,我们将TargetFrameworks里的版本先后顺序调整下,调整后的配置如下(记得保存)
net40;netstandard2.0;
此时新打开的界面就是net4.0的引用界面,这里我们选择System.Net这个dll,点击“确定”后,此时注意依赖项部分,可以看到出现了一个感叹号,展开会看到在netstandard2.0上出现了感叹号,表示netstandard2.0并不知道System.Net是什么东东,这时我们继续回到csproj界面,这时我们会看到配置文件里多了如下配置
这样表示net40和netstand2.0都需要System.Net引用,而实际只有net40才需要该引用,所以这里我们要使用Condition
这表示只有net40才符合条件,保存后你会发现依赖项那边的感叹号消失了
2019-08-23补充:之前一直忘了补充如何通过标签切换版本,补充下截图,如下图左上侧
好了上面是添加程序集引用,本地引用的方式与程序集方式类同,这里就不再描述,下面是通过nuget添加引用
首先我们先下载一个多版本都支持的类库,NLog(好吧,我终于发现NLog最新对netstandard2.0支持的dll已经是RC3版本了),在地址栏中打开https://www.nuget.org/packages/NLog/4.5.0-rc03#,选择你喜欢的方式进行引用的添加,这里我选择PM方式,添加完后csproj会多出如下配置
注意这里是PackageReference,而之前程序集的是Reference,而且我们也会发现在VS解决方案管理器中并没有出现packages.config文件,好吧,这是core开始nuget的新的管理方式,不再像以前默认在sln文件的同级创建一个packages文件夹,而是将dll下载到了C:\Users\当前登录用户\.nuget目录下,与java的Maven类似
注意图中.m2即为maven的默认配置下载位置
好了下面我们再添加一个netstandard专有的nuget引用https://www.nuget.org/packages/Microsoft.Extensions.DependencyInjection/,添加完后csproj会多出如下配置
2.0.0
好吧nuget很智能,自动帮你把Condition给加好了,而默认加的配置其实可以调整下,Version可以是Attribute方式添加,这在我们手动修改配置时会方便很多
下面我们开始设置XML文件输出,选择项目,点击 属性--生成,勾选 “XML 文档文件”
保存后csproj会自动多出如下配置
bin\Debug\netstandard2.0\StandardMultiTargetsDemo.xml
这表示netstandard2.0会生成xml文件,将该配置信息复制一份,然后修改Platform以及输出路径为net40
bin\Debug\net40\StandardMultiTargetsDemo.xml
这样net40也可以生成xml文件,当然这里可能也有其它更方便的设置方式,但目前我还不知道……
2018-02-27更新,输出xml文件可以通过下面的配置,就不用上面那种一个个的写法了
bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml
好了,最后是我们的重头戏,DEBUG,毕竟任何编码都离不开DEBUG,我们先在Class1(希望你还没删掉它……)文件中添加如下语句
#if NETFULL
int number;
#else
string number;
#endif
因为我们目前默认是netstandard2.0,所以你会在编辑界面看到如下效果
好吧,另几个参数是在添加引用时做测试的,上面忘记说了,反正也不是什么大事,不是么……
那如何测试net40呢,其实跟前面添加程序集引用时的步骤一样,将net40写到最前面即可,但VS中有个不靠谱的地方(不知道是不是bug),那就是虽然你目前是net40,但在VS编辑界面中,你看到的还是上图那样,NETFULL这个net40标签内的代码还是灰色的,而且你任何操作也不会有智能感知,这明显是很糟的用户体验,所以在这里告诉大家最后一个大招,再设置TargetFramework,注意没s后缀!!!修改后的配置如下
net40
保存并重新加载后,再打开Class1,这是你会看到下图效果
好了,从如何配置到最后的如何DEBUG这里都已经讲完了,剩下的就是各位实际操作一次实验下了。
最后完整的配置文件如下
net40
NETFULL;NET
bin\Debug\netstandard2.0\StandardMultiTargetsDemo.xml
bin\Debug\net40\StandardMultiTargetsDemo.xml
好吧,这里还隐藏了最后一样东西,各位自己注意吧,不过找出了可没奖品 :P
补充个TargetFrameworks的支持链接:https://docs.microsoft.com/en-us/dotnet/standard/frameworks