【问题标题】:Strongly Typing a LINQ Query using multiple keys of complex objects使用复杂对象的多个键强类型化 LINQ 查询
【发布时间】:2010-12-18 20:23:31
【问题描述】:

我不知道如何定义在我的 LINQ 分组查询中使用的对象以允许它们成为强类型。

我构建了一个使用两个复杂对象作为键的分组查询。查询有效,但我希望能够声明返回对象类型。

我有一个复杂类型...

Public Class Student
    Public Name As IndividualsName
    Public EnrolledSchool As School
    Public BirthHospital As BirthPlace
    Public Grade As Integer

    Public Sub New(ByVal name As IndividualsName, ByVal enrolledSchool As School, ByVal birthHospital As BirthPlace, ByVal grade As Integer)
        Me.Name = name
        Me.EnrolledSchool = enrolledSchool
        Me.BirthHospital = birthHospital
        Me.Grade = grade
    End Sub

End Class

Public Class School
    Inherits Location


    Public Sub New(ByVal name As String, ByVal city As String, ByVal state As String)
        MyBase.New(name, city, state)
    End Sub

    Public Shared Function GetMyHS() As School
        Return New School("My High School", "My City", "My State")
    End Function
    Public Shared Function GetYourHS() As School
        Return New School("Your High School", "Your City", "Your State")
    End Function
    Public Shared Function GetMyElementry() As School
        Return New School("My Elementary", "My City", "My State")
    End Function
    Public Shared Function GetMyMiddleSchool() As School
        Return New School("My Middle School", "My City", "My State")
    End Function

End Class

Public Class IndividualsName
    Public First As String
    Public Last As String

    Public Sub New(ByVal first As String, ByVal last As String)
        Me.First = first
        Me.Last = last
    End Sub

    Public Overrides Function ToString() As String
        Return First & " " & Last
    End Function
End Class

Public Class BirthPlace
    Inherits Location

    Public Sub New(ByVal name As String, ByVal city As String, ByVal state As String)
        MyBase.New(name, city, state)
    End Sub

    Public Shared Function GetMyHospital() As BirthPlace
        Return New BirthPlace("My General Hospital", "My City", "My State")
    End Function

    Public Shared Function GetYourHospital() As BirthPlace
        Return New BirthPlace("Your General Hospital", "Your City", "Your State")
    End Function
End Class

Public Class Location
    Public Name As String
    Public City As String
    Public State As String

    Public Sub New(ByVal name As String, ByVal city As String, ByVal state As String)
        Me.Name = name
        Me.City = city
        Me.State = state
    End Sub

    Public Overrides Function Equals(ByVal obj As Object) As Boolean
        Return Me.GetHashCode = obj.GetHashCode
    End Function

    Public Overrides Function GetHashCode() As Integer
        Dim returnValue As Integer
        returnValue = Me.Name.GetHashCode() Xor Me.City.GetHashCode() Xor Me.State.GetHashCode()
        Return returnValue
    End Function

End Class

我在一个列表中收集并根据两个复杂的键组合在一起。

