Question

Say I have a generic method with multiple type constraints, this this:

public static void DoSomethingAwesome<T>(T thing)
    where T : IThing, IAwesome, IComparable<T>
{
    ...
}

Now.... how can I, using reflection, create something I can send in there?

If it was only one constraint I know I can do it like this:

var types = assembly
      .GetTypes()
      .Where(typeof (IThing).IsAssignableFrom)

foreach(var t in types)
    DoSomethingAwesome((IThing) Activator.CreateInstance(t));

But, can't really cast to multiple interfaces... how on earth can I solve this? You could say I am pretty much lost here now :P

Title got kind of long and complex as I wasn't sure what to call this, please improve if you can

Was it helpful?

Solution

To add to Reed and Loren's answers about finding suitable types, note that you still won't be able to call DoSomethingAwesome by casting, because as you have found, the compiler doesn't provide a way to cast the instantiated object to multiple interfaces. You have two options:

  1. Create a new interface IAwesomeComparableThing which derives from IThing, IAwesome and IComparable<T>, have your types implement that, and cast to that.

  2. Invoke DoSomethingAwesome through reflection. To do this, you will need to get the MethodInfo for the DoSomethingAwesome generic method, then call MethodInfo.MakeGenericMethod with your type that implements all three interfaces.

Example of (2):

Type type = sometype; // For example found using reeds method
MethodInfo mgeneric = typeof(Awesomeiser).GetMethod("DoSomethingAwesome");
MethodInfo mspecific = mgeneric.MakeGenericMethod(new [] { type });
mspecific.Invoke(null, new [] { type });

OTHER TIPS

I'm guessing there's some reason you can't do

var types = assembly
.GetTypes()
.Where(typeof (IThing).IsAssignableFrom && typeof (IAwesome).IsAssignableFrom))

You need a type that's assignable from all of your constraints. The first two are easy, but the third is a bit trickier:

// Using
static bool IsIComparable(Type thing)
    {
        foreach (Type interfaceType in thing.GetInterfaces())
        {
            if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof (IComparable<>))
            {
                Type[] arguments = interfaceType.GetGenericArguments();
                if (arguments.Length == 1)
                {
                    if (arguments[0] == thing)
                        return true;
                }
            }
        }
        return false;
    }


// This returns an enumerable of compatible types:
var types = assembly.GetTypes().Where( t => 
   typeof(IThing).IsAssignableFrom(t) &&
   typeof(IAwesome).IsAssignableFrom(t) &&
   IsIComparable(t) );
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top