Is there any way to use the new dynamic features in the 4.0 framework like ExpandoObject
in VB.NET without setting Option Strict Off
? With C#, you lose type safety only with the variables you specifically declare as dynamic
. But with VB, the only way I've found to use these features is with the old Option Strict Off
trick that's been in 开发者_如何学PythonVB.NET since the beginning. Without Option Strict, everything in the file is polluted with fuzzy typing like so:
Option Explicit On
Option Strict Off
Option Infer On
Partial Public Class ClassX
Public Sub TestDynamic()
Dim dyn As Object = New System.Dynamic.ExpandoObject()
Dim a As String = 1 ''# Ew!
Dim obj As Object = "999"
dyn.Str = a ''# a is a string, remember? Even though it has a number
''# dyn.Str = 1 : Type = System.String
Console.WriteLine("dyn.Str = {0} : Type = {1}", dyn.Str, dyn.Str.GetType().ToString())
dyn.Num = 123
''# dyn.Num = 123 : Type = System.Int32
Console.WriteLine("dyn.Num = {0} : Type = {1}", dyn.Num, dyn.Num.GetType().ToString())
dyn.Dbl = obj / 9
''# dyn.Dbl = 111 : Type = System.Double
Console.WriteLine("dyn.Dbl = {0} : Type = {1}", dyn.Dbl, dyn.Dbl.GetType().ToString())
dyn.Obj = obj
''# dyn.Obj = 999 : Type = System.String
Console.WriteLine("dyn.Obj = {0} : Type = {1}", dyn.Obj, dyn.Obj.GetType().ToString())
dyn.Dte = #5/5/1955#
''# dyn.Dte = 7/7/1977 12:00:00 AM : Type = System.DateTime
Console.WriteLine("dyn.Dte = {0} : Type = {1}", dyn.Dte, dyn.Dte.GetType().ToString())
AmICalled(dyn.Num)
AmICalled(dyn.Obj)
AmICalled(dyn.Str)
AmICalled(dyn.Dbl)
Try
AmICalled(dyn.Dte)
Catch
Console.WriteLine("Dates don't convert to ints I guess... but we don't know that 'till runtime")
End Try
Console.WriteLine(dyn.Num + dyn.Str) ' 124!?
Console.WriteLine(dyn.Num & dyn.Str) ' 1231!?
End Sub
Private Sub AmICalled(ByVal i As Integer)
Console.WriteLine("AmICalled was called with: " & i)
End Sub
End Class
Is this really correct? And, if so, what's the best way to still use things like ExpandoObject
and mitigate the risk of losing all type safety? Partial classes? Or should I just not be so worried about type safety in this case?
It appears you can't without having to turn Option Strict off. I'll research some more though.
Edit
After going through some documentation on the ExpandoObject
, it appears it is used in C# for COM and Office Interop. Traditionally, in VB.NET, the Object
was used for such purposes and that would require you turn off Option Strict.
To answer your question this means that you can use dynamic types in VB.NET by using the Object
type instead of the ExpandoObject
[if such a type exists in VB.NET], set Option Infer On
and Option Strict On or Off.
You could also consider using partial classes to localise your non Option Strict code to particular files.
Suggested Reading
- Dynamic Type in C#, Equivalent in VB
- Using Type Dynamic (C# Programming Guide)
I haven't tried this, and it wouldn't be pretty, but you ought to be able to use CallByName
.
Adapting your example
Partial Public Class ClassX
Public Sub TestDynamic()
Dim dyn As Object = New System.Dynamic.ExpandoObject()
Dim a As String = "1" ''# Option Strict is on
Dim obj As Object = "999"
''# dyn.Str = a
CallByName(dyn, "Str", CallType.Set, a)
Console.WriteLine("dyn.Str = {0} : Type = {1}",
CallByName(dyn, "Str", CallType.Get, a),
CallByName(dyn, "Str", CallType.Get, a).GetType().ToString()
)
''# etc etc... I can't face any more of that
As I said, it's not pretty.
No. This is sort of the modern day late-binding.
精彩评论