vb.net - VB中的动态方法调用没有反射

标签 vb.net dynamic

我想使用这样的方法调用来格式化任何数字类型:

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

现在,根据网络上的各种讨论(VB.Net equivalent for C# 'dynamic' with Option Strict OnDynamic Keyword equivalent in VB.Net?),我认为当传递数字类型( double 、十进制、整数等)时,此代码将起作用。它没有,正如您在屏幕截图中看到的那样:

Exception showing dynamic method call failing

我可以将参数显式转换为 double ,然后 .ToString("N3")有效,但只是在所谓的动态 value 上调用它论证失败。

但是,我可以使用以下代码在 C# 中执行此操作(使用 LINQPad)。 (注意,编译器不允许您在扩展方法中使用 dynamic 参数,所以这可能是问题的一部分。)
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;
    }
}

Dynamic method invocation in C# works

那么给了什么? VB中有没有一种方法可以在不使用反射的情况下动态调用函数的参数?

最佳答案

明确回答“VB中有没有一种方法可以在不使用反射的情况下对函数的参数动态调用方法?”:
编辑:我现在查看了一些 IL 反汇编(通过 LinqPad)并将其与 CallByName 的代码进行了比较。 (通过反射器)并使用 CallByName使用相同数量的 Reflection像往常一样,Option Strict Off后期绑定(bind)。
所以,完整的答案是:你可以用 Option Strict Off 来做到这一点。为所有 Object引用,除非您尝试的方法存在于 Object本身,您可以在其中使用 CallByName 获得相同的效果(事实上,不需要 Option Strict Off )。

Dim dynamicValue = CallByName(value, "ToString", CallType.Method, "N3")
注意 这实际上并不等同于后期绑定(bind)调用,它必须满足“方法”实际上是一个(n 索引)属性的可能性,因此它实际上调用了以下等价物:
Dim dynamicValue = CallByName(value, "ToString", CallType.Get, "N3")
对于其他方法,例如 Double.CompareTo .

细节
你的问题是 Object.ToString()存在,因此您的代码不尝试任何动态调度,而是在默认 String.Chars 上进行数组索引查找String 的属性(property)结果value.ToString()称呼。
您可以通过尝试 value.ToString(1,2) 来确认这是编译时发生的情况。 ,您更愿意尝试运行时查找两个参数 ToString ,但实际上失败了

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


在编译时。
您可以类似地确认所有其他非 Shared Object使用 callvirt 直接调用方法,依靠 Overrides在可用的情况下,不是通过调用 Microsoft.VisualBasic.CompilerServices.NewLateBinding 进行动态调度命名空间,如果您在 IL 中查看已编译的代码。

关于vb.net - VB中的动态方法调用没有反射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17819977/

相关文章:

c++ - 在动态数组上实现自己的快速排序

mysql - 将结果从一个类(class)发送到另一个类(class)

android - 不同的 Android 屏幕,不同的颜色,我们可以将屏幕编程为看起来相同吗?

c# - 需要 C# 代码使用 DataReader 从 Microsoft Access Attachment 数据类型读取多个附件

.net - My.Settings 不保存 ArrayList

c - 动态分配扫描失败数量

c# - 为什么 DynamicObject 类中的方法不是通用的?

algorithm - 动态编程间隔调度与作业之间的时间

.NET - Return 是否会阻止对象处理

javascript - 如何获得屏幕宽度和高度的解决方案?