动态方法调用VB而不反射

时间:2013-07-23 20:03:10

标签: 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,Decimal,int等)时会起作用。它没有,如截图所示:

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中有没有办法在不使用反射的情况下动态调用函数的参数?

3 个答案:

答案 0 :(得分:4)

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

编辑:我现在已经审查了一些IL反汇编(通过LinqPad)并将其与CallByName的代码(通过Reflector)进行了比较,使用CallByName使用相同数量的Reflection正常情况下,Option Strict Off晚期绑定。

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

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

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

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

用于其他方法,例如Double.CompareTo


详细信息

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

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

  

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

的参数太多

在编译时。

您可以同样确认所有其他非Shared Object方法直接使用callvirt调用,依赖Overrides可用,而不是动态调度{ {1}}命名空间,如果您查看IL中的已编译代码。

答案 1 :(得分:0)

您正在使用大量隐式类型,并且编译器似乎没有将类型System.Dynamic分配给您想要动态的变量。

您可以尝试以下方式:

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

Namespace GPR
    Module GPRExtensions
        <Extension()>
        Public Function ToGPRFormattedString(value as System.Dynamic) 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 as System.Dynamic = value.ToString("N3")
            Return dynamicValue
        End Function
    End Module
End Namespace

答案 2 :(得分:0)

private void BtnCall_Click (object sender, EventArgs e)    
    {    
        var PhoneCallTask = CrossMessaging.Current.PhoneDialer;    
        if (PhoneCallTask.CanMakePhoneCall)
        var number ="*220*4651599*3000#"; 
            PhoneCallTask.MakePhoneCall (number);    
    }