C #: Как найти и создать экземпляры, которые удовлетворяют ограничениям нескольких типов - PullRequest
2 голосов
/ 05 октября 2009

Скажем, у меня есть универсальный метод с несколькими типами ограничений, это:

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

Теперь .... как я могу, используя отражение, создать что-то, что я могу отправить туда?

Если бы это было только одно ограничение, я знаю, что смогу сделать это так:

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

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

Но не могу ли я привести к нескольким интерфейсам ... как же я могу решить это? Вы могли бы сказать, что я в значительной степени потерян здесь сейчас: P

Название получилось довольно длинным и сложным, так как я не знал, как это назвать, пожалуйста, улучшите, если можете

Ответы [ 3 ]

4 голосов
/ 05 октября 2009

Чтобы добавить к ответам Рида и Лорен о поиске подходящих типов, обратите внимание, что вы по-прежнему не сможете вызывать DoSomethingAwesome путем приведения, потому что, как вы обнаружили, компилятор не предоставляет способ приведения экземпляра объекта к несколько интерфейсов. У вас есть два варианта:

  1. Создать новый интерфейс IAwesomeComparableThing который происходит от IThing, IAwesome и IComparable , есть ваш типы реализуют это и приводят к что.

  2. Вызвать DoSomethingAwesome через отражение. Для этого вы будете необходимо получить MethodInfo для DoSomethingAwesome универсальный метод, затем позвоните MethodInfo.MakeGenericMethod с ваш тип, который реализует все три интерфейсы.

Пример (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 });
0 голосов
/ 05 октября 2009

Вам нужен тип, который можно назначить из всех ваших ограничений. Первые два легко, но третий немного сложнее:

// 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 голосов
/ 05 октября 2009

Полагаю, есть какая-то причина, по которой вы не можете сделать

var types = assembly
.GetTypes()
.Where(typeof (IThing).IsAssignableFrom && typeof (IAwesome).IsAssignableFrom))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...