加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

vb.net – 在没有反射的情况下调用VB的动态方法

发布时间:2020-12-17 00:11:23 所属栏目:大数据 来源:网络整理
导读:我想使用方法调用格式化任何数字类型,如下所示: Option Infer OnOption Strict OffImports System.Runtime.CompilerServicesNamespace GPR Module GPRExtensions Extension() Public Function ToGPRFormattedString(value) As String ' Use VB's dynamic di
我想使用方法调用格式化任何数字类型,如下所示:
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 On,Dynamic Keyword equivalent in VB.Net?),我认为这个代码在传递数字类型(double,Decimal,int等)时会起作用.它没有,正如您在屏幕截图中看到的:

我可以显式地将参数转换为double,然后.ToString(“N3”)可以工作,但只是在所谓的动态值参数上调用它会失败.

但是,我可以使用以下代码在C#中完成它(使用LINQPad). (注意,编译器不允许您在扩展方法中使用动态参数,因此这可能是问题的一部分.)

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;
    }
}

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

要明确回答“VB中有没有办法在不使用反射的情况下动态调用函数的参数?”:

编辑:我现在回顾了一些IL反汇编(通过LinqPad)并将其与CallByName的代码(通过Reflector)进行比较,并使用CallByName使用与正常情况相同的反射量,Option Strict Off late binding.

因此,完整的答案是:对于所有Object引用,您可以使用Option Strict Off执行此操作,除非您尝试的方法存在于Object本身,您可以使用CallByName来获得相同的效果(事实上,不需要Option Strict Off).

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

NB这实际上并不等同于后期绑定调用,后者必须满足“方法”实际上是(n索引)属性的可能性,因此它实际上调用等效于:

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

对于其他方法,如Double.CompareTo.

细节

这里的问题是Object.ToString()存在,因此您的代码不会尝试任何动态调度,而是对该值的.ToString()调用的String结果的默认String.Chars属性进行数组索引查找.

您可以通过尝试value.ToString(1,2)来确认这是编译时发生的情况,您希望尝试对两个参数ToString进行运行时查找,但实际上是失败的

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

在编译时.

您可以类似地确认所有其他非共享对象方法是使用callvirt直接调用的,依赖于可用的覆盖,而不是通过调用Microsoft.VisualBasic.CompilerServices.NewLateBinding命名空间的动态调度,如果您查看IL中的编译代码.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读