打印并/或修改Razor编译器服务用于编译cshtml的C#版本

14

我想知道razor用于编译我的cshtml模板的C#版本是哪个。我之所以想知道这个,是因为这个破坏性更改

我们在foreach语句中使用了一个lambda,在我们的本地开发机器上工作得很好,但在没有安装C# 5的测试环境上产生了一个bug。这个bug非常难以调试(我们甚至复制了所有的测试环境DLL和数据库,仍然无法重现该bug)。

因此,为了防止未来出现开发/测试差异,我想知道是否有一种方法可以指定razor应该使用哪个C#版本来编译cshtml文件。如果我能够检查razor使用的C#版本(通过打印它),那就太好了。

更新:按要求提供更多有关此行为如何发生的详细信息。
我们在razor视图中使用devexpress mvc网格来显示数据。为了以动态方式添加列,我们循环遍历(foreach)列表,使用lambda向datagrid中插入列。下面是一个简化的示例:

@Html.DevExpress().GridView(
    settings =>
    {
        settings.Name = "gvDashboard";
        //Some more settings

        settings.Columns.Add(column =>
        {
            column.FieldName = Model.DashboardItems.PropertyName(p => p.Id);
            column.Caption = "Id";
            //Some more column settings
        });

        foreach (var extraColumnLoopVar in Model.ExtraColumns)
        {
            //We added this to solve the problem
            var extraColumn = extraColumnLoopVar; 

            settings.Columns.Add(column =>
            {
                column.Caption = extraColumn.Name;
                //Some more column settings

                column.SetDataItemTemplateContent(content =>
                {
                    Html.ViewContext.Writer.Write(extraColumn.MyValue);
                });
            });
        }
    });

1
我很好奇你所依赖的循环终止方式有什么用处。正如文章中提到的那样,它很少被实际使用。因此,我真的很想看看这样一个使用案例。 - Grimace of Despair
请查看已更新的答案。 - Rob
感谢您抽出时间更新您的问题。我原以为您实际上使用了闭包变量行为,但是实际上您遇到的问题是不想使用它。看起来这将会影响很多不知道即将弃用设置中不同行为的人。由于您的问题,我确实学习了这个破坏性更改 ;) - Grimace of Despair
你说得对,我过于简化了这个例子。我确实使用了value,在C# 4中,每列最终都得到了相同的(最后一个)值。顺便说一句,我很高兴你从中学到了东西 :)。 - Rob
1个回答

4

在 Views 目录下的 Web.config 文件中指定了 Razor 的版本。它必须与 System.Web.WebPages 程序集的依赖程序集列表中的一个版本匹配。此条目位于主 Web.config 文件中(通常位于应用程序树的根目录)。

从配置文件中检索数据非常简单。请参阅 ConfigurationManager 类。如果您想在运行时执行此操作。

还可以根据应用程序的引用程序集确定 Razor 版本。您可以使用反射来实现,以下是一个输出所有已引用程序集的代码片段:

var sb = new StringBuilder();
Assembly asm = Assembly.GetExecutingAssembly();
sb.AppendLine("File Version:");
sb.AppendLine(asm.FullName);

sb.AppendLine("References :");
AssemblyName[] asmNames = asm.GetReferencedAssemblies();
foreach (AssemblyName nm in asmNames)
{
    sb.AppendLine(nm.FullName);
}

// use sb.ToString() to print out wherever you need to

显然,基于您在运行时选择的方法来评估此信息可能会产生性能影响。 更新1 从下面的评论中我了解到,当您提到编译时,您是指在编译时进行Razor视图解析过程。有关“Razor View Compilation”的其他概念,请参见 Razor Generator,无论您指的是哪一个,都依赖于对包含Razor View Engine本身的库依赖项的System.Web.WebPages程序集的引用。因此,如果您知道您正在指向哪个程序集,就知道您正在使用哪个版本的Razor。 更新2 考虑到您担心在视图中使用的C#版本与之冲突,您应该遵循以下经验法则:始终引用针对您正在使用的框架的DLL(System.Web.WebPages)。重要的是要记住,MVC框架具有不同的更新时间轴,而不是语言本身。一个很好的例子是async关键字,它首先被添加到语言中,然后被MVC框架采用。通常,新版本的.NET Framework向后兼容到2.0版本,并且当您使用过时的东西时,会得到编译警告。如果您想在编译时使用旧版本的框架,可以随时更改IDE上的目标框架。

除了正确获取引用和目标框架之外,还要记住,在IIS中设置Web应用程序时,您会指定与框架版本相关联的应用程序池。您可能正在使用.NET框架的新功能,并且您可能希望它们能够正常工作,因为您已安装了新版本,但是您的应用程序正在运行在不同版本的应用程序池中。

在发生DLL和框架版本之间的混淆之前,我将遵循升级指南,考虑到我使用以前版本实现的一些代码可能无法与新版本正常工作。

更新3

以下是代码,可在运行时检索CLR版本,如MSDN中所述。

// Get the common language runtime version.
Version ver = Environment.Version;
Console.WriteLine("CLR Version {0}", ver.ToString());

1
是的,这样我可以获取/设置Razor的版本,但这是否与Razor用于编译我的视图的C#版本有关? - Rob
阅读您的更新后,'编译时间'是什么意思?由于我的C#代码文件在编译时编译,而我的Razor视图在运行时编译。为了更清晰地说明这一点:我不关心使用哪个Razor版本,我只关心使用的C#版本(我希望我的视图在C# 4中编译而不是C# 5)。 - Rob
OP正在谈论C#编译器的版本,而不是.NET Framework的版本或ASP.NET MVC的版本。 - John Saunders
C#编译器与框架版本相绑定。 - Raúl Roa
据我所知,这并不是真的,您可以将较新版本的C#与较旧版本的.Net混合使用。请参见http://csharpindepth.com/Articles/Chapter1/Versions.aspx。您在回答中提供了很多指针,我将在接下来的一周内尝试这些指针,并报告我的发现。 - Rob
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接