type - what is reflection c#




Como determinar se um tipo implementa uma interface com reflexão C# (8)

A reflexão em C# oferece uma maneira de determinar se algum determinado tipo System.Type modela alguma interface?

public interface IMyInterface {}

public class MyType : IMyInterface {}

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

Como alguém já mencionou: Benjamin 10 de abril de 2013 às 22:21 "

Com certeza foi fácil não prestar atenção e obter os argumentos para IsAssignableFrom de trás para frente. Eu vou com GetInterfaces agora: p -

Bem, outra maneira de contornar é apenas criar um método de extensão curto que atenda, até certo ponto, à maneira mais usual de pensar (e concordou que essa é uma escolha pessoal muito pequena para torná-la um pouco mais natural com base nas preferências de alguém ):

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

E por que não ir um pouco mais genérico (bem, não tenho certeza se é realmente interessante, bem, eu suponho que estou apenas passando outro pitada de açúcar 'sintaxe'):

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

Eu acho que pode ser muito mais natural assim, mas mais uma vez apenas uma questão de opiniões muito pessoais:

var isTrue = michelleType.IsAssignableTo<IMaBelle>();

Eu apenas fiz:

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

Eu gostaria de ter dito where I : interface , mas a interface não é uma opção de restrição de parâmetro genérico. class é o mais próxima possível.

Uso:

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

Acabei de dizer Implements porque isso é mais intuitivo. Eu sempre recebo IsAssignableFrom flip-flop.


Sobre o quê

typeof(IWhatever).GetTypeInfo().IsInterface

Uma resposta correta é

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

Contudo,

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

pode retornar um resultado errado, como mostra o código a seguir com string e 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}");
    }

Resultados:

 isConvertibleDirect: True
 isConvertibleTypeAssignable: False
 isConvertibleHasInterface: True

Você tem algumas escolhas fora do topo da minha cabeça

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

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

Para uma interface genérica, é um pouco diferente.

typeof(MyType).GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IMyInterface<>))

sobre o quê

if(MyType as IMyInterface != null)

?


typeof(IMyInterface).IsAssignableFrom(someclass.GetType());

ou

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

    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;
    }

Eu acho que esta é a versão correta, por três razões:

1) Ele usa GetInterfaces e não IsAssignableFrom, ele é mais rápido desde IsAssignableFrom, eventualmente, depois que várias verificações chamam GetInterfaces.
2) Ele itera sobre o array local, portanto, não haverá verificações de limites.
3) Ele usa o operador == que é definido para Type, então provavelmente é mais seguro que o método Equals (que o Contains chama, eventualmente usará).





interface