【问题标题】:Checking if Generic Type Inherits from Generic Interface检查泛型类型是否从泛型接口继承
【发布时间】:2019-06-25 10:02:51
【问题描述】:

我有一个基本接口,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))

感谢任何反馈。

【问题讨论】:

  • 如果一个类型为不同的T多次实现ICollectionResponse会发生什么?
  • 我能想到的最简单的就是typeof(T).GetInterfaces().Where(i =&gt; i.IsGenericType &amp;&amp; i.GetGenericTypeDefinition() == typeof(ICollectionResponse&lt;&gt;))。这很丑陋并且可以返回多个实例,这表明您可能需要重新考虑这种方法。例如,您可以只寻找适当类型的公共Collection 属性——这也需要反射,但没有“类型安全”的薄薄的饰面(在这种情况下,无论如何你都没有——你不能静态转换为ICollectionResponse,因为你不知道类型参数)。
  • 好问题。接口的任何后续实现都必须显式完成。这不应该发生,如果发生了,那将是一个特例。但是,可能应该考虑到并处理每个版本Collection。
  • 应该可以使用泛型抽象类代替泛型接口来防止多重继承。
  • typeof 通常最好在编译期间使用。由于您将使用运行时来定义类型 T,因此您可能应该使用 GetType() - 因为它与运行时配合得更好。

标签: c# .net generics inheritance interface


【解决方案1】:

这对你有用吗?

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

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

【讨论】:

    【解决方案2】:

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

    if (typeof(T).GetInterfaces().Any(
      i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICollectionResponse<>)))
    {
      Console.WriteLine($"Do something for {param}");
    }
    

    IsGenericType 用于查找任何通用接口 - 在此示例中,它过滤掉 IReponse,GetInterfaces() 也返回。

    然后GetGenericTypeDefinition 从ICollectionResponse&lt;Employee&gt; 移动到ICollectionResponse&lt;&gt;,这是我们要检查的类型。因为我们不知道Employee 是什么。

    正如 cmets 中所指出的,可能实现了多个接口,例如 ICollectionResponse&lt;Employee&gt;, ICollectionResponse&lt;Person&gt;。上面的代码将运行“做某事”语句,并且不关心是否有一个匹配项或多个匹配项。在不了解更多范围的情况下,不能说这是否是一个问题。

    【讨论】:

      猜你喜欢
      • 2023-03-22
      • 1970-01-01
      • 2014-03-05
      • 1970-01-01
      • 2011-03-06
      • 1970-01-01
      • 2020-03-02
      • 1970-01-01
      • 2018-09-27
      相关资源
      最近更新 更多