如何用C#反射确定一个类型是否实现了接口

712

C#中,反射是否提供了一种确定某个给定的System.Type类型是否模拟某个接口的方法?

public interface IMyInterface {}

public class MyType : IMyInterface {}

// should yield 'true'
typeof(MyType)./* ????? */MODELS_INTERFACE(IMyInterface);
16个回答

6

如果有人在寻找此内容,可能会发现以下扩展方法很有用:

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测试:

public class TypeExtensionTests
{
    [Theory]
    [InlineData(typeof(string), typeof(IList<int>), 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);
    }
}

2

IsAssignableFrom现在已经移动到TypeInfo中:

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

1
一个正确的答案是。
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

5
正如您在被接受的答案中所看到的,您在使用IsAssignableFrom时交换了类型。就像Benjamin和Ehouarn警告的那样。 - VV5198722

0

怎么样?

if(MyType as IMyInterface != null)

?


7
当我有一个实例时,这很明显。但是当我从反射中得到一个类型时,它就不太有用了。 - edc65

0

关于什么?

typeof(IWhatever).GetTypeInfo().IsInterface

-1
如果您不需要使用反射并且已经有了一个对象,您可以使用以下代码:
if(myObject is IMyInterface )
{
 // it's implementing IMyInterface
}

1
你的解决方案仅适用于现有对象,对于类型无效。此外,如果你已经创建了一个对象,可以获取其类型并执行必要的检查。 - Maxim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接