【问题标题】:Supporting Multiple Versions of a Compilation Dependency (vNext)支持多个版本的编译依赖 (vNext)
【发布时间】:2015-08-23 07:44:16
【问题描述】:

我贡献了一个当前支持 MVC 2 - MVC 5 的开源库,并且我也想支持 MVC 6(及更高版本)。为了支持 MVC 的每个版本,我们利用 MSBuild 的 Condition 功能在构建时包含正确版本的 MVC 及其依赖项(取决于 DefineConstants 的值)。这使得可以为所有受支持的 MVC 版本使用单个项目文件,方法是使用相同的项目文件和源代码为每个 MVC 版本创建单独的 DLL。

<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>

我已经查看了 ASP.NET 5/MVC 6 的项目结构,并且已经辞职使用 project.json 文件而不是用于 MVC 6 的 .csproj 文件。但是,我阅读了 project.json documentation 并在那里似乎不是一种使用单个 project.json 文件支持多个 MVC 版本的方法。

理想情况下,我想放弃 MSBuild 并在以后的每个 MVC 版本(包括 MVC 2 - MVC 5)中使用 Roslyn。但是有没有一种方法可以支持多个 MVC 版本,而不必为每个 MVC 版本创建项目文件(和项目目录,因为它们都必须命名为 project.json)?如果没有,是否有另一种方法不必将所有 project.json 配置复制 5 次?

【问题讨论】:

    标签: c# asp.net-mvc asp.net-core roslyn asp.net-core-mvc


    【解决方案1】:

    我找到了一个(不太好的)解决该问题的方法。我仍然想知道是否有更好的方法。

    我想出的解决方案是使用 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
    

    所有.cs 文件都包含在MyProject 中。然后我的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
    

    这仍然远非理想。如果有,请提供更好的答案。

    【讨论】:

      【解决方案2】:

      您可以创建一个可编译到多个运行时的单个项目,即 .NET Core、.NET 4.5.1 等。

      1. 文件 -> 新建项目。
      2. Web -> 类库(包)
      3. 编辑 project.json 文件。
      4. 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
                }
            }
        }
        
      5. 然后在您的代码中,您可以使用预处理器指令来编写特定于特定框架或运行时的代码。

        public void Foo()
        {
            #if DNX451
            // Code specific to .NET 4.5.1
            #endif
        }
        

      【讨论】:

      • 这行不通(至少不像你拥有的那样)。我们正在为 MVC2 为 .NET 3.5、.NET 4.0 和 .NET 4.5 编译一个单独的 DLL。 MVC3 和 MVC4 在 .NET 4.0 和 .NET 4.5 下编译,MVC5 仅在 .NET 4.5 下编译。我们有编译符号来逐步利用新功能。例如,AllowAnonymous 属性周围有一个,因为 MVC2 或 MVC3 不支持该属性,但 MVC4 和 MVC5 需要它以确保具有全局注册 AuthorizeAttribute 的人始终可以访问控制器。你是说我应该将 MVC 的一个版本映射到单个框架?
      • 啊,我明白了。在这种情况下,是的,你做的是正确的事情,你的答案是正确的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-28
      • 1970-01-01
      • 2018-02-13
      • 2020-12-31
      • 1970-01-01
      • 2020-01-17
      相关资源
      最近更新 更多