检查通用类型是否继承自通用接口

3

我有一个基本接口,IResponse...

public interface IResponse
{
    int CurrentPage { get; set; }
    int PageCount { get; set; }
}

我将翻译以下内容:

...一个通用的接口,ICollectionResponse,它继承自基础接口...

public interface ICollectionResponse<T> : IResponse
{
    List<T> Collection { get; set; }
}

...还有一个类EmployeesResponse,它继承了通用接口和基础接口...

public class EmployeesResponse : ICollectionResponse<Employee>
{
    public int CurrentPage { get; set; }
    public int PageCount { get; set; }
    public List<Employee> Collection { get; set; }
}

public class Employee
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

我的问题在这里。我有一个通用的任务方法,它返回基本接口IResponse的实例。在这个方法内部,我需要确定T是否实现了ICollectionResponse。

public class Api
{
    public async Task<IResponse> GetAsync<T>(string param)
    {
        // **If T implements ICollectionResponse<>, do something**

        return default(IResponse);
    }
}

我尝试了所有版本的IsAssignableFrom()方法,但均未成功,包括:

typeof(ICollectionResponse<>).IsAssignableFrom(typeof(T))

我很感激任何反馈意见。


1
如果一个类型针对不同的 T 实现了多次 ICollectionResponse,应该发生什么? - Jeroen Mostert
我能想到的最简单的方法是 typeof(T).GetInterfaces().Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICollectionResponse<>))。这段代码的丑陋和可能返回多个实例的事实表明您可能需要重新考虑此方法。例如,您可以查找一个适当类型的公共“Collection”属性 -- 这也需要反射,但没有“类型安全性”的薄膜(在这种情况下,您无法静态转换为 ICollectionResponse,因为您不知道类型参数)。 - Jeroen Mostert
好问题。接口的任何后续实现都必须明确地完成。这 不应该 发生,如果发生了,那就是一个特例。然而,它可能需要考虑到,并处理每个版本的“Collection”。 - Chase Blasingame
应该可以使用通用的抽象类来替代通用接口,以防止多重继承。 - Chase Blasingame
typeof通常在编译期间使用效果更佳。由于您将使用运行时来定义类型T,因此最好选择GetType() - 因为它与运行时的兼容性更好。 - Hozikimaru
2个回答

4

由于您没有任何 T 实例,因此必须使用反射。

if (typeof(T).GetInterfaces().Any(
  i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICollectionResponse<>)))
{
  Console.WriteLine($"Do something for {param}");
}
IsGenericType 用于查找任何泛型接口 - 在此示例中,它过滤掉由 GetInterfaces() 返回的 IReponse
然后,GetGenericTypeDefinitionICollectionResponse<Employee> 移动到我们想要检查的类型 ICollectionResponse<>。因为我们不知道 Employee 是什么。
正如评论中所指出的那样,可能会实现多个接口,例如 ICollectionResponse<Employee>, ICollectionResponse<Person>。上述代码将运行“Do Something”语句,而不关心是否只有一个匹配项或多个匹配项。如果没有更多范围的了解,不能确定这是否是一个问题。

0

这个对你有用吗?

List<bool> list = new List<bool>();

foreach (var i in list.GetType().GetInterfaces())
{
  if (i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList<>))
  { }
}

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