VB.NET equivalent for C# 'dynamic' with Op

2019-01-02 15:38发布

Is there an equivalent for the C# 4 'dynamic' keyword when using type safe VB.NET, i.e. with Option Strict On?

8条回答
伤终究还是伤i
2楼-- · 2019-01-02 16:19

This will demonstrate what Basic is saying about VB not having the same granularity in this as C#. I have this piece of code in C#, that uses reflection to dynamically invoke a method at runtime:

var listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, null);

The reason I'm doing this is that "GetSomeData" could be any of a number of methods, each getting different data. Which method to invoke here is dependent on a string parameter passed into this object at runtime, so, value of "GetSomeData" varies at runtime.

The signature of "GetSomeData" is:

public List<SomeResultSetClass> GetSomeData()

Each one of the methods invoked returns some sort of List<T> object. Next, I'm sending the listResult object to a generic method called Export, which looks like this:

void Export<T>(List<T> exportList, string filePath, byte fileType) where T: class;

Here's where we run into a problem. Invoke returns an object of type System.Object. Of course, a List<T> is also a System.Object, but the interface exposed is the System.Object interface, not the IList interface. If I try to execute the Export method, thus:

myExportObj.Export(listResult, parms.filePath, parms.fileType);

the code fails to compile. The error is:

The type arguments for method '...Export<T>...' cannot be inferred from the usage. Try specifying the type arguments explicitly.

No thanks!! The problem is that the compiler can't find the IList metadata, because it's looking at the System.Object interface. Now, you can create a new List<T>, assign (List<Whatever>) listResult to it, but that defeats the purpose of dynamic invocation in the first place.

The fix is to change var to dynamic:

dynamic listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, null);

Since dynamic bypasses static type checking at compile time, we don't get a compile error. Then, when the dynamic object gets passed to the Export method, the DLR (Dynamic Language Runtime) looks to see if it can implicitly cast the object to meet the requirements of the method signature. Which of course it can.

Ok, so that's how things work in C#. With VB, the line goes like this:

Dim listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, Nothing)

With Option Strict On, this line upsets the compiler, as expected. With it off, it works fine. In other words, in VB, I have to turn off the type checker for the entire module that contains the line. There is no finer granularity than that.

查看更多
孤独寂梦人
3楼-- · 2019-01-02 16:27

There are enough ways to handle methods and properties with late binding COM objects and type safe (Option Strict On). This when using the Microsoft.VisualBasic.Interaction.CallByName and System.Type.InvokeMember methods. (Or create a separate "partial" file where Option Strict is Off).

But to handle events with late binding from VB.NET is not as straightforward as with the dynamic type in C#. You can check the "hack" for that in Dynamic Events in VB.NET.

查看更多
无与为乐者.
4楼-- · 2019-01-02 16:28

Note that even with Option Strict on you can still use e.g. an ExpandoObject to access properties like:

Dim doc = JsonConvert.DeserializeObject(Of ExpandoObject)("{""name"":""Bob""}")
Dim lookup as IDictionary(Of String, Object) = doc
lookup("name") ' Bob
查看更多
笑指拈花
5楼-- · 2019-01-02 16:30

The equivalent is Object in VB.NET but with Option Strict Off. With Option Strict On there's no equivalent. Put another way the dynamic keyword brings Option Strict Off equivalent functionality to C#.

查看更多
深知你不懂我心
6楼-- · 2019-01-02 16:35

VB.NET always had the "dynamic" feature built in, originally called late binding. This syntax was supported forever:

 Dim obj = new SomeComClass()
 obj.DoSomething()

Worked on code implemented in .NET and COM, the latter being the most common use. The dynamic keyword in C# gave it that same capability. It did get changed in VB.NET version 10 however, it is now using the DLR as well. Which adds support for dynamic binding to language implementations like Python and Ruby.

The syntax is exactly the same, use the Dim keyword without As. You will however have to use Option Strict Off, Option Infer On can soften that blow a bit. It does show that C# using a specific keyword to signal dynamic binding was a pretty good move. Afaik all requests to do so in VB.NET as well have as yet been considered but not planned.

If you prefer Option Strict On then using the Partial Class keyword so you can move some of the code into another source file is probably the most effective approach.

查看更多
若你有天会懂
7楼-- · 2019-01-02 16:35

You can turn Option Infer On and Option Strict Off and still have something very close.

查看更多
登录 后发表回答