2009-11-20 1 views
0

Je n'arrive pas à comprendre comment définir l'objet utilisé dans ma requête de regroupement LINQ pour leur permettre d'être fortement typé.Taper fortement une requête LINQ en utilisant plusieurs clés d'objets complexes

J'ai créé une requête de regroupement qui utilise deux objets complexes en tant que clés. La requête fonctionne, mais j'aimerais pouvoir déclarer le type d'objet de retour.

J'ai un type complexe ...

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 

que je collectionne dans une liste et regrouper à partir de deux clés complexes.

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 

Tout fonctionne, mais cela me dérange que lorsque je traite la collecte de données tout est déclaré de manière anonyme. Ceci est particulièrement gênant l'objet que crée la liste groupée dans un assemblage et il est consommé dans un service Web et sur un site Web.

Je voudrais vraiment être en mesure de taper fortement le IEnumberable qui est retourné, mais je ne peux pas comprendre comment déclarer mon IGrouping interface.

Je devrais pouvoir transversal ma structure de données comme ...

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 

, mais jusqu'à présent, je ne l'ai pas été en mesure de comprendre comment déclarer mon type de IGrouping.

Répondre

2

Comme Bryan dit, créer une nouvelle classe:

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

Ensuite, utilisez tout en regroupant:

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}) 

Si vous avez des problèmes, placez ici votre code et les erreurs que vous obtenez.

+0

Parfait. C'était exactement ce que je cherchais. –

1

Par définition, si quelque chose est anonyme, vous ne pouvez pas l'appeler par un nom.

Vous devez créer une nouvelle classe qui représente votre type de clé complexe et l'utiliser à la place des types anonymes.

+0

J'ai essayé de créer une nouvelle classe à utiliser comme clé pour le regroupement, mais je n'ai pas réussi à faire correspondre les regroupements à ce type. J'ai continué à obtenir des erreurs de conversion de type. –

Questions connexes