Handling classes inherent in an abstract class and type parameter

I have a base abstract class and its abstract parameter type:

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 { ... } 

Then I have the number of child classes inherent in it:

 public class ShopDatabase : Database<ShopItem> {} public class ShopItem : DatabaseItem {} public class WeaponDatabase : Database<WeaponItem> {} public class WeaponItem : DatabaseItem {} ... 

Now I want to put a dictionary to track the databases and a method to return them using the DatabaseItem type, something like this:

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

Then he gave me a “T” there must be a non-abstract type with an open constructor without parameters, to use it as a “T” parameter , because DatabaseItem is abstract. I created DatabaseItem as a non-abstract type, the error disappeared, but there are still many type conversion errors ...

Found a similar question , but I still don't get it ...

What is the best solution / structure for this?

+5
source share
2 answers

The easiest way is to save the Database<T> children as objects:

 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)]; } } 

Even if you turn the DatabaseItem into a non-abstract class with a constructor without parameters, this will not help either, because typeof(Database<ShopItem>) != typeof(Database<DatabaseItem>) .

Note that the general restrictions for the GetDatabase<T> method must be the same as for the Database<T> class.

Upd .

is there any way to find out what type of parameter the class is using? for example giving ShopDatabase, I want to get ShopItem. I need it when I initialize the database dictionary

Use reflection:

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

For such cases:

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

you need to go through the inheritance tree to find the Database<FooItem> .

+3
source

The bad news is that you cannot use your code without any role. Define a non-generic type or inerface for the database, then use this code:

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

Source: https://habr.com/ru/post/1238345/


All Articles