Sub Main()

    Dim students As List(Of Student) = New List(Of Student)

    students.Add(New Student(New IndividualsName("Bill", "Jones"), School.GetMyHS(), BirthPlace.GetMyHospital(), 9))
    students.Add(New Student(New IndividualsName("George", "Jamesen"), School.GetMyHS(), BirthPlace.GetMyHospital(), 11))
    students.Add(New Student(New IndividualsName("Chris", "McCartney"), School.GetYourHS(), BirthPlace.GetMyHospital(), 9))
    students.Add(New Student(New IndividualsName("Sara", "Smith"), School.GetMyMiddleSchool(), BirthPlace.GetMyHospital(), 7))
    students.Add(New Student(New IndividualsName("Josh", "Jefferies"), School.GetMyMiddleSchool(), BirthPlace.GetYourHospital(), 8))
    students.Add(New Student(New IndividualsName("Mel", "Tompson"), School.GetMyHS(), BirthPlace.GetMyHospital(), 12))
    students.Add(New Student(New IndividualsName("Jill", "Schmidt"), School.GetYourHS(), BirthPlace.GetMyHospital(), 10))
    students.Add(New Student(New IndividualsName("Beth", "Taylor"), School.GetMyElementry(), BirthPlace.GetMyHospital(), 5))
    students.Add(New Student(New IndividualsName("Mark", "Thatcher"), School.GetMyElementry(), BirthPlace.GetMyHospital(), 4))
    students.Add(New Student(New IndividualsName("Tom", "Jones"), School.GetMyHS(), BirthPlace.GetYourHospital(), 9))
    students.Add(New Student(New IndividualsName("Kevin", "Woo"), School.GetMyMiddleSchool(), BirthPlace.GetYourHospital(), 7))

    Dim groupedQuery 'As IEnumerable(Of IGrouping())
    groupedQuery = From student In students _
                   Group student By student.EnrolledSchool, student.BirthHospital Into Group _
                 Select EnrolledSchool, BirthHospital, StudentGroup = Group

    For Each groupItem In groupedQuery
        Console.WriteLine(String.Format("School: {0}, Birth Place: {1}", groupItem.EnrolledSchool.Name, groupItem.BirthHospital.Name))
        'Console.WriteLine(String.Format("Group Item is type {0}.", groupItem.GetType()))

        For Each item As Student In groupItem.StudentGroup
            Console.WriteLine(String.Format("Name: {0} - Grade: {1}", item.Name.ToString(), item.Grade.ToString()))
        Next

    Next
End Sub

一切正常,但令我困扰的是,当我处理数据收集时,一切都是匿名声明的。如果创建分组列表的对象位于一个程序集中,并且正在 Web 服务和网站上使用,这尤其令人烦恼。

我真的希望能够强输入返回的 IEnumberable,但我不知道如何声明我的 IGrouping interface

我应该能够像...一样横穿我的数据结构

    Dim groupedQuery As IEnumerable(Of IGrouping(Of IDoNotKnowHowToDeclareMyComplexKey, Student))
    groupedQuery = From student In students _
                   Group student By student.EnrolledSchool, student.BirthHospital Into Group _
                 Select EnrolledSchool, BirthHospital, StudentGroup = Group

    For Each groupItem As IGrouping(Of IDoNotKnowHowToDeclareMyComplexKey, Student) In groupedQuery
        Console.WriteLine(String.Format("School: {0}, Birth Place: {1}", groupItem.Key.Name)
        For Each item As Student In groupItem
            Console.WriteLine(String.Format("Name: {0} - Grade: {1}", item.Name.ToString(), item.Grade.ToString()))
        Next

    Next

但到目前为止,我还没有弄清楚如何声明我的 IGrouping 类型。

【问题讨论】:

    标签: vb.net linq group-by strong-typing


    【解决方案1】:

    正如 Bryan 所说,创建一个新类:

    Public Class SomeName
        Public EnrolledSchool As School
        Public BirthHospital As BirthPlace
        Public StudentGroup As IEnumerable(Of Student)
    End Class
    

    然后在分组时使用它:

    Dim result As IEnumerable(Of SomeName)
    result = (From student In students _
     Group student By student.EnrolledSchool, student.BirthHospital Into Group _
     Select New SomeName With {.EnrolledSchool = EnrolledSchool, .BirthHospital = BirthHospital, .StudentGroup = Group})
    

    如果您有任何问题,请将您的代码和遇到的错误放在这里。

    【讨论】:

    • 完美。这正是我想要的。
    【解决方案2】:

    根据定义,如果某物是匿名的,则不能直呼其名。

    您应该创建一个代表复杂键类型的新类,并使用它来代替匿名类型。

    【讨论】:

    • 我尝试创建一个新类用作分组的键,但我无法将分组映射到该类型。我不断收到类型转换错误。
    猜你喜欢
    • 2021-03-24
    • 1970-01-01
    • 2015-03-06
    • 1970-01-01
    • 2018-10-14
    • 1970-01-01
    • 2018-02-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多