tags:

views:

112

answers:

5

I have a generic method with a new() constraint. I have a call to this method with an abstract type which, of course, won't compile. I wish to keep the call generic, but was hoping I could determine at runtime what the derived class is so as to satisfy the compiler. The call would look something like this:

var result = MyGenericMethod<FindDerivedClass(myAbstractClass)>();

I tried typeof() but this doesn't seem to work.

A: 

Bad idea, which DerivedClass do you want to take ? What if there is more than one ? what if there is no DerivedClass ?

You may pass the type as class type parameter and not method type parameter :

abstract class MyAbstractClass<T> where T : MyAbstractClass<T>, new()
{
  T MyMethod() { return new T(); }
}
Guillaume
A: 

use Ojbect o.GetType();

JERiv
You can't pass a Type object as a generic type parameter... Anyway, you should read the question to the end, not just the title !
Thomas Levesque
+1  A: 

I have a generic method with a new() constraint. I have a call to this method with an abstract type which, of course, won't compile. I wish to keep the call generic, but was hoping I could determine at runtime what the derived class is so as to satisfy the compiler.

It's not the compilation, but rather the actual semantics you need to worry about. You have a method with a new() constraint - this suggests that the method needs to instantiate an object of the T it is passed. You want to pass an abstract class as the T - but what would this mean? What should the generic method do when it wants to instantiate?

You need to decide the answers to these questions: If the method doesn't need to instantiate a T, why does it have a new() constraint? If it does need to instantiate a T, what's it supposed to do if you somehow manage to get the compiler to accept an abstract class as T ?

AakashM
+1  A: 

To use generics at runtime you need to use reflection - look through all the types in the assembly for the one you want (you can use Type.IsSubclassOf), get a MethodInfo for the generic method you want to call on it, then substitute in the actual type you want to call it on with MethodInfo.MakeGenericMethod, and call it using Invoke

thecoop
A: 

If MyGenericMethod is an instance method:

var method = typeof(this).GetMethod("MyGenericMethod", Type.EmptyTypes);
method = method.MakeGenericMethod(new Type[] { FindDerivedClass(myAbstractClass) });
Action action = (Action)Delegate.CreateDelegate(typeof(Action), this, method);
action();

If MyGenericMethod is a static method:

var method = typeof(TypeWithGenericMethod).GetMethod("MyGenericMethod", BindingFlags.Public | BindingFlags.Static, null, Type.EmptyTypes, null);
method = method.MakeGenericMethod(new Type[] { FindDerivedClass(myAbstractClass) });
Action action = (Action)Delegate.CreateDelegate(typeof(Action), method);
action();

If MyGenericMethod returns a value, then use Func<ReturnType> in place of the Action delegate.

280Z28