C#:Как найти и создать экземпляры, удовлетворяющие ограничениям нескольких типов

StackOverflow https://stackoverflow.com/questions/1521749

Вопрос

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

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

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

Это было полезно?

Решение

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

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

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

Пример из (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 });

Другие советы

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

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

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

// 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) );
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top