Чи існує еквівалент для ключового слова C # 4 "динамічний" при використанні безпечного типу VB.NET, тобто з Option Strict On
?
dynamic
до C #. Той, хто погоджується чи не погоджується, може тут проголосувати чи прокоментувати Microsoft Connect
Чи існує еквівалент для ключового слова C # 4 "динамічний" при використанні безпечного типу VB.NET, тобто з Option Strict On
?
dynamic
до C #. Той, хто погоджується чи не погоджується, може тут проголосувати чи прокоментувати Microsoft Connect
Відповіді:
Еквівалентом є Object у VB.NET, але з Option Strict Off
. При Option Strict On
цьому немає еквівалента. Іншими словами, динамічне ключове слово забезпечує Option Strict Off
еквівалентну функціональність C #.
У VB.NET завжди була вбудована "динамічна" функція, яку спочатку називали пізнім прив'язуванням. Цей синтаксис підтримувався назавжди:
Dim obj = new SomeComClass()
obj.DoSomething()
Працював над кодом, реалізованим у .NET та COM, останній найбільш поширений. Динамічний ключове слово в C # дав йому той же потенціал. Це було змінено у версії VB.NET 10, однак, зараз він також використовує DLR. Що додає підтримку динамічного прив’язки до таких реалізацій мови, як Python та Ruby.
Синтаксис абсолютно однаковий, використовуйте ключове слово Dim без As. Однак вам доведеться використовувати Option Strict Off, Option Infer On може трохи пом'якшити цей удар. Це показує, що C # з використанням певного ключового слова для сигналізації динамічного прив'язки був досить хорошим кроком. Afaik всі запити про це у VB.NET також ще розглядались, але не планувалися.
Якщо ви віддаєте перевагу Option Strict On, тоді використання ключового слова Partial Class, щоб ви могли перемістити частину коду в інший вихідний файл, є, мабуть, найбільш ефективним підходом.
app
виводиться як тип Object
, тому не можна використовувати об’єкт програми Excel app
. Наприклад, якщо я підставляю, app.Calculate
де у вас є, REM etc...
він не компілюється. Я думаю, що це проблема, про яку задається Джерон. Компілятор кажеError 1 Option Strict On disallows late binding.
dynamic
. Той, хто погоджується або не погоджується, може тут проголосувати чи прокоментувати Microsoft Connect
Option
директив у верхній частині файлу.
Це продемонструє, що Basic говорить про VB, який не має такої деталізації, як C #. У мене є цей фрагмент коду в C #, який використовує відображення для динамічного виклику методу під час виконання:
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. Звичайно, a List<T>
- це також System.Object, але виставлений інтерфейс - це інтерфейс System.Object, а не інтерфейс IList. Якщо я спробую виконати метод експорту, таким чином:
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) перевіряє, чи може неявно передавати об’єкт відповідно до вимог підпису методу. Що, звичайно, може.
Гаразд, так це працює в C #. У VB лінія виглядає так:
Dim listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, Nothing)
З Option Strict On цей рядок засмучує компілятор, як і очікувалося. Якщо його вимкнути, він працює нормально. Іншими словами, у VB я повинен вимкнути перевірку типу для всього модуля, що містить рядок. Немає більш тонкої деталізації, ніж ця.
Ви можете увімкнути Option Infer та Option Strict Off і все одно мати щось дуже близьке.
Існує достатньо способів обробляти методи та властивості з пізньо прив’язуваними COM-об’єктами та типом safe ( Option Strict On
). Це при використанні методів Microsoft.VisualBasic.Interaction.CallByName та System.Type.InvokeMember. (Або створіть окремий "частковий" файл там, де Option Strict
є Off
).
Але обробляти події з пізнім прив'язуванням з VB.NET не так просто, як з динамічним типом в C #. Ви можете перевірити "хак" для цього в Динамічні події у VB.NET .
Еквівалент динамічного ключового слова c # у Vb.Net із строкою опцією 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.
Так, ExpandoObject.
Dim DObj = Нова система.Dynamic.ExpandoObject ()
DObj.A = "abc"
DObj.B = 123
Option Strict On
. Ваша відповідь працює лише зOption Strict Off
Зверніть увагу, що навіть якщо увімкнено Option Strict, ви все одно можете використовувати, наприклад, ExpandoObject для доступу до таких властивостей, як:
Dim doc = JsonConvert.DeserializeObject(Of ExpandoObject)("{""name"":""Bob""}")
Dim lookup as IDictionary(Of String, Object) = doc
lookup("name") ' Bob