c#7元组不起作用(roslyn编译器异常)

问题描述 投票:6回答:2

有一段时间我们在剃刀文件中使用了一些新的c#7.0功能。我们已将Roslyn编译器集成到我们的Web项目中,这些项目目前正在针对.NET Framework 4.6.2。

今天我想在剃刀文件中试用tuples,如下所示:

@functions
{
    public (string labelName, string sfName) GetNames(PurchaseType purchaseType)
    {
        switch (purchaseType)
        {
            case PurchaseType.New:
                return (labelName: Booklist.New, sfName: SpecflowIdentifiers.BooklistItem.CheckBoxNew);
            case PurchaseType.Rental:
                return (labelName: Booklist.Rent, sfName: SpecflowIdentifiers.BooklistItem.CheckBoxRental);
            case PurchaseType.SecondHand:
                return (labelName: Booklist.Secondhand, sfName: SpecflowIdentifiers.BooklistItem.CheckBoxSecondHand);
            default:
                throw new ArgumentOutOfRangeException(nameof(purchaseType), @"should not get here");
        }
    }
}

@helper RenderCheckbox(PurchaseType purchaseType, int index, decimal priceTo)
{
    var names = GetNames(purchaseType);
    var x = name.labelName;
    // render something
}

这会产生以下运行时异常:

CS8137:无法定义使用元组的类或成员,因为无法找到编译器所需类型“System.Runtime.CompilerServices.TupleElementNamesAttribute”。你错过了参考吗?

CS8179:未定义或导入预定义类型'System.ValueTuple`2'

这导致我https://stackoverflow.com/a/40826779/2772845提到我应该将System.ValueTuple包添加到项目中。但我已经添加了这个。

这些是配置中使用的包:

<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="1.0.8" targetFramework="net462" />
<package id="Microsoft.Net.Compilers" version="2.4.0" targetFramework="net462" developmentDependency="true" />
<package id="System.ValueTuple" version="4.4.0" targetFramework="net462" />

所以,我现在回到使用旧的Tuple<>。我想知道是否有人知道我在忽视什么。

编辑11/16/2017:

所以我把public (string labelName, string sfName) GetNames(PurchaseType purchaseType)改成了public ValueTuple<string, string> GetNames(PurchaseType purchaseType),这给了我以下例外:

CS0433:类型'ValueTuple'存在于'System.ValueTuple,Version = 4.0.2.0,Culture = neutral,PublicKeyToken = cc7b13ffcd2ddd51'和'mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089'

这导致我向'ValueTuple<T1, T2>' exists in both 'System.ValueTuple ...' and 'mscorlib ...'提供了实际答案。我已经安装了.NET Framework 4.7,并且由于razor是在运行时编译的,所以它只使用该版本。

亲切的问候,里克

c# razor tuples roslyn c#-7.0
2个回答
6
投票

Razor视图由ASP.Net在运行时编译,不会自动从项目继承引用或其他设置。

您需要将System.ValueTuple添加到Web.config中的ASP.Net运行时编译中:

<system.web>
    <compilation>
      <assemblies>
        <add assembly="System.ValueTuple" />

1
投票

这似乎是Razor的好地狱。如果您的目标是.NET 4.7或更高版本,则不应该引用System.ValueTuple,因为所有需要的类型都已经是mscorlib的一部分。但在我看来,Razor正在使用最新版本的mscorlib,即使你特别指出例如.NET 4.6.2。所以在我看来,至少在安装了.NET 4.7的系统上,解决方案实际上是要删除

 <system.web>
    <compilation>
        <assemblies>
            <add assembly="System.ValueTuple, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51"/>

这样,您当然可以在缺少.NET 4.7的服务器上破坏应用程序的运行时编译,或者在使用它时进行预编译。

如果至少所有服务器处于相同状态,则可以使用配置转换。

另外,当检查web.configs时,检查两者 - 根web.config和视图文件夹中的web.config。

如果任何人在部署期间遇到与预编译类似的问题,到目前为止,我设法解决它的唯一方法是将System.ValueTuple的引用直接添加到CSC命令行,如下所示:

<system.codedom>
    <compilers>
        <compiler extension=".cs" compilerOptions='/langversion:7 /nowarn:1659;1699;1701 /R:"../packages\System.ValueTuple.4.4.0\lib\net461\System.ValueTuple.dll"' xdt:Locator="Match(extension)" xdt:Transform="SetAttributes" />
    </compilers>
</system.codedom>

在服务器部署的转换文件中。这需要运行时编译,因为它无法访问../packages。

© www.soinside.com 2019 - 2024. All rights reserved.