Существует ли эквивалент для ключевого слова С# 4 'dynamic' при использовании безопасного типа VB.NET, т.е. с Option Strict On
?
Эквивалент VB.NET для С# 'dynamic' с опцией Strict On
Ответ 1
Эквивалент - объект в VB.NET, но с Option Strict Off
. При Option Strict On
нет эквивалента. Другими словами, ключевое слово dynamic приносит Option Strict Off
эквивалентную функциональность С#.
Ответ 2
У VB.NET всегда была встроенная "динамическая" функция, первоначально называвшаяся поздней привязкой. Этот синтаксис поддерживался навсегда:
Dim obj = new SomeComClass()
obj.DoSomething()
Работает над кодом, реализованным в .NET и COM, причем последнее является наиболее распространенным. Динамическое ключевое слово в С# дало ему такую же возможность. Однако он изменился в версии VB.NET версии 10, но теперь он использует DLR. Что добавляет поддержку динамической привязки к языковым реализациям, таким как Python и Ruby.
Синтаксис точно такой же, используйте ключевое слово Dim без As. Однако вам придется использовать опцию Strict Off, Option Infer On, которая может немного смягчить этот удар. Это показывает, что С#, использующее конкретное ключевое слово для динамического связывания сигнала, было довольно хорошим шагом. Afaik все запросы сделать это в VB.NET также пока не рассмотрены, но не запланированы.
Если вы предпочитаете вариант Strict On, то с использованием ключевого слова Partial Class, чтобы вы могли переместить часть кода в другой исходный файл, вероятно, наиболее эффективный подход.
Ответ 3
Это продемонстрирует, что Basic говорит о том, что VB не имеет такой же степени детализации в этом, как С#. У меня есть эта часть кода на С#, которая использует отражение для динамического вызова метода во время выполнения:
var listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, null);
Причина, по которой я делаю это, заключается в том, что "GetSomeData" может быть любым из нескольких методов, каждый из которых получает разные данные. Какой метод для вызова здесь зависит от параметра строки, переданного в этот объект во время выполнения, поэтому значение "GetSomeData" изменяется во время выполнения.
Подпись "GetSomeData" :
public List<SomeResultSetClass> GetSomeData()
Каждый из вызванных методов возвращает какой-то объект List<T>
. Затем я отправляю объект listResult в общий метод Export, который выглядит следующим образом:
void Export<T>(List<T> exportList, string filePath, byte fileType) where T: class;
Здесь мы сталкиваемся с проблемой. Invoke возвращает объект типа System.Object. Конечно, List<T>
также является объектом System.Object, но интерфейсом является интерфейс System.Object, а не интерфейс IList. Если я попытаюсь выполнить метод Export, таким образом:
myExportObj.Export(listResult, parms.filePath, parms.fileType);
код не скомпилируется. Ошибка:
The type arguments for method '...Export<T>...' cannot be inferred from the usage. Try specifying the type arguments explicitly.
Нет, спасибо! Проблема в том, что компилятор не может найти метаданные IList, потому что он смотрит на интерфейс System.Object. Теперь вы можете создать новый List<T>
, присвоить ему (List<Whatever>) listResult
, но в первую очередь победите цель динамического вызова.
Исправление состоит в изменении var
на dynamic
:
dynamic listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, null);
Поскольку динамический обход проверки статического типа во время компиляции, мы не получаем ошибку компиляции. Затем, когда динамический объект передается методу "Экспорт", DLR (Dynamic Language Runtime) смотрит, может ли он неявно отбрасывать объект в соответствии с требованиями сигнатуры метода. Это, конечно, возможно.
Хорошо, так как все работает на С#. С VB строка выглядит следующим образом:
Dim listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, Nothing)
С опцией Strict On эта строка расстраивает компилятор, как и ожидалось. С его помощью он работает нормально. Другими словами, в VB мне нужно отключить проверку типа для всего модуля, который содержит строку. Нет более тонкой детализации, чем это.
Ответ 4
Вы можете включить опцию Infer On и Option Strict Off и все еще иметь что-то очень близкое.
Ответ 5
Существует достаточно способов обработки методов и свойств с поздними связями COM-объектов и безопасностью типа (Option Strict On
). Это при использовании методов Microsoft.VisualBasic.Interaction.CallByName и System.Type.InvokeMember. (Или создайте отдельный "частичный" файл, где Option Strict
есть Off
).
Но обрабатывать события с поздним связыванием с VB.NET не так просто, как с динамическим типом в С#. Вы можете проверить "взломать" для этого в Динамические события в VB.NET.
Ответ 6
Да, ExpandoObject.
Dim DObj = Новая система .Dynamic.ExpandoObject()
DObj.A = "abc"
DObj.B = 123
Ответ 7
Обратите внимание, что даже с помощью опции Strict вы все равно можете использовать, например, ExpandoObject для доступа к таким свойствам, как:
Dim doc = JsonConvert.DeserializeObject(Of ExpandoObject)("{""name"":""Bob""}")
Dim lookup as IDictionary(Of String, Object) = doc
lookup("name") ' Bob
Ответ 8
Эквивалент ключевого слова С# dynamic в Vb.Net с опцией strict on существует в виде пакета NuGet: Dynamitey.
После установки пакета Dynamitey можно записать код Vb.Net следующим образом:
Option Strict On : Option Infer On : Option Explicit On
Imports Dynamitey
Module Module1
Public Sub Main()
Dim o = Nothing
o = "1234567890"
Console.WriteLine(Dynamic.InvokeMember(o, "Substring", 5)) ' writes 67890
End Sub
End Module
Или немного более читаемым:
Option Strict On : Option Infer On : Option Explicit On
Imports Dynamitey
Module Module1
<Extension()>
Public Function Substring(self As Object, offset As Integer) As String
Return CType(Dynamic.InvokeMember(self, "Substring", offset), String)
End Function
Public Sub Main()
Dim o = Nothing
o = "1234567890"
Console.WriteLine(Substring(o, 5)) ' writes 67890
End Sub
End Module
Протестировано с VS2017 и.net Framework 4.7.2.