2010-10-06 22 views
10

Ich versuche, ziemlich große (für mich) Problem zu überrennen, dass ich beim Schreiben meiner Anwendung stieß. Schauen Sie sich das bitte an (ich werde versuchen, den Code für die Einfachheit zu kürzen):Interfaces Vererbung in C#

Ich habe Root-Schnittstelle namens IRepository<T>. Als nächstes IBookRepository : IRepository<Book> nächstes werden konkrete Klasse, die es implementiert: BookRepository : IBookRepository

In der RepositoryManager Klasse deklariert ich private IRepository<IRepoItem> currentRepo;

IRepoItem ist eine Schnittstelle, die durch Buch-Klasse implementiert wird.

Jetzt, wenn ich versuche, so etwas zu tun:

currentRepo = new BookRepository(); 

Visual Studio Fehlermeldung gibt:

kann nicht implizit Typ umwandeln 'BookRepository' auf 'IRepository'. Eine explizite Konvertierung vorhanden ist (möglicherweise fehlt eine Guss?)

Ich habe versucht, explizit zu werfen, aber Laufzeit Ausnahme ausgelöst wird ...

I (fast sicher) wissen, dass es etwas namens Kovarianz und das ist (wahrscheinlich) in .Net 4.0 gelöst. Leider schreibe ich mit Framework-Version 3.5, und ich kann das nicht ändern. Bitte geben Sie mir einige Ratschläge, wie Sie dieses Problem lösen können. Ich möchte currentRepo von RepoFactory erhalten, das nur wenige Arten von Repositories produziert, abhängig von den Bedürfnissen der Benutzer. Ich weiß nicht, ob Links hier erlaubt sind, aber ich schreibe eine Art Blog unter http://olgatherer.wordpress.com/, wo ich die Erstellung von Anwendungen beschreibe. Mein Englisch ist nicht gut, aber ich hoffe, dass es genug ist, um mich zu verstehen. Vielen Dank im Voraus für die Antwort.

Mit freundlichen Grüßen, skrzeczowas

+0

Was ist der deklarierte Typ von currentRepo? –

+0

Macht nichts, ich sehe es ist ein IRepository . –

Antwort

4

In .NET 3.5 Sie auf keinen Fall eine IRepository<Book> als IRepository<IRepoItem> behandeln kann.

Wir bräuchten mehr darüber wissen, was Sie das Repository verwenden für in RepositoryManager wirklich zu wissen, wie es zu lösen ... aber könnten Sie eine nicht-generic IRepository Schnittstelle schaffen, die IRepository<T> erstreckt? Machen Sie es alle Mitglieder ein, die sich nicht auf T beziehen. Dann können Sie currentRepo als nur IRepository deklarieren.

+0

+1 - Ich dachte über dieses nicht-generische 'IRepository'-Interface nach, war mir aber nicht sicher, wie ich es bringen sollte. Ausgezeichneter Jon! =) –

+0

Hallo nochmal! Ich habe Repositories in der hier beschriebenen Weise: http://olgatherer.wordpress.com/2010/08/18/repositorysrus/ Und ich erstellte DbManager, um die Datenbank zu verwalten und Repositories für jede der Tabellen zu erstellen (Bücher, Comics, Poststempel usw.)). Jetzt möchte ich, dass CurrentRepository in DbManager BookRepository, StampsRepository, was auch immer sein könnte - ich dachte, dass diese Sache mit Schnittstellen wäre OK, aber leider nicht, weil IRepoItem (wie ich heute realisiere) alle anderen Eigenschaften dann haben sollte ... :( – skrzeczowas

0

In .NET 3.5 gibt es keine Beziehung zwischen IRepository und IRepository in .NET 4, könnten Sie so etwas wie dies mit Kovarianz und Kontra Unterstützung erreichen (aber es hängt von der IRepository Interface-Deklaration)

A würde Empfehlen Sie eine nicht-allgemeine IRepository-Schnittstelle und machen Sie die Besetzung selbst. Ich weiß, es ist nicht wunderbar, aber die Funktionalität, die Sie beschreiben, erfordert Unterstützung von Kovarianz/Kontravarianz.

+0

Vielen Dank für diese Antwort, ich habe diese unten verwendet und erkannte, dass dies nicht völlig zu mir passt :(Ich weiß nicht, was jetzt zu tun ist ... IRepoItem konnte nicht alle Eigenschaften, die Bücher, Comics, Briefmarken consits von :( – skrzeczowas

1

Versuchen Sie, die Zwischenschicht (iRep) mit: Sie können

interface IRepository<T> 
    { 
    } 

    interface IRep<T> : IRepository<IRepoItem> where T : IRepoItem 
    { 
    } 

    interface IBookRepository : IRep<Book> 
    { 
    } 

    class BookRepository : IBookRepository 
    { 
    } 

dann tun, was Sie wollen:

 BookRepository br = new BookRepository(); 
     IRepository<IRepoItem> currentRepo = br; 
+0

Hallo! Das ist großartig und sehr elegant, ich bin sehr froh, dass Sie dies gepostet. Leider, wie ich im Kommentar zu oben Post beschrieben, erkannte ich, dass dies nicht völlig zu mir passt. IRepoItem ist eine Schnittstelle, die in Büchern, Stempeln, Comics implementiert wäre, also hätte sie alle Eigenschaften für verschiedene Elemente, das ist nicht schlau und ich muss einen anderen Weg finden, um das zu erreichen, was ich will - das heißt, dass ich currentRepo haben möchte BookRepository oder StampsRepository oder was auch immer anderes Repository ... Vielleicht eine Hilfe, bitte? – skrzeczowas

+0

IRepoItem eine Schnittstelle für andere Sachen sollte nur dazu führen, dass sie die Dinge, die sie gemeinsam haben, konsolidieren, nicht "alle Eigenschaften". Zum Beispiel IMoveable sollte nur die Move-Methode verfügbar machen, nicht alles, was alle Klassen (wie Cheetah, Car, Airplane) davon abgeleitet haben. – Grozz

+0

Aber wenn ich, sagen wir mal, currentRepo = StampsRepo(); habe, kann ich nur Methoden verwenden, aus denen IRepository besteht. Ich kann nicht IStampsRepository Methoden verwenden :(Ich glaube, dass ich dann fragen kann, welchen Typ diese currentRepo ist: Wenn (currentRepo ist IBookRepository) etwas anderes tun, wenn (currentRepo ist IStampsRepository) etwas tun ... Aber das ist nicht gutes Objektprogrammieren, denke ich, ich muss alle Annahmen neu überdenken, denn vielleicht ist das, was ich will, dumm und nicht zu erreichen ... – skrzeczowas