Отражение и изменение типа переменных во время выполнения? - PullRequest
1 голос
/ 26 мая 2010

Я пытаюсь создать объект определенного типа. У меня есть следующий код, но он не работает, потому что он не может привести новый объект таблицы к тому, который уже определен. Мне нужна таблица для запуска типа 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 

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

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

Джеймс

Ответы [ 3 ]

1 голос
/ 26 мая 2010

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

Public Function GetTable(Of T)() As Table(Of T)
1 голос
/ 26 мая 2010

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

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

0 голосов
/ 26 мая 2010

Посмотрите на них пару примеров того, что, я думаю, вы спрашиваете:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...