Knockout MVC - проблема VB.NET с IsAssignableFrom и MethodCallExpression

У меня проблемы с библиотекой Knockout MVC. Это оболочка.NET вокруг Knockout.js. Хотя он работает довольно хорошо при использовании в проекте ASP.NET MVC на C#, он просто не работает в проекте на основе 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();
}

Условие всегда оценивается как False, когда проект, который вызывает библиотеку, написан на VB.NET. То же самое в C#: работает отлично.

Поскольку я не совсем уверен, что является причиной такого различного поведения, я подумал, что было бы неплохо спросить сообщество. Может быть, кто-то знает, как эта строка может быть переведена во что-то, что работает как с C#, так и с VB.NET.

Код можно найти в строке 260 здесь.

[РЕДАКТИРОВАТЬ]

Чтобы прояснить ситуацию: приведенный выше код не нужно переводить на VB.NET. Проблема скорее в том, что содержащееся в нем условие возвращает разные результаты в зависимости от того, вызывается ли оно из кода C# или VB.NET. Я считаю, что IsAssignableFrom ведет себя по-разному для VB.NET и C#... поэтому мне нужно знать, как заставить это условие работать независимо от того, с какого языка оно вызывается.

[РЕДАКТИРОВАТЬ] - Пример Следующие шаги воспроизводят проблему:

  1. Создайте новый проект ASP.NET MVC 4 в Visual Studio 2012 с помощью VB.NET
  2. Добавьте Knockout MVC через консоль диспетчера пакетов (Install-Package kMVC)
  3. Проигнорируйте ошибку (Methods is null), это ошибка скрипта NuGet и добавьте следующую строку в 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. Визуализируйте ScriptBundle в _layout.vbhtml под модернизатором

    @Scripts.Render("~/ связки / Нокаут")

  6. Добавить новую модель в папку Models

    Импортирует 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. Щелкните правой кнопкой мыши действие Index в контроллере и выберите "Add View.."
  10. Оставьте имя представления и выберите "Создать строго типизированное представление", выбрав "HelloWorldModel" в качестве модели; оставьте остальные с параметрами по умолчанию и нажмите Добавить
  11. Добавить оператор импорта в верхней части представления

    @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(Функция (m) m.Fullname)!

    @ Ko.Apply (модель)

Теперь, если вы скомпилируете и запустите приложение и вызовете контроллер HelloWorld (localhost: nnnnn / HelloWorld), вы получите исключение NotImplementedException в строке ko.Apply(Model).

Если вы повторите описанные выше шаги при создании проекта ASP.NET MVC с C#, все будет работать как положено.

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

чтобы увидеть, где конкретное несоответствие.

Другие вопросы по тегам