2009-09-26 3 views
11

Ich habe einfachere Anwendungen wie Nerddinner und ContactManager sowie kompliziertere wie Kigg betrachtet. Ich verstehe die einfacheren und jetzt möchte ich die komplexeren verstehen.Meine MVC auf die nächste Ebene bringen: DI und Unit of Work

Normalerweise haben die einfacheren Anwendungen Repository-Klassen und -Schnittstellen (so lose wie möglich) über LINQtoSQL oder das Entity Framework. Die Repositories werden von den Controllern aufgerufen, um die notwendigen Datenoperationen durchzuführen.

Ein gemeinsames Muster, das ich sehe, wenn ich kompliziertere Anwendungen wie KIGG oder Oxite ist die Einführung prüfen (ich nur der Oberfläche kratzen hier, aber ich habe irgendwo beginnen):

  • IOC DI (in KIGG des Fall Unity)
  • Web anfordern Lebensdauer Manager
  • Arbeitseinheit

Hier sind meine Fragen:

Ich verstehe, dass Sie etwas Unity verwenden müssen, um wirklich eine lose gekoppelte Anwendung zu haben. Es scheint aber auch so zu sein, dass Sie in dem Moment, in dem Sie Unity in den Mix einführen, auch einen Web Request Lifetime Manager einführen müssen. Warum das? Warum haben Beispielanwendungen wie Nerddinner keinen Web Request Lifetime Manager? Was genau macht es? Ist es eine spezielle Einheit?

Ein zweites Muster, das ich bemerke, ist die Einführung der Einheit der Arbeit. Noch einmal dieselbe Frage: Warum benutzt Nerddinner oder ContactManager nicht Unit of Work? Stattdessen verwenden diese Anwendungen die Repository-Klassen oberhalb von Linq2Sql oder Entity Framework, um die Datenbearbeitung durchzuführen. Keine Spur von einer Arbeitseinheit. Was genau ist es und warum sollte es verwendet werden?

Dank

Unten finden Sie ein Beispiel für DI in Nerddiner am DinnersController Ebene:

public DinnersController() 
     : this(new DinnerRepository()) { 
    } 

    public DinnersController(IDinnerRepository repository) { 
     dinnerRepository = repository; 
    } 

So ist mir, dass der Controller „Eigentümer“ der DinnerRepository wegen des ersten Konstruktor Recht zu übernehmen und es wird daher von der Lebensdauer des Controllers abhängen, da er dort deklariert ist?

Antwort

3

Mit Linq-to-SQL direkt verwendet wird, besitzt der Controller den Verweis auf den Datenkontext . Es ist normalerweise eine private Referenz innerhalb des Controllers und wird daher als Teil seiner Konstruktion erstellt. Das Lifetime Management ist nicht notwendig, da es an einem Ort ist.

Wenn Sie jedoch einen IoC-Container verwenden, wird Ihr Datenrepository außerhalb Ihres Controllers erstellt. Da IoC-Container, die es für Sie erstellen, nicht wissen, wie und wie lange Sie das erstellte Objekt verwenden werden, wird eine lebenslange Strategie eingeführt.

Zum Beispiel, Datenkontext (Repository) wird in der Regel am Anfang der Web-Anfrage erstellt und am Ende zerstört. Für Komponenten, die mit einem externen Webdienst oder einem statischen Mapper (z. B. Logger) arbeiten, müssen sie jedoch nicht jedes Mal neu erstellt werden. Sie können also sagen, sie einmal zu erstellen (d. H. Singleton Lebensstil).

All dies geschieht, weil IoC-Container (wie Unity) für viele Situationen ausgelegt sind und Ihre spezifischen Bedürfnisse nicht kennen. Zum Beispiel verwenden einige Anwendungen "Conversation" -Transaktionen, bei denen NHibernate (oder Entity Framework möglicherweise) während mehrerer Seiten/Web-Anfragen dauern kann. Mit IoC-Containern können Sie Objekte lebenslang an Ihre Bedürfnisse anpassen. Aber wie gesagt, das hat seinen Preis - da es keine einzige vordefinierte Strategie gibt, müssen Sie selbst eine auswählen.

