Wie organisiere ich C # -Klassen, die voneinander erben, aber auch Eigenschaften besitzen, die von einander erben?

8

Ich habe eine Anwendung mit einem Konzept von Venue , einem Ort, an dem Ereignisse passieren. A Venue hat viele VenuePart s. So sieht es also aus:

%Vor%

A Venue kann ein GolfCourseVenue sein, was ein Venue ist, das eine Steigung und eine bestimmte Art von VenuePart hat, die HoleVenuePart heißt:

%Vor%

Möglicherweise gibt es in Zukunft auch andere Arten von Venue s, die alle von Venue erben. Sie können ihre eigenen Felder hinzufügen und haben immer VenuePart s ihres eigenen spezifischen Typs.

Hier sind die VenuePart -Klassen:

%Vor%

Meine obigen Deklarationen scheinen falsch, weil ich jetzt ein GolfCourseVenue mit zwei Sammlungen habe, wenn es wirklich nur eins hätte. Ich kann es nicht überschreiben, weil der Typ anders ist, oder? Wenn ich Berichte ausführe, möchte ich mich generisch auf die Klassen beziehen, wo ich nur Venue s und VenuePart s ausspucke. Aber wenn ich Formen und dergleichen rende, möchte ich spezifisch sein.

Ich habe viele Beziehungen wie diese und frage mich, was ich falsch mache. Zum Beispiel habe ich eine Order , die OrderItem s hat, aber auch bestimmte Arten von Order s, die bestimmte Arten von OrderItem s haben.

Update: Ich sollte beachten, dass diese Klassen Entity Framework Code-First-Entitäten sind. Ich hatte gehofft, das würde nichts ausmachen, aber ich denke, es könnte sein. Ich muss die Klassen so strukturieren, dass Code-First Tabellen korrekt erstellen kann. Es sieht nicht so aus, als könnte Code-First mit Generika umgehen. Es tut uns leid, dass dieses Implementierungsdetail einer eleganten Lösung im Wege steht: /

Update 2: Jemand, der mit einer Suche verbunden ist, die auf Kovarianz und Kontravarianz zeigt , was eine Möglichkeit zu sein scheint, Listen innerhalb von Subtypen selbst auf einen bestimmten Subtyp zu beschränken. Das scheint wirklich vielversprechend, aber die Person löschte ihre Antwort! Hat jemand Informationen darüber, wie ich diese Konzepte nutzen kann?

Update 3: Die Navigationseigenschaften von untergeordneten Objekten wurden entfernt, da sie Personen verwirrten und nicht zur Beschreibung des Problems beitrugen.

    
Chris 27.03.2012, 17:26
quelle

4 Antworten

2

Hier ist eine mögliche Option mit Generics:

%Vor%

Hier hat GolfCourseVenue die Sammlung VenueParts, die HoleVenueParts oder Super-Klassen HoleVenueParts enthalten kann. Andere Spezialisierungen von Venue würden VenueParts beschränken, VenueParts zu enthalten, die für diesen Ort spezifisch sind.

Eine zweite Möglichkeit ist ungefähr so, wie Sie sie hatten

%Vor%

Jetzt hat GolfCourseVenue die Sammlung VenueParts, die VenueParts oder Superklassen VenueParts enthalten kann. Hier können alle Spezialisierungen von Venue jede Art von VenuePart enthalten, die geeignet oder nicht geeignet sein kann.

Als Antwort auf Ihren Kommentar zur Kovarianz würde ich etwas vorschlagen:

%Vor%     
Phil 27.03.2012, 17:35
quelle
1

Ich freue mich auf den Rat anderer - aber mein Ansatz besteht darin, in diesem Fall Generika zu verwenden. Bei Generika sind die "Teile" von GolfCourseVenue stark typisiert!

... und wenn ich das schreibe, sagt jeder andere auch Generika. WIE überstotzen Sie so schnell wie möglich?!

Wie auch immer, so tun, als wäre ich immer noch der Erste -

%Vor%

Als zweite Option können Sie auch eine Schnittstelle verwenden. Wenn Sie den Namen Parts nicht mögen, können Sie ihn als Holes bezeichnen, wenn der abgeleitete Typ als GolfCourse bekannt ist

%Vor%     
payo 27.03.2012 17:43
quelle
1

Sie können Covariance

verwenden %Vor%

Angenommen, HoleVenuePart wird von VenuePart geerbt

    
Anurag Ranjhan 27.03.2012 17:43
quelle
0

Wenn Sie "set" Teile beider Sammlungen entfernen, wird es mehr Sinn ergeben: Basisklasse bietet "alle Teile" Sammlung, während abgeleitete Klassen gefilterte Ansicht zusätzlich zur Basisklasse eins haben.

Hinweis: Je nach Ihren Anforderungen kann GolfVenue zur Spezialisierung werden. generic of Venue<VenuePart> funktioniert möglicherweise nicht, da Venue<Type1> und Venue<Type2> keine gute Basisklasse haben, mit der Sie arbeiten können.

Erwägen Sie die Verwendung von Schnittstellen anstelle von Basisklassen, da dies mehr Flexibilität bei der Implementierung ermöglichen würde.

%Vor%

Nun können Sie GolfCourse: Venue von anderen Samples verwenden, aber da es Interface implementiert, können Sie es auch auf eine genderische Weise handhaben:

%Vor%

Beachten Sie, dass GolfCourse und OtherPlace keine gemeinsame Elternklasse (außer Objekt) haben, also ohne Schnittstelle können Sie sie nicht gegenseitig verwenden.

    
Alexei Levenkov 27.03.2012 18:20
quelle

Tags und Links