我想使用方法调用来格式化任何数字类型:
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")
可以工作,但只是在所谓的动态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;
}
}
那是什么给出的? VB中有没有办法在不使用反射的情况下动态调用函数的参数?
答案 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);
}