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#... поэтому мне нужно знать, как заставить это условие работать независимо от того, с какого языка оно вызывается.
[РЕДАКТИРОВАТЬ] - Пример Следующие шаги воспроизводят проблему:
- Создайте новый проект ASP.NET MVC 4 в Visual Studio 2012 с помощью VB.NET
- Добавьте Knockout MVC через консоль диспетчера пакетов (Install-Package kMVC)
Проигнорируйте ошибку (Methods is null), это ошибка скрипта NuGet и добавьте следующую строку в Global.asax.vb (Application_Start) вручную:
ModelBinders.Binders.DefaultBinder = Новый PerpetuumSoft.Knockout.KnockoutModelBinder()
Добавьте следующую конфигурацию в BundleConfig.vb
bundles.Add (New ScriptBundle ("~ / bundles / knockout"). Include ("~ / Scripts / knockout- {version}.js", "~ / Scripts / knockout.mapping-latest.js", "~ / Scripts /perpetuum.knockout.js "))
Визуализируйте ScriptBundle в _layout.vbhtml под модернизатором
@Scripts.Render("~/ связки / Нокаут")
Добавить новую модель в папку 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
Конечный класс
Добавить новый контроллер в папку Controllers
Открытый класс HelloWorldController Наследует PerpetuumSoft.Knockout.KnockoutController
' ' GET: /HelloWorld Function Index() As ActionResult Return View(New HelloWorldModel With { .Firstname = "John", .Lastname = "Doe"}) End Function
Конечный класс
Скомпилируйте проект, чтобы расширение MVC познакомилось с моделью.
- Щелкните правой кнопкой мыши действие Index в контроллере и выберите "Add View.."
- Оставьте имя представления и выберите "Создать строго типизированное представление", выбрав "HelloWorldModel" в качестве модели; оставьте остальные с параметрами по умолчанию и нажмите Добавить
Добавить оператор импорта в верхней части представления
@Imports PerpetuumSoft.Knockout
Создайте контекст нокаута в разделе кода
Dim ko = Html.CreateKnockoutContext()
Определите вид и примените модель под тегом h2
Имя: @ko.Html.TextBox(Function(m) m.Firstname) p>
Фамилия: @ko.Html.TextBox(Function(m) m.Lastname) p>
Здравствуйте, @ko.Html.Span(Функция (m) m.Fullname)! h2>
@ 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)
}
чтобы увидеть, где конкретное несоответствие.