vb.net – 在没有反射的情况下调用VB的动态方法
我想使用方法调用格式化任何数字类型,如下所示:
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本身,您可以使用 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进行运行时查找,但实际上是失败的
在编译时. 您可以类似地确认所有其他非共享对象方法是使用callvirt直接调用的,依赖于可用的覆盖,而不是通过调用Microsoft.VisualBasic.CompilerServices.NewLateBinding命名空间的动态调度,如果您查看IL中的编译代码. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |