如何从VB.NET中的匿名类型获取属性

时间:2010-02-12 18:51:54

标签: .net asp.net vb.net linq anonymous-types

我试图弄清楚如何在当前函数中创建匿名类型时获取匿名类型对象的属性。

具体来说,我将ASP.NET ListView绑定到LINQ结果集,然后尝试处理ItemDataBound事件中的每个项目。

Option Explicit On
Option Strict On

Class MyPageClass

    Private Sub Bind()
        Dim items As ItemData = FetchItemData()

        Dim groups = From s In items Group s By Key = s.GroupId Into Group _
                Select GroupID = Key, GroupData = Group

        ' This works fine:
        Dim groupId As Integer = groups(0).GroupID

        lvGroups.DataSource = groups
        lvGroups.DataBind()
    End Sub

    Private Sub lvGroups_ItemDataBound(ByVal sender As Object, ByVal e As ListViewItemEventArgs) Handles lvGroups.ItemDataBound
        If e.Item.ItemType = ListViewItemType.DataItem Then
            Dim item As ListViewDataItem = DirectCast(e.Item, ListViewDataItem)
            Dim groupData = item.DataItem  ' This is the anonymous type {GroupId, GroupData}

            ' Next Line Doesn't Work 
            ' Error: Option Strict disallows late binding
            Dim groupId As Integer = groupData.GroupId

        End If
    End Sub

End Class

我需要在lvGroups_ItemDataBound()中做什么来获取item.DataItem.GroupId?

3 个答案:

答案 0 :(得分:4)

当您执行select时,要么创建一个要选择的类(选择新的MyClass With {prop assignmentments here}),以便MyClass是您可以返回的实际物理类。或者,您可以使用DataBinder类,如下所示:

DataBinder.GetPropertyValue(item.DataItem, "GroupId", null);

我相信我用它来获取一个值,它使用反射来检查底层类型。

答案 1 :(得分:1)

不幸的是,你几乎无能为力。匿名类型的用途仅限于创建它们的功能。一旦你将它们从函数中传递出去,你将失去所有强大类型的属性。这里最好的解决方案是创建一个非常小的结构,它封装了这些属性并使用它。

其他选项包括

  • 使用后期绑定。这毕竟是VB
  • 使用不安全的强制类型推理技巧使其再次强类型化。

我只提到了铸造技巧,因为它是一个有效的解决方案。然而,后期绑定更不安全,并且在两者之间做出选择我会选择后期绑定。

答案 2 :(得分:1)

以下是从Linq获取匿名类型项目到xml,然后通过电子邮件发送其属性的示例。 linq项目作为匿名类型传递给sendmail函数,它通过反射投资其属性:

Public Function ProcessFile(ByRef i_fullFilename As String) As String

    Dim result As String = String.Empty

    Try

        Dim xDoc As XDocument = XDocument.Load(i_fullFilename)

        Dim message = From q In xDoc.Descendants _
                      Where q.Name.LocalName = "ContinuousMessage" _
                      Select q

        Dim nsName As String = message.FirstOrDefault.Name.NamespaceName

        Dim ns As XNamespace = nsName

        Dim messageCollection = From msg In xDoc.Descendants(ns + "ContinuousMessage") _
                                Select customOfficeNumber = msg.Element(ns + "customOfficeNumber").Value, _
                                unitCode = msg.Element(ns + "unitCode").Value, _
                                leadingFileNumber = msg.Element(ns + "leadingFileNumber").Value, _
                                messageType = msg.Element(ns + "messageType").Value, _
                                note = msg.Element(ns + "note").Value, _
                                sendingOrPrintingDate = CType(msg.Element(ns + "sendingOrPrintingDate").Value, Date)

        Dim commonNsName As String = "http://com.com/some/common.xsd"
        Dim commonNs As XNamespace = commonNsName

        Dim tgpiCollection = From item In xDoc.Descendants(ns + "TPGIdentifier") _
                             Select fileNumber = item.Element(commonNs + "fileNumber").Value, _
                            numeral = item.Element(commonNs + "numeral").Value, _
                            fillingNumber = item.Element(commonNs + "FillingNumber").Value

        For Each item In messageCollection
            SendMail(item, "Info")
        Next

    Catch ex As Exception
        result &= ex.Message
    End Try

    Return result

End Function


Private Sub SendMail(ByRef i_item, ByVal i_errorDescriptionString)

    Dim email As New MailMessage
    email.From = New MailAddress("SuperPuperAutomaticCustomsProcessing@net.net")
    email.To.Add(New MailAddress("net@net.net"))
    email.Subject = "New message from customs received 5115"

    Dim name As String = String.Empty
    Dim value As String = String.Empty
    Dim body As String = String.Empty
    Dim nextLine As String = String.Empty

    Dim propertiesInfo As PropertyInfo() = i_item.GetType().GetProperties()
    For Each prop As PropertyInfo In propertiesInfo

        name = prop.Name
        value = prop.GetValue(i_item, Nothing)
        nextLine = String.Format("   {0}:  {1} {2}", name, value, vbCrLf)
        body = body & nextLine

    Next

    If Not String.IsNullOrEmpty(i_errorDescriptionString) Then
        nextLine = String.Format("   Error Description:  {1} {2}", name, i_errorDescriptionString, vbCrLf)
        body = body & nextLine
    End If

    email.Body = body


    Dim smtp As New SmtpClient()
    smtp.Host = "smtp.local"
    smtp.Send(email)

End Sub