处理抽象类和类型参数固有的类

Ric*_* Fu 5 c# inheritance abstract-class type-conversion type-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 {
  ...
}
Run Code Online (Sandbox Code Playgroud)

然后我有许多固有的儿童课程:

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

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

...
Run Code Online (Sandbox Code Playgroud)

现在,我想使用Dictionary来跟踪数据库以及使用DatabaseItem类型返回它们的方法,如下所示:

Dictionary<Type, Database<DatabaseItem>> databases;

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

然后它给了我"'T'必须是一个非抽象类型,带有一个公共无参数构造函数,以便将它用作参数'T'"错误,因为DatabaseItem是抽象的.我将DatabaseItem设置为非抽象类型,错误消失但仍然出现了很多类型转换错误...

发现了类似的问题,但我还是不明白......

实现这一目标的更好的解决方案/结构是什么?

Den*_*nis 3

最简单的方法是将Database<T>后代存储为对象:

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)];
    }
}
Run Code Online (Sandbox Code Playgroud)

即使您转向DatabaseItem具有无参数构造函数的非抽象类,这也无济于事,因为typeof(Database<ShopItem>) != typeof(Database<DatabaseItem>).

请注意,GetDatabase<T>方法的通用约束必须与类的通用约束相同Database<T>

更新

有没有办法知道类使用什么类型参数?例如给ShopDatabase,我想得到ShopItem。我在初始化数据库字典时需要它

使用反射:

var databaseItemType = typeof(ShopDatabase).BaseType.GetGenericArguments()[0];
Run Code Online (Sandbox Code Playgroud)

对于这样的情况:

class FooDatabase : Database<FooItem> {}
class BooDatabase : FooDatabase {}
// etc...
Run Code Online (Sandbox Code Playgroud)

您需要循环遍历继承树才能找到Database<FooItem>.