Warum NerdDinner und andere Anwendungen keine fortgeschritteneren Techniken verwenden, ist einfach, weil sie MVC-Funktionen, nicht fortgeschrittene Verwendungen einiger anderer Bibliotheken demonstrieren sollen. Ich erinnere mich an einen Artikel, der geschrieben wurde, um die erweiterte Funktionalität eines IoC-Containers zu demonstrieren - dieser Artikel hat einige genehmigte Designmuster wie die Trennung von Bedenken gebrochen - aber das war nicht so wichtig, weil Designmuster nicht das Ziel des Artikels waren. Dasselbe gilt für einfache MVC-Demo-Anwendungen - sie wollen nicht, dass Sie, der MVC-Neuling, in IoC-Labyrinthe verloren gehen.

Und ich würde nicht Oxite als gestalterisches Referenzbeispiel aussehen empfehlen: http://codebetter.com/blogs/karlseguin/archive/2008/12/15/oxite-oh-dear-lord-why.aspx http://ayende.com/Blog/archive/2008/12/19/oxite-open-exchangable-informative-troubled-engine.aspx

+0

Vielen Dank! Das hat geholfen. Ich habe meine Frage unten bearbeitet. Ist das das, was Sie meinen, wenn Sie sagen, dass der Controller die Referenz zum Repository/Datenkontext besitzt? – Thomas

+0

Nicht genau. In NerdDinner verwenden sie einen zusätzlichen Konstruktor, der IDinnerRepository annimmt, um Komponententests einfacher zu machen. Aber ja, es ist immer noch entweder Controller (parameterloser Konstruktor) oder Tests, die das Repository-Objekt erstellen und besitzen. Sie sterben beide und es gibt keine anderen Benutzer des Repositories; so ist das Leben einfach. Übrigens ist eine solche Technik schlecht; Sie können mehr darüber hier lesen: http://www.losetechies.com/blogs/jimmy_bogard/archive/2009/07/03/how-not-to-do-pendency-injection-in-nerddinner.aspx (wie auch als Google für "IoC des armen Mannes"). – queen3

+0

Jimmy Bogards Argument, dass dies ein eklatantes Beispiel für den "IoC des armen Mannes" sei, ist hier extrem gut. Die Kommentare sind auch gut. Auf jeden Fall eine Lektüre wert. –

0

Die meisten wenn nicht alle DI Container berühren das Konzept der Lebenszeit, glaube ich. Je nach betroffenem Szenario möchten Sie möglicherweise, dass der Container immer dieselbe Instanz einer registrierten Komponente zurückgibt, während Sie bei einer anderen Komponente immer eine neue Instanz zurückgeben möchten. Bei den meisten Containern können Sie auch angeben, dass innerhalb eines bestimmten Kontexts dieselbe Instanz usw. zurückgegeben werden soll.

Ich kenne die Einheit nicht sehr gut (bisher habe ich Windsor und Autofac verwendet), aber ich den Webanforderungslebensdauermanager als eine Implementierung von Lebensdauerstrategien ansehen, bei denen dieselbe Instanz während der Lebensdauer einer einzelnen Webanforderung vom Container bereitgestellt wird. Sie werden ähnliche Strategien in Containern wie Windsor finden.

Schließlich, ich nehme an, Sie beziehen sich auf Unit of Work. Eine Arbeitseinheit ist im Wesentlichen eine Gruppe von Aktionen, die als eine atomare Geschäftstransaktion erfolgreich sein oder fehlschlagen sollen. Für eine formalere Beschreibung, schauen Sie sich Martin Fowlers definition an. Es ist ein Konzept, das im Zusammenhang mit Domain Driven Design an Popularität gewonnen hat. Eine Arbeitseinheit verfolgt die Änderungen, die Sie in einer solchen Transaktion anwenden, und wenn die Zeit reif ist, werden diese Änderungen in einer ACID-Transaktion bestätigt. In NHibernate z.B.unterstützt die Sitzung den Begriff der Arbeitseinheit und genauer die Änderungsverfolgung, während in Linq2SQL der Kontext ...

Verwandte Themen