Das Problem läßt sich auf ganz unterschiedliche Weisen lösen. Unter der Annahme, daß die Klasse Person keinen öffentlichen parameterlosen Konstruktor besitzt, gibt es die Möglichkeit, der Methode GetPersonList() eine Factory-Instanz mitzugeben, die in der Lage ist, die IPerson-implementierende Klasse zu erzeugen
Public Interface IPersonFactory
Function CreateInstance() As IPerson
End Interface
''' <summary>
''' Gibt eine Liste von IPerson-Instanzen zurück
''' </summary>
''' <param name="strIdList"></param>
''' <param name="itemFactory"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetPersonList(ByVal strIdList As String, ByVal itemFactory As IPersonFactory) As List(Of IPerson)
Dim RetVal As New List(Of IPerson)
Dim dt As DataTable
'Datenbankabfrage und Ergebnis in dt, simuliert durch New DataTable
dt = New DataTable
For Each row As DataRow In dt.Rows
Dim item As IPerson = itemFactory.CreateInstance()
'Daten zuweisen
Next
Return RetVal
End Function
Einfacher wird es, wenn besagter öffentliche parameterlose Konstruktor existiert. Dann ließe sich die Function GetPersonList() generisch formulieren:
''' <summary>
''' generischen Parameter sorgt dafür, daß Konstruktor aufrufbar ist, auch wenn der tatsächliche
''' Klassentype nicht bekannt ist
''' </summary>
''' <typeparam name="TItem"></typeparam>
''' <param name="strIdList"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetPersonList(Of TItem As {IPerson, New})(ByVal strIdList As String) As List(Of IPerson)
Dim RetVal As New List(Of IPerson)
Dim dt As DataTable
'Datenbankabfrage und Ergebnis in dt, simuliert durch New DataTable
dt = New DataTable
For Each row As DataRow In dt.Rows
Dim item As New TItem
'Daten zuweisen
Next
Return RetVal
End Function
Durch die Angabe (Of TItem As {IPerson, New}) erzwingt man, daß der Type TItem mit einem öffentlichen parameterlosen Konstruktor erzeugt werden kann, gleichzeitig aber auch die Schnittstelle IPerson implementiert. Auf Seiten der Geschäftslogik wird die Data-Layer Funktion GetPersonList() aufgerufen per
Dim list As List(Of IPerson) = dlObj.GetPersonList(Of Person)("Id1,Id2, ...")
Legt man zudem Wert auf die Tatsache, das die Rückgabeliste ein List(Of Person) ist, muß lediglich auf Data-Layer-Ebene die Funktion GetPersonList() definiert werden als
Public Function GetPersonList(Of TItem As {IPerson, New})(ByVal strIdList As String) As List(Of TItem)
Dim RetVal As New List(Of TItem)
Dim dt As DataTable
'Datenbankabfrage und Ergebnis in dt, simuliert durch New DataTable
dt = New DataTable
For Each row As DataRow In dt.Rows
Dim item As New TItem
'Daten zuweisen
Next
Return RetVal
End Function
Noch eine Anmerkung zu ByRef - Parametern. Sie sind nützlich, wenn mehr als ein Rückgabewert zurückgegeben werden soll oder der Rückgabewert selbst nur darüber informiert, ob der Funktionsaufruf erfolgreich war. Sie sind ebenfalls sinnvoll, wenn Structure-Instanzen übergeben werden, deren Inhalt durch die Routine modifiziert werden soll, da diese anders als Class-Instanzen nur als Kopie und nicht als Referenz übergeben werden. Wenn jedoch wie in der Problembeschreibung eine gültige Liste zu füllen ist, die per Parameter übergeben wird, ist ein ByVal völlig ausreichend, hat sogar den Vorteil, daß man sich und dem Programm den Overhead des Wert Zurückkopierens (Code wird vom Compiler automatisch erzeugt) erspart.