Laden...

Generische Basisklasse, spezielle Unterklasse, Erzeugung über Factorymethod

Erstellt von serial vor 13 Jahren Letzter Beitrag vor 13 Jahren 2.029 Views
S
serial Themenstarter:in
902 Beiträge seit 2007
vor 13 Jahren
Generische Basisklasse, spezielle Unterklasse, Erzeugung über Factorymethod

Hallo,

ich gaube ich habe wohl einen großen denkfehler, komme aber einfach nicht auf eine saubere lösung.

Folgendes Problem: Ich habe eine Basisklasse Repository<T>, welche in einem Presenter<T> verwendet wird.
Von diesem Repository habe ich ein spezielles abgeleitet: NewsRepository hat eine spezielle Methode zur Volltextsuche, die nur mit dem Datentyp News verwendet werden kann.
Zur Erzeugung benutze ich eine Factorymethod.

Basisklasse:


public class Repository<T> where T:class
    {
//Factorymethod
        public static Repository<T> Create()
        {
            if (typeof(T) == typeof(News))
                return (Repository<News>)new NewsRepository() as Repository<T>;
            return new Repository<T>();
        }
  //weitere Methoden
}

NewsRepository


public class NewsRepository:Repository<News>
    {
        public IEnumerable<News> Search(string searchTerm, IEnumerable<System.Linq.Expressions.Expression<Func<News, bool>>> filters, List<KeyValuePair<string, bool>> sorters, int maxCount, int skip, bool readOnly)
        {
           //suche
        }
    }

Und benutzung im Presenter:


 public abstract class DataPresenterBase<T> : PresenterBase, IDataPresenterBase where T: class {
        protected List<T> _data;
        protected Repository<T> _repository = Repository<T>.Create();

So, nun meine Frage, ist die Factorymethod so wirklich eine schöne Lösung?
Für mich sieht das sehr "gehackt" aus, geht das schöner?
Und 2tens, um dieses ewsRepository zu benutzen, komme ich im NewsPresenter:DataPresenterBase<News> nicht um einen cast herum, oder?

ich hoffe ihr könnt mir die erleuchtung bringen...

mfg
serial

5.941 Beiträge seit 2005
vor 13 Jahren

Hoi serial

IoC / DI 😃

Und nein, um den Cast kommst du nicht herum, wenn du auf dem Typen Repository<T> arbeitest.

Daher würde ich eher empfehlen, zumindest für das NewsRepository einen eigenen Kontrakt (Interface) zu benutzen, was dann auch z.B. IRepository<T> implementiert.

Danach: Entweder eigene Instanziierung oder IoC / DI.
Generalisierung ist gut und schön, aber in diesem Fall schadet sie dir mehr, als sie nützt.
Du kannst aber die Generalisierung (Repository<T> / IRepository<T>) nutzen, wo du nur das brauchst.

Ansonsten musst du casten oder erzeugst dir direkt ein NewsRepository.

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

C
224 Beiträge seit 2009
vor 13 Jahren

Hi,

das sieht mir alles sehr kompliziert aus (Klassendesign).

Brauchst Du überhaupt solch generische Klassen?
Ich würde zusehen, dass ich bei


public abstract class DataPresenterBase<T> : PresenterBase, IDataPresenterBase where T: 

das <T> loswerde.

Muss die Klasse abstrakt sein bzw. gibt es einen anderen Weg ohne abstrakte Klasse?

Versuche es mal ohne wheres und abstracts.
Falls nötig wie Peter schreibt mit Interfaces.

Ich kenne Deine Aufgabe nicht.
Von daher verzeih' diese plumpe Antwort.

Gruß, CoLo

S
serial Themenstarter:in
902 Beiträge seit 2007
vor 13 Jahren

Hallo,

das T brauch ich, da es ein Repository für Linq-Objekte ist, und ich hier den Linq-Typ als T angebe.

mfg
serial

S
443 Beiträge seit 2008
vor 13 Jahren

also einerseits finde ich

        public static Repository<T> Create()
        {
            if (typeof(T) == typeof(News))
                return (Repository<News>)new NewsRepository() as Repository<T>;
            return new Repository<T>();
        }

relative umständlich
ein

return new NewsRepository(); 

reicht da vollkommen.

und bei einem where T: class bin ich auch leicht irretiert, das ist gerade soviel Einschränkung dass keine Valuetypes genommen werden können, aber dennoch sehr nahe bei object.
Ist das ein gewünschtes Verhalten?

mbg
Rossegger Robert
mehr fragen mehr wissen

Montag morgen ist die beste Zeit um eine erfolgreiche Woche zu beginnen

S
serial Themenstarter:in
902 Beiträge seit 2007
vor 13 Jahren

ein ... reicht da vollkommen.

nein leider reicht das nicht, da es nicht implizit gecastet werden kann, darum brauch ich dieses konstrukt.

und bei einem where T: class bin ich auch leicht irretiert, das ist gerade soviel Einschränkung dass keine Valuetypes genommen werden können, aber dennoch sehr nahe bei object.
Ist das ein gewünschtes Verhalten?

Ja das ist gewollt, da ich keine basisklasse bzw interfaces für die linq-objekte besitze.

mfg
serial

S
443 Beiträge seit 2008
vor 13 Jahren

richtig, sorry, aber beide Arten von cast brauchst Du nicht, es genügt das 'as'

und wenn das so gewollt ist, ich kenne natürlich nicht die genauen Anforderungen dann wird der code auch so passen.

Aber generell, wenn ich so einen Code schreibe, denke ich nochmal darüber nach ob ich nicht die Anforderungen an die Suche umgestalten kann.

mbg
Rossegger Robert
mehr fragen mehr wissen

Montag morgen ist die beste Zeit um eine erfolgreiche Woche zu beginnen