我试图弄清楚如何在当前函数中创建匿名类型时获取匿名类型对象的属性。
具体来说,我将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?
答案 0 :(得分:4)
当您执行select时,要么创建一个要选择的类(选择新的MyClass With {prop assignmentments here}),以便MyClass是您可以返回的实际物理类。或者,您可以使用DataBinder类,如下所示:
DataBinder.GetPropertyValue(item.DataItem, "GroupId", null);
我相信我用它来获取一个值,它使用反射来检查底层类型。
答案 1 :(得分:1)
不幸的是,你几乎无能为力。匿名类型的用途仅限于创建它们的功能。一旦你将它们从函数中传递出去,你将失去所有强大类型的属性。这里最好的解决方案是创建一个非常小的结构,它封装了这些属性并使用它。
其他选项包括
我只提到了铸造技巧,因为它是一个有效的解决方案。然而,后期绑定更不安全,并且在两者之间做出选择我会选择后期绑定。
答案 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