views:

264

answers:

4

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?

+1  A: 

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

Tim Long
I'm using .NET 4
FerretallicA
I think you'd still have to use Activator.CreateInstance but you could deal with that better at compile time {i.e. LookupForm<SomeInstanceType> a = (LookupForm<SomeInstanceType>)Activator.CreateInstance(etc.); } and ensure that SomeInstanceType matched other dynamically generated types. Kind of hard to explain right now but you no doubt know what I mean.
Graphain
+5  A: 

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!!!'
Igor Zevaka
Thankyou, an accurate answer, though Graphain got in first and with a VB.NET example :)
FerretallicA
+2  A: 

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[]{});
Graphain
Possibly because the original title had VB.NET at the start and the question only had a VB.NET example :) I removed the title reference and added a C# hoping to tap a larger mindset.
FerretallicA
Thanks for the accept. You'll find out about lots of little rabbit holes with most of the applications of this kind of stuff, but it's a good way to find boundary cases of a language.
Graphain
+1  A: 

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.

Alconja
It doesn't have to be friendly in implementation as long as the interface plays nice :)
FerretallicA