Отражение и изменение типа переменных во времени выполнения?

Я пытаюсь создать объект определенного типа. У меня есть следующий код, но он перестал работать, потому что он не может бросить новый объект таблицы к тому, который уже определяется. Мне нужна таблица для запуска типа IEnumerable, таким образом, я не могу объявить, объект.

Public sub getTable(ByVal t as Type)

   Dim table As Table(Of Object)

   Dim tableType As Type = GetType(Table(Of )).MakeGenericType(t)

   table = FormatterServices.GetUninitializedObject(tableType)

End sub 

Так короче говоря - существует ли способ изменить тип переменной во времени выполнения? (или лучший способ сделать то, что я делаю),

Заранее спасибо.

James

1
задан JamesWest 26 May 2010 в 17:25
поделиться

3 ответа

Попробуйте сделать весь метод универсальным (и использовать функцию, а не подпрограмму):

Public Function GetTable(Of T)() As Table(Of T)
​​
1
ответ дан 3 September 2019 в 00:17
поделиться

Взгляните на них, чтобы увидеть пару примеров того, что, как мне кажется, вы спрашиваете:

0
ответ дан 3 September 2019 в 00:17
поделиться

Прежде чем ответить, у меня есть два замечания:

  • Я согласен с Джоэлом, что общее решение было бы намного проще, но без большего контекста я предположу, что вам действительно нужно отражение
  • почему вы используете 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), если это возможно.

1
ответ дан 3 September 2019 в 00:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: