712 Stimmen

Wie man bestimmt, ob ein Typ eine Schnittstelle mit C#-Reflexion implementiert

Bietet Reflexion in C# eine Möglichkeit festzustellen, ob ein bestimmter System.Type ein bestimmtes Interface modelliert?

public interface IMyInterface {}

public class MyType : IMyInterface {}

// sollte 'true' ergeben
typeof(MyType)./* ????? */MODELS_INTERFACE(IMyInterface);

6voto

Bill Barry Punkte 3231

Jeder, der danach sucht, könnte die folgende Erweiterungsmethode nützlich finden:

public static class TypeExtensions
{
    public static bool ImplementsInterface(this Type type, Type @interface)
    {
        if (type == null)
        {
            throw new ArgumentNullException(nameof(type));
        }

        if (@interface == null)
        {
            throw new ArgumentNullException(nameof(@interface));
        }

        var interfaces = type.GetInterfaces();
        if (@interface.IsGenericTypeDefinition)
        {
            foreach (var item in interfaces)
            {
                if (item.IsConstructedGenericType && item.GetGenericTypeDefinition() == @interface)
                {
                    return true;
                }
            }
        }
        else
        {
            foreach (var item in interfaces)
            {
                if (item == @interface)
                {
                    return true;
                }
            }
        }

        return false;
    }
}

xUnit-Tests:

public class TypeExtensionTests
{
    [Theory]
    [InlineData(typeof(string), typeof(IList), false)]
    [InlineData(typeof(List<>), typeof(IList<int>), false)]
    [InlineData(typeof(List<>), typeof(IList<>), true)]
    [InlineData(typeof(List<int>), typeof(IList<>), true)]
    [InlineData(typeof(List<int>), typeof(IList<int>), true)]
    [InlineData(typeof(List<int>), typeof(IList<string>), false)]
    public void ValidateTypeImplementsInterface(Type type, Type @interface, bool expect)
    {
        var output = type.ImplementsInterface(@interface);
        Assert.Equal(expect, output);
    }
}

2voto

codeputer Punkte 1925

IsAssignableFrom wurde nun zu TypeInfo verschoben:

typeof(ISMSRequest).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo());

1voto

EricBDev Punkte 947

Eine korrekte Antwort ist

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

Jedoch könnte

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

eine falsche Antwort liefern, wie der folgende Code zeigt mit string und 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}");
    }

Ergebnisse:

 isConvertibleDirect: True
 isConvertibleTypeAssignable: False
 isConvertibleHasInterface: True

5 Stimmen

Wie Sie in der akzeptierten Antwort sehen können, haben Sie die Typen beim Gebrauch von IsAssignableFrom vertauscht. Genau wie Benjamin und Ehouarn warnen.

0voto

Pingi Punkte 342

Was ist mit

if(MyType as IMyInterface != null)

?

7 Stimmen

Das ist offensichtlich, wenn ich eine Instanz habe. Nicht nützlich, wenn ich einen Typ aus der Reflexion habe.

0voto

LaWi Punkte 71

Was ist mit

typeof(IWhatever).GetTypeInfo().IsInterface

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X