.
Anmeldung | Registrieren | Hilfe
in Suchen

Übergabe von generischen Listen zwischen Anwendungsschichten

Letzter Beitrag 09. Mrz 2010 19:07 von akk. 6 Antworten.
Seite 1 von 1 (7 Treffer)
Beiträge sortieren: Zurück Weiter
  • 02. Mrz 2010 10:46

    • kristof
    • Top 500 Mitwirkender
    • Registriert am 12. Mrz 2009
    • Beiträge 4
    • Punkte 65

    Übergabe von generischen Listen zwischen Anwendungsschichten

    Hallo,

    ich habe gerade ein Problem, an dem ich mir etwas die Zähne ausbeiße und hoffe auf eine Eingebung eurerseits...

    Ich habe in meinem Business-Layer eine Klasse namens Person und in einer eigenen Assembly das dazugehörige Interface IPerson. Der BL referenziert auf den Data-Layer, der die Klasse PersonData enthält, die das Objekt füllen soll. BL und DL referenzieren beide auf die Interface-Assembly. 

    Zweck des Ganzen ist, dass der BL keine Datenzugriffskomponenten wie DataSets o.ä. kennen soll, sondern nur die Interfaces der Objekte.

    Im DL gibt es nun folgende Methode:

    Public Sub GetPerson(ByRef p As IPerson)
    
       'Füllen des Objekts
    
       '...
    
    End Sub

    Soweit so gut... 

    Nun möchte ich, um den Datenbank-Server zu schonen, eine Methode implementieren, die eine generische Liste als ByRef-Parameter enthält, die gefüllt werden soll, a la:

    Public Sub GetPersonList(ByRef lp As List(Of IPerson), ByVal strIDList As String)
       'Füllen der Liste mit Objekten anhand der ID-Liste<div>   '...
    
    End Sub

    Problem ist hier allerdings, dass ich ja keine neuen Instanzen von IPerson erstellen kann, die ich an die Liste anhängen könnte und der DL das Objekt Person ja nicht kennt?

    Gruss
    Kristof
    Abgelegt unter:
    • IP-Adresse ist Registriert
  • 02. Mrz 2010 10:54 Antwort zu

    • Nasenbaer
    • Top 25 Mitwirkender
      Männlich
    • Registriert am 07. Mrz 2008
    • Schweiz
    • Beiträge 97
    • Punkte 1.505

    Übergabe von generischen Listen zwischen Anwendungsschichten

    Hi

    Also auf die Schnelle sehe ich drei Möglichkeiten das zu lösen:
    1. Du erstellst eine "New List(Of IPerson)". Das müsste doch gehen. Und übergibst sie leer. New bezieht sich ja auf die neue Instanz der Liste und noch nicht auf IPerson.
    2. Du erstellst eine "New List(Of Object)".
    3. Du erstellst eine einfache Klasse mit einem Konstruktor für IPerson. Darin werden nur die Interfaces befriedigt, aber noch keine Daten verwaltet. Unschön aber wird bei API's manchmal so gemacht.

    Gruss
    Nase
    • IP-Adresse ist Registriert
  • 02. Mrz 2010 11:26 Antwort zu

    • kristof
    • Top 500 Mitwirkender
    • Registriert am 12. Mrz 2009
    • Beiträge 4
    • Punkte 65

    Übergabe von generischen Listen zwischen Anwendungsschichten

    Hi Nasenbaer,

    Danke für Deine Antwort...

    zu 1. 
    Das genau ist das Problem. Ich habe einen Instanz der LISTE, komme aber nicht an das Objekt selbst heran, um zum Beispiel zu sagen: lst.Add(<neues Objekt vom Typ Person>), weil ja Dim p As New IPerson nicht geht.

    zu 2. 
    Object ist blöd, weil ich im folgenden die reellen Eigenschaften von IPerson mit Daten aus der Datenbank füllen will: p.LastName = ...

    zu 3.
    Du meinst im DL für jedes Interface eine Dummy-Klasse? Quasi doppelte Arbeit im DL und BL?
    • IP-Adresse ist Registriert
  • 02. Mrz 2010 16:36 Antwort zu

    • Rainer Hilmer
    • Top 10 Mitwirkender
      Männlich
    • Registriert am 22. Jan 2008
    • Braunschweig
    • Beiträge 927
    • Punkte 14.105

    Übergabe von generischen Listen zwischen Anwendungsschichten

    Hallo Kristof,
    es gibt verschiedene Wege, Komponenten zu entkoppeln (ich glaube das ist es um was es hier im Prinzip geht). Sagen dir Schlagworte wie

    • Dependency Injection und IOC etwas?
    • DI/IOC Frameworks wie Unity, StructureMap, NInject, AutoFac?
    • Dazu kommen dann noch einige Design Patterns. Je nach Anforderung und gewünschter Architektur wären das z.B.
      • Bridge Pattern,
      • Mediator,
      • Adapter,
      • Proxy.

    Falls dir das alles nichts sagt, schlage ich vor, du beschäftigst dich für den Anfang einmal mit handgestrickter Dependency Injection. Ich melde mich gleich noch einmal mit Links zu dem Thema.

    Gruß,
    Rainer
    • IP-Adresse ist Registriert
  • 02. Mrz 2010 16:45 Antwort zu

    • Rainer Hilmer
    • Top 10 Mitwirkender
      Männlich
    • Registriert am 22. Jan 2008
    • Braunschweig
    • Beiträge 927
    • Punkte 14.105

    Übergabe von generischen Listen zwischen Anwendungsschichten

    Wie versprochen, ein paar Links:

    Thema Dependency Injection/IOC:
    http://martinfowler.com/articles/injection.html
    http://www.developer.com/net/net/print.php/11087_3636501_1

    DI/IOC Frameworks:
    Unity (Bestandteil der Enterprise Library): http://entlib.codeplex.com/
    Ninject: http://ninject.org/
    StructureMap: http://structuremap.sourceforge.net/Default.htm
    Autofac: http://code.google.com/p/autofac/
    Welches davon am besten ist, wage ich nicht zu beurteilen. Zum Teil hängt es auch vom persönlichen Geschmack ab.

    Thema Design Patterns:
    http://www.dofactory.com/Patterns/Patterns.aspx
    Das Internet ist voller Artikel zum Thema Design Patterns.

    Gruß,
    Rainer
    • IP-Adresse ist Registriert
  • 02. Mrz 2010 18:33 Antwort zu

    • kristof
    • Top 500 Mitwirkender
    • Registriert am 12. Mrz 2009
    • Beiträge 4
    • Punkte 65

    Übergabe von generischen Listen zwischen Anwendungsschichten

    Hallo Rainer,

    ich hab's mir fast gedacht. Ich dachte es gäbe schlicht einen schnelleren Weg. Die EntLib 5.0 planen wir für unser Projekt schon ein, also werde ich mir wohl Unity rein tun...

    Danke Dir
    • IP-Adresse ist Registriert
  • 09. Mrz 2010 19:07 Antwort zu

    • akk
    • Top 50 Mitwirkender
    • Registriert am 24. Nov 2009
    • Beiträge 49
    • Punkte 725

    Übergabe von generischen Listen zwischen Anwendungsschichten

    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.

    • IP-Adresse ist Registriert
Seite 1 von 1 (7 Treffer)

WPF Forum | ASP.NET Forum | ASP.NET MVC Forum | Silverlight Forum | Windows Phone 7 Forum | SharePoint Forum | Dotnet Jobs | Dotnet Termine | Developer Blogs | Dotnet News

Das Team | Regeln | Impressum