Cast to generic type in C#

前端 未结 13 902
野性不改
野性不改 2021-01-30 20:27

I have a Dictionary to map a certain type to a certain generic object for that type. For example:

typeof(LoginMessage) maps to MessageProcessor

        
13条回答
  •  -上瘾入骨i
    2021-01-30 21:10

    I struggled to solve a similar problem around data table classes instead of messages. The root issue mentioned above of casting a non-generic version of the class to a derived generic version was the same.

    In order to allow injection into a portable class library which did not support database libraries, I introduced a set of interface classes, with the intent that I could pass a type and get a matching generic. It ended up needing to implement a generic method.

    // Interface for injection
    public interface IDatabase
    {
        // Original, non-functional signature:
        IDatatable GetDataTable(Type dataType);
    
        // Functional method using a generic method:
        IDatatable GetDataTable();
    }
    
    
    

    And this the whole implementation using the generic method above.

    The generic class that will be cast from a dictionary.

    // Non-generic base class allows listing tables together
    abstract class Datatable
    {
        Datatable(Type storedClass)
        {
          StoredClass = storedClass;
        }
    
        Type StoredClass { get; private set; }
    }
    
    // Generic inheriting class
    abstract class Datatable: Datatable, IDatatable
    {
        protected Datatable()
            :base(typeof(T))
        {
        }
    }
    

    This is the class that stores the generic class and casts it to satisfy the generic method in the interface

    class Database
    {
        // Dictionary storing the classes using the non-generic base class
        private Dictionary _tableDictionary;
    
        protected Database(List tables)
        {
            _tableDictionary = new Dictionary();
            foreach (var table in tables)
            {
                _tableDictionary.Add(table.StoredClass, table);
            }
        }
    
        // Interface implementation, casts the generic
        public IDatatable GetDataTable()
        {
            Datatable table = null;
    
            _tableDictionary.TryGetValue(typeof(T), out table);
    
            return table as IDatatable;
        }
    }
    

    And finally the calling of the interface method.

    IDatatable table = _database.GetDataTable();
    

    提交回复
    热议问题