Прежде чем ответить, у меня есть два замечания:
- Я согласен с Джоэлом в том, что общее решение было бы намного проще, но без большего контекста я предполагаю, что вам действительно нужно размышление
- почему вы используете FormatterServices.GetUninitializedObject ()? Это не вызовет конструктор вашего объекта Table. Я предполагаю, что вы на самом деле хотите использовать здесь Activator.CreateInstance ().
Теперь перейдем к проблеме. Вы столкнулись с отсутствием поддержки совместной (и противоположной) дисперсии в .Net. Оператор присваивания никогда не будет работать, также без отражения:
' does not compile (with Option Strict On)
Dim t as Table(Of Object) = New Table(Of Product)
Причина в том, что типы на самом деле разные. Хотя Product наследуется от Object, это не означает, что Table (Of Product) не наследуется от Table (Of Object).
.Net 4 действительно поддерживает универсальную ковариацию, но только для универсальных интерфейсов и типов делегатов. Аннотируя универсальный тип ключевым словом «out», вы можете пометить его как универсально ковариантный. Например, объявление универсального интерфейса IEnumerable выглядит так:
IEnumerable(Of Out T)
Это означает, что теперь возможно сделать следующее:
Dim mylist As IEnumerable(Of Object) = new List<Product>()
Таким образом, можно безопасно назначить список IEnumerable (Of Product) переменной типа IEnumerable (Of Object).
Вот объяснение ко-и контрастности в VB.Net
Итак, вы могли бы определить интерфейс для общей таблицы:
Interface ITable(Of Out T)
End Interface
Затем вы можете реализовать этот интерфейс в своем родном классе Table:
Class Table(Of T)
Implements ITable(Of T)
End Class
Тогда это будет работать:
Function CreateTable(ByVal t As Type) As ITable(Of Object)
Dim result As ITable(Of Object)
Dim type = GetType(Table(Of )).MakeGenericType(t)
result = FormatterServices.GetUninitializedObject(type)
Return result
End Function
Конечно, еще лучше было бы использовать IEnumerable (Of T) вместо ITable (Of T), если это возможно.