动态方法调用VB中没有反射 [英] Dynamic method calling in VB without reflection

查看:256
本文介绍了动态方法调用VB中没有反射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  Option $ on 
选项严格关闭
导入System.Runtime.CompilerServices

命名空间GPR
模块GPRExtensions
< Extension()>
公共函数ToGPRFormattedString(value)As String
'使用VB的动态调度来假定该值为数字
Dim d As Double = CDbl(value)
Dim s = d.ToString (N3)
Dim dynamicValue = value.ToString(N3)
返回dynamicValue
结束函数
结束模块
结束命名空间

现在,通过网络上的各种讨论(以获得相同的效果(实际上,这不是

  Dim dynamicValue = CallByName(value ,ToString,CallType.Method,N3)

NB这实际上并不等同于后期绑定电话,必须满足方法实际上是(n索引)属性的可能性,所以它实际上称为相当于:

  Dim dynamicValue = CallByName(value,ToString,CallType.Get,N3)

其他方法,如 Double.CompareTo






详细信息



您的问题是 Object.ToString()存在,因此您的代码不会尝试任何动态调度,而是从 String 的默认 String.Chars 属性的数组索引查找结果 value.ToString() call。



您可以通过尝试<$ c确认这是编译时发生的情况$ C> value.T oString(1,2),您最好尝试使用两个参数 ToString 进行运行时查询,但实际上与


参数Public ReadOnly Default Property Chars(index As Integer)As Char'


在编译时。



您可以同样确认所有其他非共享 对象方法直接与 callvirt 直接调用,依赖于覆盖在可用的情况下,如果您查看IL中的编译代码,则不调用 Microsoft.VisualBasic.CompilerServices.NewLateBinding 命名空间的动态调度。


I want to format any numeric type using a method call like so:

Option Infer On
Option Strict Off
Imports System.Runtime.CompilerServices

Namespace GPR
    Module GPRExtensions
        <Extension()>
        Public Function ToGPRFormattedString(value) As String
            ' Use VB's dynamic dispatch to assume that value is numeric
            Dim d As Double = CDbl(value)
            Dim s = d.ToString("N3")
            Dim dynamicValue = value.ToString("N3")
            Return dynamicValue
        End Function
    End Module
End Namespace

Now, from various discussions around the web (VB.Net equivalent for C# 'dynamic' with Option Strict On, Dynamic Keyword equivalent in VB.Net?), I would think that this code would work when passed a numeric type (double, Decimal, int, etc). It doesn't, as you can see in the screenshot:

I can explicitly convert the argument to a double and then .ToString("N3") works, but just calling it on the supposedly-dynamic value argument fails.

However, I can do it in C# with the following code (using LINQPad). (Note, the compiler won't let you use a dynamic parameter in an extension method, so maybe that is part of the problem.)

void Main()
{
    Console.WriteLine (1.ToGPRFormattedString());
}

internal static class GPRExtensions
{
    public static string ToGPRFormattedString(this object o)
    {
        // Use VB's dynamic dispatch to assume that value is numeric
        var value = o as dynamic;
        double d = Convert.ToDouble(value);
        var s = d.ToString("N3").Dump("double tostring");
        var dynamicValue = value.ToString("N3");
        return dynamicValue;
    }
}

So what gives? Is there a way in VB to call a method dynamically on an argument to a function without using reflection?

解决方案

To explicitly answer "Is there a way in VB to call a method dynamically on an argument to a function without using reflection?":

EDIT: I've now reviewed some IL disassembly (via LinqPad) and compared it to the code of CallByName (via Reflector) and using CallByName uses the same amount of Reflection as normal, Option Strict Off late binding.

So, the complete answer is: You can do this with Option Strict Off for all Object references, except where the method you're trying exists on Object itself, where you can use CallByName to get the same effect (and, in fact, that doesn't need Option Strict Off).

Dim dynamicValue = CallByName(value, "ToString", CallType.Method, "N3")

NB This is not actually the equivalent to the late binding call, which must cater for the possibility that the "method" is actually a(n indexed) property, so it actually calls the equivalent of:

Dim dynamicValue = CallByName(value, "ToString", CallType.Get, "N3")

for other methods, like Double.CompareTo.


Details

Your problem here is that Object.ToString() exists and so your code is not attempting any dynamic dispatch, but rather an array index lookup on the default String.Chars property of the String result from that value.ToString() call.

You can confirm this is what is happening at compile time by trying value.ToString(1,2), which you would prefer to attempt a runtime lookup for a two parameter ToString, but in fact fails with

Too many arguments to 'Public ReadOnly Default Property Chars(index As Integer) As Char'

at compile time.

You can similarly confirm all other non-Shared Object methods are called directly with callvirt, relying upon Overrides where available, not dynamic dispatch with calls to the Microsoft.VisualBasic.CompilerServices.NewLateBinding namespace, if you review the compiled code in IL.

这篇关于动态方法调用VB中没有反射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