检查类型是否在不考虑泛型类型参数的情况下实现泛型接口

时间:2013-08-14 13:40:40

标签: c# generics types interface

我有一个界面

public interface MyInterface<TKey, TValue>
{
}

实施无关紧要。现在我想检查给定类型是否是该接口的实现。

这个方法失败了
public class MyClass : MyInterface<int, string>
{
}

但我不知道如何检查。

public void CheckIfTypeImplementsInterface(Type type)
{
    var result1 = typeof(MyInterface<,>).IsAssignableFrom(type); --> false
    var result2 = typeof(MyInterface<int,string>).IsAssignableFrom(type); --> true
}

我需要做什么才能使result1成为现实?

2 个答案:

答案 0 :(得分:44)

据我所知,唯一的方法是获取所有接口,看看泛型定义是否与所需的接口类型匹配。

bool result1 = type.GetInterfaces()
    .Where(i => i.IsGenericType)
    .Select(i => i.GetGenericTypeDefinition())
    .Contains(typeof(MyInterface<,>));
编辑:正如乔恩在评论中指出的那样,你也可以这样做:

bool result1 = type.GetInterfaces()
    .Where(i => i.IsGenericType)
    .Any(i => i.GetGenericTypeDefinition() == typeof(MyInterface<,>));

答案 1 :(得分:2)

通常,只有在接口包含某些不依赖于泛型类型参数的功能的情况下才需要这种行为。如果您可以控制接口,那么最佳解决方案是使类型相关的部分继承自非类型相关部分。例如,如果现有的集合接口不存在,可以将它们定义为:

interface ICountable 
  { CollectionAttribute Attributes {get;} int Count {get;} }
interface ICollection<T> : IEnumerable<T> ICountable
  { ... and other stuff ... }

如果使用ICollection做了这样的事情,那么期待IEnumerable<Animal>但得到类型CatList的对象的代码只能实现IList<Cat>就没问题使用该对象的Count成员(请注意List<Animal>实现非通用ICollection,但其他IList<Animal>实现可能不会。)

实际上,如果您在执行Count时遇到代码以某种方式找到ICollection<Cat> IEnumerable<Animal>方法的任务,那么它可能是值得的构建像Dictionary<Type, Func<IEnumerable<Animal>, int>这样的东西,这样一旦你发现CatList实现ICollection<Cat>.Count,你就可以构建一个委托给一个方法,该方法将其参数转换为ICollection<Cat>,调用{ {1}},然后返回结果。如果您有这样的字典,那么如果您获得另一个Count,您将能够简单地从字典中调用该委托。