C #: how to find and create instances that satisfy multiple type constraints

Let's say I have a generic method with multiple constraints like this:

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

      

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

If it was just one limitation, 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 actually I cannot use multiple interfaces ... how can I solve this? You could say that I have lost a lot here: P

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

+2


source to share


3 answers


To add to Reed and Lauren's answers about finding suitable types, note that you still can't call DoSomethingAwesome by casting, because, as you've already found, the compiler doesn't provide a way to instantiate an object multiple interfaces. You have two options:

  • Create a new interface IAwesomeComparableThing which comes from IThing, IAwesome and IComparable <T>, the types implement this and discard that.

  • Calling DoSomethingAwesome through reflection. To do this, you need to get the MethodInfo for the DoSomethingAwesome generic method, then call MethodInfo.MakeGenericMethod with your type, which implements all three interfaces.



Example (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 });

      

+4


source


I am guessing that for some reason you cannot do



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

      

0


source


You need a type that can be assigned from all of your constraints. The first two are easy, but the third is a little more complicated:

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

      

0


source







All Articles