【问题标题】:Knockout MVC - VB.NET issue with IsAssignableFrom and MethodCallExpression淘汰赛 MVC - IsAssignableFrom 和 MethodCallExpression 的 VB.NET 问题
【发布时间】:2013-08-28 13:30:37
【问题描述】:

我在使用名为 Knockout MVC 的库时遇到问题。它是一个围绕 Knockout.js 的 .NET 包装器。虽然它在基于 C# 的 ASP.NET MVC 项目中使用时效果很好,但在基于 VB.NET 的项目中根本就不行,我找到了原因。

protected virtual string VisitMethodCall(MethodCallExpression m)
{
  ...
  if (typeof(Expression).IsAssignableFrom(m.Method.ReturnType))
    return VisitMemberAccess(m.Object, m.Method.Name);
  throw new NotSupportedException();
}

当调用库的项目是用 VB.NET 编写的时,条件总是评估为 False。在 C# 中也是如此:完美运行。

由于我不太确定导致这种不同行为的原因,我认为向社区询问可能是个好主意。也许有人知道如何将这行代码翻译成同时适用于 C# 和 VB.NET 的内容。

代码可以在 ~ line 260 here找到。

[编辑]

澄清一下:上面的代码不需要翻译成 VB.NET。问题在于,它包含的条件根据是从 C# 代码还是 VB.NET 代码调用而返回不同的结果。我相信 IsAssignableFrom 对于 VB.NET 和 C# 的行为不同......所以我需要知道如何让这个条件独立于调用它的语言而工作。

[编辑] - 示例 以下步骤重现了该问题:

  1. 使用 VB.NET 在 Visual Studio 2012 中创建一个新的 ASP.NET MVC 4 项目
  2. 通过包管理器控制台添加 Knockout MVC(安装包 kMVC)
  3. 忽略错误(Methods 为空),这是 NuGet Script 错误,在 Global.asax.vb (Application_Start) 中手动添加以下行:

    ModelBinders.Binders.DefaultBinder = 新 PerpetuumSoft.Knockout.KnockoutModelBinder()

  4. 在BundleConfig.vb中添加如下配置

    bundles.Add(New ScriptBundle("~/bundles/knockout").Include( "~/Scripts/knockout-{version}.js", "~/Scripts/knockout.mapping-latest.js", "~/Scripts/perpetuum.knockout.js"))

  5. 在 Modernizer 下方的 _layout.vbhtml 中渲染 ScriptBundle

    @Scripts.Render("~/bundles/knockout")

  6. 将新模型添加到模型文件夹

    导入 DelegateDecompiler

    公共类 HelloWorldModel

      Public Property Firstname As String
      Public Property Lastname As String
    
      <Computed>
      Public ReadOnly Property Fullname As String
          Get
              Return Firstname + " " + Lastname
          End Get
      End Property
    

    结束类

  7. 将新控制器添加到 Controllers 文件夹

    公共类 HelloWorldController 继承 PerpetuumSoft.Knockout.KnockoutController

      '
      ' GET: /HelloWorld
    
      Function Index() As ActionResult
          Return View(New HelloWorldModel With {
                      .Firstname = "John",
                      .Lastname = "Doe"})
      End Function
    

    结束类

  8. 编译项目,以便 MVC 扩展了解模型

  9. 右键单击控制器中的索引操作并选择“添加视图..”
  10. 保留视图名称并选择创建强类型视图,选择 HelloWorldModel 作为模型;将其余部分保留为默认选项,然后单击添加
  11. 在视图顶部添加 Imports 语句

    @Imports PerpetuumSoft.Knockout

  12. 在代码部分创建敲除上下文

    Dim ko = Html.CreateKnockoutContext()

  13. 定义视图并在h2标签下应用模型

    名字:@ko.Html.TextBox(Function(m) m.Firstname)


    姓氏:@ko.Html.TextBox(Function(m) m.Lastname)


    你好,@ko.Html.Span(Function(m) m.Fullname)!


    @ko.Apply(模型)

现在,如果您编译并执行应用程序并调用 HelloWorld 控制器 (localhost:nnnnn/HelloWorld),那么您将在 ko.Apply(Model) 行上得到 NotImplementedException。

如果您在使用 C# 创建 ASP.NET MVC 项目时重复上述步骤,则一切正常。

【问题讨论】:

  • 请在您使用该库的地方发布一些示例视图代码,它会引发异常!
  • 这是 Knockout MVC/DelegateDecompiler 中的一个错误,因此您应该从这里在 Github github.com/AndreyAkinshin/knockout-mvc 上为您当前的复制创建一个问题。但由于该项目不太活跃,不要指望快速修复......

标签: asp.net-mvc vb.net knockout.js knockout-mvc


【解决方案1】:

请试试这个

在 Vb.net 中,代码的语法发生了变化。

    Protected Overridable Function VisitMethodCall(m As MethodCallExpression) As String

    If GetType(Expression).IsAssignableFrom(m.Method.ReturnType) Then
        Return VisitMemberAccess(m.[Object], m.Method.Name)
    End If
        Throw New NotSupportedException()
    End Function

我认为包含当前程序集引用的类型 IPlugin 的程序集之间存在不匹配。

你应该使用

 typeof (IPlugin).Module.FullyQualifiedName

 foreach (var type in t.GetInterfaces ()) 
 {    
     Console.WriteLine (type.Module.FullyQualifiedName)
 }

查看特定不匹配的位置。

【讨论】:

  • 我想我可能需要编辑我的问题。问题不在于我试图将上面的代码转换为 VB.NET。问题是,当使用包含来自基于 VB.NET 项目的上述代码的 C# 库时,此条件的行为与从 VB.NET 项目中使用时不同。所以我猜 IsAssignableFrom 方法为基于 C# 和 VB.NET 的调用返回不同的结果。
猜你喜欢
  • 2013-11-01
  • 1970-01-01
  • 2013-06-15
  • 1970-01-01
  • 1970-01-01
  • 2015-03-30
  • 2014-09-18
  • 1970-01-01
相关资源
最近更新 更多