公共成员' ToCSVValue'在类型'整数'找不到VB扩展方法

时间:2016-08-17 00:50:20

标签: vb.net extension-methods

我正在尝试基于Scott Hanselman's blog在VB中编写ToCSV()扩展名。可能是我的C#到VB不正确,但一切看起来都是正确的。 我添加了一个模块:

<System.Runtime.CompilerServices.Extension>
Public Function ToCSV(Of T)(items As IEnumerable(Of T)) As String
    Try

        Dim csvBuilder = New StringBuilder()
        Dim properties = GetType(T).GetProperties()

        For Each item As T In items

            '' Test Code
            Dim newline As String = ""
            For Each l2 As Reflection.PropertyInfo In properties

                ' This works
                newline &= l2.GetValue(item, Nothing)

                ' This works too
                Dim int As Integer = 1234
                Dim s As String = int.ToCSVValue()

                'This works
                Dim nl = l2.GetValue(item, Nothing)

                ' This blows up with "Public member 'ToCSVValue' on type 'Integer' not found."  
                ' The Debugger type shows "Object {Integer}" which I assume to mean that the debugger interprets the object as an integer.
                nl = nl.ToCSVValue()
            Next

            ' Original code
            Dim line As String = String.Join(",", properties.Select(Function(p) p.GetValue(item, Nothing).ToCSVValue()).ToArray())
            csvBuilder.AppendLine(line)
        Next

        Return csvBuilder.ToString()

    Catch ex As Exception
        Throw
    End Try

End Function


<System.Runtime.CompilerServices.Extension>
Private Function ToCSVValue(Of T)(item As T) As String

    If item Is Nothing Then
        Return """"""
    End If

    If TypeOf item Is String Then
        Return String.Format("""{0}""", item.ToString().Replace("""", "\"""))
    End If
    Dim dummy As Double
    If Double.TryParse(item.ToString(), dummy) Then
        Return String.Format("{0}", item)
    End If
    Return String.Format("""{0}""", item)

End Function

当我用以下内容打电话时:

Dim s As String = ctx.Customers.Where(Function(x) x.CustomerID = 123456).Select(Function(x) New With {.CustomerID = x.CustomerID, .CustomerName = x.CustomerName}).ToCSV()

它到达ToCSV功能就好了。它识别传入的项目。它抽出第一个项目并看到其中有2个字段。一切都好!

GetValue()工作正常。

如果我创建一个静态整数并在其上调用ToCSVValue,它可以正常工作。 如果我创建一个静态字符串并在其上调用ToCSVValue,它可以正常工作。

当我在GetValue()上调用ToCSVValue时,我得到: 公共成员&#39; ToCSVValue&#39;在类型&#39;整数&#39;没找到。

同样,如果我在数据集中只有字符串,我得到: 公共成员&#39; ToCSVValue&#39;在类型&#39;字符串&#39;没找到。

理想情况下,这可以在&#34;原始代码&#34;中使用。部分,我可以杀死所有其他测试代码。

任何人都可以告诉我发生了什么以及为什么&#34;(Of T)&#34;是不是使用get getValue()类型,但是它适用于直接转换类型?

2 个答案:

答案 0 :(得分:1)

您需要选择“推断”&#39;。 当我使用Option Infer On时,它可以正常工作。

如果你不使用它,那么VB正在使用&#39;对象&#39;每当你离开这个类型时。

此外,虽然这不会导致您的问题,但ToCSV方法的正确转换是:

Public Function ToCSV(Of T As Class)(items As IEnumerable(Of T)) As String

答案 1 :(得分:0)

简短的回答是,将其称为方法ToCSVValue(p.GetValue(item, Nothing))将与C#版本一样。

答案越长,您就无法在VB中Object调用扩展方法。在VB中Object更像是C#中的dynamic。例如:

<Extension()> Function toStr(Of T)(item As T) As String
    Return item.ToString
End Function

然后这将导致编译时警告&#34; Late bound resolution; runtime errors could occur.&#34;和运行时错误&#34; Public member 'toStr' on type 'Integer' not found.&#34;,但它可以在C#中工作:

Dim i As Object = 123
Dim s = i.toStr