5

ich eine Basis abstrakte Klasse und seiner abstrakten Typ-Parameter haben, wie:Handhabung Klassen inhärent von der abstrakten Klasse und Typ-Parameter

public abstract class Database<T> where T : DatabaseItem, new() { 
    protected List<T> _items = new List<T>(); 
    protected virtual void Read (string[] cols) { 
    T item = new T(); 
    ... 
} 

public abstract class DatabaseItem { 
    ... 
} 

Dann habe ich Kinder Anzahl der Klassen inhärenten von ihm haben:

public class ShopDatabase : Database<ShopItem> {} 
public class ShopItem : DatabaseItem {} 

public class WeaponDatabase : Database<WeaponItem> {} 
public class WeaponItem : DatabaseItem {} 

... 

Nun möchte ich ein Dictionary setzen, um die Datenbanken zu verfolgen und eine Methode, um sie unter Verwendung DatabaseItem Typ, etwas wie folgt zurückgeben:

Dictionary<Type, Database<DatabaseItem>> databases; 

public static Database<T> GetDatabase<T>() where T: DatabaseItem { 
    return databasebases [typeof (T)]; 
} 

Dann gab es mir Fehler „‚T‘einen nicht-abstrakten Typ mit einem öffentlichen parameterlosen Konstruktor, um sie als Parameter‚T‘zu verwenden sein müssen“, weil DatabaseItem abstrakt ist. Ich habe DatabaseItem als nicht-abstrakten Typ, der Fehler ist weg, aber immer noch viele Fehler Typumwandlung herauskam ...

Gefunden eine ähnliche question aber ich verstehe immer noch nicht ...

Was ist besser Lösung/Struktur um dies zu erreichen?

+0

Wahrscheinlich eine Schnittstelle für Ihre Datenbank-Klasse zu definieren, zB Dictionary

Antwort

3

Die einfachste Sie tun können, ist speichern Database<T> Nachkommen als Objekte:

static class DatabaseManager 
{ 
    private static Dictionary<Type, object> databases = new Dictionary<Type, object>(); 

    // .... 

    public static Database<T> GetDatabase<T>() 
     where T : DatabaseItem, new() 
    { 
     return (Database<T>)databases[typeof(T)]; 
    } 
} 

Auch wenn Sie DatabaseItem an nicht drehen -abstract-Klasse mit parameterlosem Konstruktor, das wird auch nicht helfen, weil typeof(Database<ShopItem>) != typeof(Database<DatabaseItem>).

Beachten Sie, dass generische Bedingungen für die Methode GetDatabase<T> dieselben sein müssen wie für die Klasse Database<T>.

Upd.

Gibt es eine Möglichkeit zu wissen, welchen Typ Parameter eine Klasse verwendet? z.B. geben ShopDatabase, möchte ich ShopItem bekommen. Ich brauche es, wenn ich Datenbanken Wörterbuch

Verwenden Reflexion initialisieren:

var databaseItemType = typeof(ShopDatabase).BaseType.GetGenericArguments()[0]; 

Für Fälle wie folgt aus:

class FooDatabase : Database<FooItem> {} 
class BooDatabase : FooDatabase {} 
// etc... 

Sie eine Schleife durch Vererbungsbaum brauchen Database<FooItem> zu finden.

+0

Ich denke, wir sind fast da, gibt es eine Möglichkeit zu wissen, welche Art Parameter eine Klasse verwendet? z.B. Wenn ich ShopDatabase gebe, möchte ich ShopItem bekommen. Ich brauche es, wenn ich * Datenbanken * Wörterbuch –

+0

initialisieren @RichardFu: Ich habe die Antwort aktualisiert. – Dennis

1

Die schlechte Nachricht ist, dass Sie Ihren Code ohne Art der Besetzung nicht verwenden können. Definieren Sie eine nicht-generischen Typ oder inerface für Datenbank, dann verwenden Sie diesen Code:

Dictionary<Type, Database> databases; 
public static Database<T> GetDatabase<T>() where T: DatabaseItem, new() 
{ 
    return databasebases[typeof(T)] as Database<T>; 
} 
Verwandte Themen