Экземпляр универсального класса .NET - передача типа данных переменной - PullRequest
4 голосов
/ 02 июня 2010

Как следует из заголовка, я пытаюсь передать переменный тип данных в класс шаблона. Примерно так:

frmExample = New LookupForm(Of Models.MyClass) 'Works fine

Dim SelectedType As Type = InstanceOfMyClass.GetType() 'Works fine
frmExample = New LookupForm(Of SelectedType) 'Ba-bow!
frmExample = New LookupForm(Of InstanceOfMyClass.GetType()) 'Ba-bow!

LookupForm<Models.MyClass> frmExample;
Type SelectedType = InstanceOfMyClass.GetType();
frmExample = new LookupForm<SelectedType.GetType()>(); //Ba-bow
frmExample = new LookupForm<(Type)SelectedType>(); //Ba-bow

Я предполагаю, что это как-то связано с тем, что шаблон обрабатывается во время компиляции, но даже если я не в курсе, это все равно не решит мою проблему. Я не могу найти никакой соответствующей информации об использовании Reflection для экземпляров классов шаблонов.

(Как) я могу создать экземпляр динамически типизированного хранилища во время выполнения?

Ответы [ 4 ]

9 голосов
/ 02 июня 2010

Пример C # чего-то довольно близкого расположен здесь на вопрос, который у меня был:

typeof(MyClass).GetMethod("Foo").MakeGenericMethod(new[] { param.GetType() }).Invoke(null, new[] { param });

Преобразование в VB.NET, его преобразование в создание типа, а не в вызов метода, и использование имен ваших примеров:

Dim frmExample as LookupForm<Models.MyClass>;
Dim SelectedType as Type = InstanceOfMyClass.GetType();   
Dim GenericLookupType as Type = GetType(LookupForm(Of)).MakeGenericType(SelectedType)
frmExample = Activator.CreateInstance(GenericLookupType, new object(){})

(Ах, почему-то я думал, что вы хотели это в VB.NET, но вот пример на C #)

LookupForm<Models.MyClass> frmExample;
Type SelectedType = InstanceOfMyClass.GetType();   
Type GenericLookupType = typeof(LookupForm<>).MakeGenericType(SelectedType);
frmExample = Activator.CreateInstance(GenericLookupType, new object[]{});
6 голосов
/ 02 июня 2010

Использование Type.MakeGenericType.

Type modelType = typeof(Models.MyClass);
var repoType = typeof(LookupForm<>).MakeGenericType(new [] {modelType} );
//at this point repoType == typeof(LookupForm<Models.MyClass>);
var repo = Activator.CreateInstance(repoType );
//Ta-dah!!!

И версия VB.NET:)

    Dim modelType As Type = GetType(Models.MyClass)
    Dim repoType As Type = GetType(LookupForm(Of )).MakeGenericType(New Type() {modelType})
    'at this point repoType = GetType(LookupForm(of Models.MyClass))'
    Dim repo = Activator.CreateInstance(repoType)
    'Ta-dah!!!'
1 голос
/ 02 июня 2010

К сожалению, вы не можете сделать это без размышлений, и даже тогда это не очень дружелюбно. Код отражения будет выглядеть примерно так:

Type baseType = typeof(LookupForm<>);
Type selectedType = InstanceOfMyClass.GetType(); //or however else you want to get hold of it
Type genericType = baseType.MakeGenericType(new Type[] { selectedType });
object o = Activator.CreateInstance(genericType);

Конечно, теперь вы не знаете, к чему привести объект (предполагая, что selectedType был динамически установлен), но вы все равно можете вызывать методы для него через отражение, или вы можете создать неуниверсальный интерфейс для приведения это и вызвать методы на этом.

1 голос
/ 02 июня 2010

Звучит как кандидат на динамический язык Runtime, тип Dynamic в C #, но для этого потребуется использование .NET 4.0

...