Как определить, реализует ли тип интерфейс с отражением C # - PullRequest
505 голосов
/ 11 февраля 2011

Предоставляет ли отражение в C# способ определения, если некоторые данные типа System.Type моделируют какой-либо интерфейс?

public interface IMyInterface {}

public class MyType : IMyInterface {}

// should yield 'true'
typeof(MyType)./* ????? */MODELS_INTERFACE(IMyInterface);

Ответы [ 13 ]

856 голосов
/ 11 февраля 2011

У вас есть несколько вариантов с макушки моей головы

  1. typeof(IMyInterface).IsAssignableFrom(typeof(MyType))

  2. typeof(MyType).GetInterfaces().Contains(typeof(IMyInterface))

Для общего интерфейса все немного по-другому.

typeof(MyType).GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IMyInterface<>))
62 голосов
/ 11 февраля 2011

Использование Type.IsAssignableFrom:

typeof(IMyInterface).IsAssignableFrom(typeof(MyType));
28 голосов
/ 11 февраля 2011
typeof(IMyInterface).IsAssignableFrom(someclass.GetType());

или

typeof(IMyInterface).IsAssignableFrom(typeof(MyType));
12 голосов
/ 11 октября 2013
    public static bool ImplementsInterface( this Type type, Type ifaceType ) {
        Type[] intf = type.GetInterfaces();
        for ( int i = 0; i < intf.Length; i++ ) {
            if ( intf[ i ] == ifaceType ) {
                return true;
            }
        }
        return false;
    }

Я думаю, что это правильный выпуск по трем причинам:

1) Он использует GetInterfaces, а не IsAssignableFrom, он быстрее, поскольку IsAssignableFrom, в конце концов, после нескольких проверок вызывает GetInterfaces.
2) Он перебирает локальный массив, поэтому проверки границ не будет.
3) Он использует оператор ==, который определен для Type, поэтому, вероятно, безопаснее, чем метод Equals (который в конечном итоге будет использовать вызов Contains).

8 голосов
/ 31 марта 2017

Я только что сделал:

public static bool Implements<I>(this Type source) where I : class
{
  return typeof(I).IsAssignableFrom(source);
}

Я бы хотел сказать where I : interface, но interface не является универсальной опцией ограничения параметров.class настолько близко, насколько возможно.

Использование:

if(MyType.Implements<IInitializable>())
  MyCollection.Initialize();

Я только что сказал Implements, потому что это более интуитивно понятно.Я всегда получаю IsAssignableFrom флип-флоп.

7 голосов
/ 07 июля 2015

Изменение ответа Джеффа для достижения оптимальной производительности (благодаря тесту производительности Пьера Арно):

var type = typeof(MyType);
var implementsInterface = typeof(IMyInterface).IsAssignableFrom(type) && type.IsClass;

Чтобы найти все типы, которые реализуют интерфейс в данном Assembly:

var implementations = typeof(TypeInTargetAssembly).Assembly.GetTypes()
                          .Where(t => typeof(IMyInterface).IsAssignableFrom(t) && t.IsClass);
7 голосов
/ 05 мая 2015

Как уже упоминал кто-то другой: Бенджамин 10 апреля '13 в 22:21 "

Было легко не обращать внимания и получать аргументы для IsAssignableFrom в обратном направлении. Сейчас я пойду с GetInterfaces: p -

Ну, другой способ - просто создать метод короткого расширения, который в некоторой степени соответствует «наиболее обычному» мышлению (и согласился, что это очень маленький личный выборчтобы сделать его немного «более естественным» в зависимости от своих предпочтений):

public static class TypeExtensions
{
    public static bool IsAssignableTo(this Type type, Type assignableType)
    {
        return assignableType.IsAssignableFrom(type);
    }
}

И почему бы не пойти немного более обобщенно (ну, не уверен, действительно ли это так интересно, ну, я полагаю, я просто передаюеще один «сахар синтаксиса»):

public static class TypeExtensions
{
    public static bool IsAssignableTo(this Type type, Type assignableType)
    {
        return assignableType.IsAssignableFrom(type);
    }

    public static bool IsAssignableTo<TAssignable>(this Type type)
    {
        return IsAssignableTo(type, typeof(TAssignable));
    }
}

Я думаю, что это может быть гораздо более естественным, но, опять же, просто личное мнение:

var isTrue = michelleType.IsAssignableTo<IMaBelle>();
2 голосов
/ 01 июня 2017

IsAssignableFrom теперь перемещено в TypeInfo:

typeof(ISMSRequest).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo());
1 голос
/ 23 ноября 2017

Правильный ответ:

typeof(MyType).GetInterface(nameof(IMyInterface)) != null;

Однако

typeof(MyType).IsAssignableFrom(typeof(IMyInterface));

может вернуть неправильный результат, как показано в следующем коде со строкой и IConvertible:

    static void TestIConvertible()
    {
        string test = "test";
        Type stringType = typeof(string); // or test.GetType();

        bool isConvertibleDirect = test is IConvertible;
        bool isConvertibleTypeAssignable = stringType.IsAssignableFrom(typeof(IConvertible));
        bool isConvertibleHasInterface = stringType.GetInterface(nameof(IConvertible)) != null;

        Console.WriteLine($"isConvertibleDirect: {isConvertibleDirect}");
        Console.WriteLine($"isConvertibleTypeAssignable: {isConvertibleTypeAssignable}");
        Console.WriteLine($"isConvertibleHasInterface: {isConvertibleHasInterface}");
    }

Результаты:

 isConvertibleDirect: True
 isConvertibleTypeAssignable: False
 isConvertibleHasInterface: True
0 голосов
/ 13 июля 2019

Если у вас есть тип или экземпляр, вы можете легко проверить, поддерживают ли они определенный интерфейс.

Чтобы проверить, реализует ли объект определенный интерфейс:

if(myObject is IMyInterface) {
  // object myObject implements IMyInterface
}

Чтобы проверить, еслитип реализует определенный интерфейс:

if(typeof(IMyInterface).IsAssignableFrom(typeof(MyType))) {
  // type MyType implements IMyInterface
}

Если вы получили универсальный объект и хотите выполнить приведение, а также проверить, реализован ли интерфейс, к которому вы приведете, код:

 var myCastedObject = myObject as IMyInterface;

    if(myCastedObject != null) {
      // object myObject implements IMyInterface
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...