c# - Razor 页面中 VB.NET 的 @@<text> 标签问题

标签 c# asp.net-mvc vb.net razor

我正在更新旧的 VB.Net Aspnet MVC(razor 页面)网站。更新 .NET Framework 版本、Entity Framework、MVC。

到目前为止,它运行良好,除了几个使用@@ 运算符的页面。我之前在 C# 中看到过,以转义 Razor 的 @。

但在这种情况下,在 VB.NET 中,它返回一个匿名方法,该方法接受一个对象并返回一个 System.Web.WebPages.HelperResult。

以下代码:

@Code
    Dim myString As String
    myString = "mystring"
End Code

Double-At : @String.Format("{0}", @@<text>@myString</text>)
<br />
Double-At execution : @String.Format("{0}", (@@<text>Some @myString and then some</text>)(Nothing))
<br />

输出:

Double-At : VB$AnonymousDelegate_0`2[System.Object,System.Web.WebPages.HelperResult] 
Double-At execution : Somesome mystring and then some 

因为我不太习惯 VB.Net,所以我试图在 C# 中找到等效项,以便我可以使用它并更好地理解它,但找不到任何类似的东西。

在标志处谷歌搜索 VB.Net Razor Double 没有产生任何有意义的答案,我仍然不知道那是什么。

现在,我正在更新的网站因生成的代码无法编译而失败,并且生成的代码来自那些 Double At-Signs 函数。

作为引用,如果有人有想法,生成的代码无法编译,它会失败,因为我在 @@ 中使用的 @ 被拆分成多行,即使它们是一条指令。

例如:

@(Html.Kendo().Window() _
                    .Name("SomeWindow") _
                    .Draggable() _
                    .Modal(True) _
                    .Title("") _
                    .Width(300) _
                    .Content(@@<text>
    SomeValue : @LocalizedResources.SomeValue
</text>))

使用以下代码在运行时编译(点击页面时)崩溃:

WriteTo(__razor_template_writer, 

        #ExternalSource("C:\TestProject\TestPage.vbhtml",141)


        #End ExternalSource

        ##ExternalSource("C:\TestProject\TestPage.vbhtml",141)
             LocalizedResources.SomeValue)


        #End ExternalSource

WriteTo 函数的第二个参数出现在另一行这一事实使编译器吐出错误,BC30205:预期语句结束。

知道@@是什么吗?知道它的 C# 等价物是什么吗?或者甚至建议让我的 Razor 页面生成实际编译的代码?

最佳答案

问题中提到的功能被称为templated Razor delegateinline Razor template,它们生成 Func<T, TResult> (或 VB.NET 中的 Func(Of T, TResult),另请参见 What is Func, how and when is it used )并允许使用 @<tag>...</tag> 插入片段格式。

创建模板化 Razor 委托(delegate)的常用方法使用如下语法:

C#

@{
    string myString = "mystring";
    Func<object, HelperResult> helper = @<text>@myString</text>;
}

@String.Format("{0}", helper(myString))

VB.NET

@Code
    Dim myString As String = "mystring"
    Dim helper = (@@<text>@myString</text>)
@End Code

@String.Format("{0}", helper(myString))

VB.NET 定义实际上有这样的 lambda 表达式(通过应用 GetType() 方法我们可以知道 lambda 背后的底层类型):

Dim helper = Function(o As Object) 
    @<text>@myString</text>
End Function

C# 和 VB.NET 委托(delegate)实现之间的区别是 VB.NET 利用 relaxed delegate conversion 默认情况下,它允许将函数(包括 lambda 表达式)分配给非相同参数的委托(delegate)(即使使用匿名委托(delegate)),但仅在 Option Strict 时可用。设置关闭。如果添加 @Option Strict On在具有上述表达式的 Razor View 上,您​​将看到此错误:

Option Strict On requires each lambda expression parameter to be declared with an 'As' clause if its type cannot be inferred.

简而言之,您不能将匿名委托(delegate)与 Option Strict On 一起使用, 并被迫使用 Func(Of Object, HelperResult)相反。

此功能在C# 中不存在,与Func<T, TResult> 的显式转换必须用于从类型为 TResult 的 lambda 创建实例:

var result = (Func<object, HelperResult>)(@<text>@myString</text>);

如果您使用 var result = (@<text>@myString</text>);直接,会出现这个异常,因为编译器不知道是否应该转换为delegate:

Cannot assign lambda expression to an implicitly-typed local variable

因此,同样的规则也适用于 String.Format() 方法,其中包含 object作为第二个参数:

// Error: cannot convert lambda expression to type 'object' because it is not a delegate type
@String.Format("{0}", ((@<text>@myString</text>)))
@String.Format("{0}", ((@<text>@myString</text>))(null))

// Correct
@String.Format("{0}", ((Func<object, HelperResult>)(@<text>@myString</text>)))
@String.Format("{0}", ((Func<object, HelperResult>)(@<text>@myString</text>))(null))

关于 Kendo helper 问题, Content() 之一Kendo UI 中的方法重载 WindowBuilder包含 Func<object, object>委托(delegate)类型作为参数:

namespace Kendo.Mvc.UI.Fluent
{
    public class WindowBuilder : WidgetBuilderBase<Window, WindowBuilder>, IHideObjectMembers
    {
        // other methods

        public WindowBuilder Content(Func<object, object> value)
        {
            base.Component.Template.InlineTemplate = value; // this is the inline template
            return this;
        }

        // other methods
    }
}

哪里InlineTemplate属性声明为 Func<T, object> :

public Func<T, object> InlineTemplate
{
    get
    {
        return this.inlineTemplate;
    }
    set
    {
        this.inlineTemplate = value;
        this.binder = delegate(T dataItem, IHtmlNode node)
        {
            // skipped for brevity 
        };
    }
}

因此您可以在 CSHTML 页面中将 lambda 表达式作为参数传递:

@(Html.Kendo().Window()
              .Name("SomeWindow")
              .Draggable()
              .Modal(true)
              .Title("")
              .Width(300)
              .Content(@<text>SomeValue : @LocalizedResources.SomeValue</text>))

注意事项:

1) VB$AnonymousDelegateFunc(Of T, TResult)不是同一类型。

2) 任何接受模板化 Razor 委托(delegate)的助手必须有 TResult参数定义为 HelperResult ,因此 @@带有内联模板的是指 Func(Of T, HelperResult) .

引用:

Templated Razor delegates

关于c# - Razor 页面中 VB.NET 的 @@<text> 标签问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54154688/

相关文章:

asp.net-mvc - 在ASP.NET MVC 1.0中使用Elmah的“执行URL失败”

asp.net - 为什么每个人都不喜欢ViewData?

vb.net - 使用 LINQ 查询的 DataGridView 单元格搜索

c# - 连接 byte[] 的 C# 列表

c# - MongoDB .NET 驱动程序 - 将 lambda 表达式转换为 JSON 对象

c# - ASP.Net MVC - 路由对象 id == 标题 - 如何处理重复项?

c# - 将列表转换为队列 C#

c# - 使用 mvvm 和 wpf 重用菜单

c# - 为什么 C# 不允许重载 operator()?

c# - 如何将文件上传到 Web API 服务器并将参数发送到操作?