Question

As the title suggests, I'm tyring to pass a variable data type to a template class. Something like this:

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

I'm assuming it's something to do with the template being processed at compile time but even if I'm off the mark there, it wouldn't solve my problem anyway. I can't find any relevant information on using Reflection to instance template classes either.

(How) can I create an instance of a dynamically typed repository at runtime?

Was it helpful?

Solution

A C# example of something pretty close is located here on a question I had:

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

Converting to VB.NET, changing it to type creation not method invocation and using your example names for you:

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(){})

(Ah for some reason I thought you wanted it in VB.NET but here is a C# example)

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

OTHER TIPS

Use 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!!!

And VB.NET version :)

    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!!!'

This sounds like a candidate for the Dynamic Language Runtime, 'Dynamic' type in C#, but that would require you to use .NET 4.0

Unfortunately you can't do this without reflection and even then its not very friendly. The reflection code will looks something like this:

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);

Of course now you don't know what to cast your object to (assuming selectedType was dynamically set), but you can still call the methods on it via reflection, or you could create a non-generic interface to cast it to & call the methods on that.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top