C# 支持编译依赖项(vNext)的多个版本
我为目前支持MVC2-MVC5的开源库做了贡献,我还想支持MVC6(以及更高版本)。为了支持每个版本的MVC,我们利用MSBuild的特性,在进行构建时包括正确版本的MVC及其依赖项(取决于C# 支持编译依赖项(vNext)的多个版本,c#,asp.net-mvc,asp.net-core,roslyn,asp.net-core-mvc,C#,Asp.net Mvc,Asp.net Core,Roslyn,Asp.net Core Mvc,我为目前支持MVC2-MVC5的开源库做了贡献,我还想支持MVC6(以及更高版本)。为了支持每个版本的MVC,我们利用MSBuild的特性,在进行构建时包括正确版本的MVC及其依赖项(取决于DefineConstants)。通过使用相同的项目文件和源代码为每个MVC版本创建单独的DLL,可以对所有受支持的MVC版本使用单个项目文件 <ItemGroup Condition=" $(DefineConstants.Contains('MVC2')) "> <Referen
DefineConstants
)。通过使用相同的项目文件和源代码为每个MVC版本创建单独的DLL,可以对所有受支持的MVC版本使用单个项目文件
<ItemGroup Condition=" $(DefineConstants.Contains('MVC2')) ">
<Reference Include="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
</ItemGroup>
<ItemGroup Condition=" $(DefineConstants.Contains('MVC3')) ">
<!-- Due to the windows update MS14-059, we need this hack to ensure we can build MVC3 both on machines that have the update and those that don't -->
<Reference Condition=" Exists('$(windir)\Microsoft.NET\assembly\GAC_MSIL\System.Web.Mvc\v4.0_3.0.0.0__31bf3856ad364e35\System.Web.Mvc.dll') " Include="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
<Reference Condition=" !Exists('$(windir)\Microsoft.NET\assembly\GAC_MSIL\System.Web.Mvc\v4.0_3.0.0.0__31bf3856ad364e35\System.Web.Mvc.dll') " Include="System.Web.Mvc, Version=3.0.0.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.AspNet.Mvc.3.0.20105.1\lib\net40\System.Web.Mvc.dll</HintPath>
</Reference>
<Reference Include="System.Web.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.AspNet.Razor.1.0.20105.408\lib\net40\System.Web.Razor.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.AspNet.WebPages.1.0.20105.408\lib\net40\System.Web.WebPages.Razor.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup Condition=" $(DefineConstants.Contains('MVC4')) ">
<Reference Include="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.AspNet.Mvc.4.0.20710.0\lib\net40\System.Web.Mvc.dll</HintPath>
</Reference>
<Reference Include="System.Web.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.AspNet.Razor.4.0.20715.0\lib\net40\System.Web.Razor.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.AspNet.WebPages.4.0.20710.0\lib\net40\System.Web.WebPages.Razor.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup Condition=" $(DefineConstants.Contains('MVC5')) ">
<Reference Include="System.Web.Mvc, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.AspNet.Mvc.5.0.0\lib\net45\System.Web.Mvc.dll</HintPath>
</Reference>
<Reference Include="System.Web.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.AspNet.Razor.3.0.0\lib\net45\System.Web.Razor.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.0.0\lib\net45\System.Web.WebPages.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.0.0\lib\net45\System.Web.WebPages.Razor.dll</HintPath>
</Reference>
</ItemGroup>
真的
..\packages\Microsoft.AspNet.Mvc.3.0.20105.1\lib\net40\System.Web.Mvc.dll
真的
..\packages\Microsoft.AspNet.Razor.1.0.20105.408\lib\net40\System.Web.Razor.dll
真的
..\packages\Microsoft.AspNet.WebPages.1.0.20105.408\lib\net40\System.Web.WebPages.Razor.dll
真的
..\packages\Microsoft.AspNet.Mvc.4.0.20710.0\lib\net40\System.Web.Mvc.dll
真的
..\packages\Microsoft.AspNet.Razor.4.0.20715.0\lib\net40\System.Web.Razor.dll
真的
..\packages\Microsoft.AspNet.WebPages.4.0.20710.0\lib\net40\System.Web.WebPages.Razor.dll
真的
..\packages\Microsoft.AspNet.Mvc.5.0.0\lib\net45\System.Web.Mvc.dll
真的
..\packages\Microsoft.AspNet.Razor.3.0.0\lib\net45\System.Web.Razor.dll
真的
..\packages\Microsoft.AspNet.WebPages.3.0.0\lib\net45\System.Web.WebPages.dll
真的
..\packages\Microsoft.AspNet.WebPages.3.0.0\lib\net45\System.Web.WebPages.Razor.dll
我已经研究了ASP.NET 5/MVC 6的项目结构,并且已经放弃使用project.json
文件,而不是MVC 6的.csproj
文件。但是,我阅读了,似乎没有一种方法可以通过单个project.json
文件支持多个版本的MVC
MyProject.sln
// This is where the legacy MVC2-5 support goes
MyProject/
MyProject.csproj
MyProject.DNX.Debug.xproj
project.json
// This is where the MVC6 support is compiled from
MyProject.MVC6/
MyProject.MVC6.xproj
project.json
理想情况下,我希望放弃MSBuild
,在以后的每个MVC版本(包括MVC2-MVC5)中使用Roslyn
。但是有没有一种方法可以支持多个MVC版本,而不必为每个MVC版本创建一个项目文件(和项目目录,因为它们都必须命名为project.json
)呢?如果没有,是否有其他方法不必将所有project.json
配置复制5次?我找到了一个(不太好的)解决方法。我仍然想知道是否有更好的方法
我提出的解决方案是使用globbing来包含要在项目目录之外编译的文件。例如,我的项目结构如下所示:
MyProject.sln
// This is where the legacy MVC2-5 support goes
MyProject/
MyProject.csproj
// This is where the MVC6 support is compiled from
MyProject.MVC6/
MyProject.MVC6.xproj
project.json
{
"version": "1.0.0-*",
"description": "MyProject Description",
"dependencies": {
"Microsoft.AspNet.Mvc": "6.0.0-beta7",
"Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-beta7",
"Microsoft.AspNet.Routing": "1.0.0-beta7"
},
"compile": "../MyProject/**/*.cs",
"compilationOptions": {
"define": ["MVC6", "NET46"]
},
"frameworks": {
"dnxcore50": {
"dependencies": {
"Microsoft.CSharp": "4.0.1-beta-23225",
"System.Collections": "4.0.11-beta-23225",
"System.Linq": "4.0.1-beta-23225",
"System.Runtime": "4.0.21-beta-23225",
"System.Threading": "4.0.11-beta-23225"
}
}
}
}
所有.cs
文件都包含在MyProject
中。然后我的project.json
文件如下所示:
MyProject.sln
// This is where the legacy MVC2-5 support goes
MyProject/
MyProject.csproj
// This is where the MVC6 support is compiled from
MyProject.MVC6/
MyProject.MVC6.xproj
project.json
{
"version": "1.0.0-*",
"description": "MyProject Description",
"dependencies": {
"Microsoft.AspNet.Mvc": "6.0.0-beta7",
"Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-beta7",
"Microsoft.AspNet.Routing": "1.0.0-beta7"
},
"compile": "../MyProject/**/*.cs",
"compilationOptions": {
"define": ["MVC6", "NET46"]
},
"frameworks": {
"dnxcore50": {
"dependencies": {
"Microsoft.CSharp": "4.0.1-beta-23225",
"System.Collections": "4.0.11-beta-23225",
"System.Linq": "4.0.1-beta-23225",
"System.Runtime": "4.0.21-beta-23225",
"System.Threading": "4.0.11-beta-23225"
}
}
}
}
但是,此解决方案还有另一个问题-Visual Studio 2015不显示MyProject.MVC6
中的任何文件,因为它们仅用于编译。此外,不可能包含.csproj
文件,因为这会导致整个项目无法编译
因此,我提出了另一种解决方法-在实际项目中包含project.json
文件和MyProject.DNX.Debug.xproj
文件,并将其包含在MVC6解决方案中,而不是.csproj
文件中
MyProject.sln
// This is where the legacy MVC2-5 support goes
MyProject/
MyProject.csproj
MyProject.DNX.Debug.xproj
project.json
// This is where the MVC6 support is compiled from
MyProject.MVC6/
MyProject.MVC6.xproj
project.json
这些文件的作用只是提供一种在MVC6中调试它们的方法,其思想是当MVC7出现时,我将能够创建另一个项目文件夹,然后根据需要交换该配置以调试哪个版本
MyProject.sln
// This is where the legacy MVC2-5 support goes
MyProject/
MyProject.csproj
MyProject.DNX.Debug.xproj
project.json // This project will be swapped between MVC6 and MVC7 based on compilationOptions
// This is where the MVC6 support is compiled from
MyProject.MVC6/
MyProject.MVC6.xproj
project.json
// This is where the MVC7 support is compiled from
MyProject.MVC7/
MyProject.MVC7.xproj
project.json
这还远远不够理想。如果有,请提供更好的答案。您可以创建一个编译为多个运行时的项目,即.NET Core、.NET 4.5.1等
frameworks
元素下,可以输入多个框架。我的目标是.NET Core和.NET 4.5.1:
"frameworks": {
"dnx451": {
"frameworkAssemblies": {
"System.Net.Http": "4.0.0.0", // Example reference
}
},
"dnxcore50": {
"dependencies": {
"System.Net.Http": "4.0.1-beta-23225" // Example reference
}
}
}
public void Foo()
{
#if DNX451
// Code specific to .NET 4.5.1
#endif
}
这行不通(至少不像你有它)。我们正在为.NET 3.5、.NET 4.0和.NET 4.5编译一个单独的DLL,仅用于MVC2。MVC3和MVC4仅在.NET4.0和.NET4.5下编译,MVC5仅在.NET4.5下编译。我们有编译符号来逐步利用更新的特性。例如,在
AllowAnonymous
属性周围有一个属性,因为MVC2或MVC3不支持该属性,但MVC4和MVC5需要该属性,以确保具有全局注册的authorized属性的人员始终可以访问控制器。你是说我应该把MVC的一个版本映射到一个框架上吗?啊,我明白了。在这种情况下,是的,你做了正确的事情,你的答案是正确的。