如何判断我的泛型类型是否支持某个接口并在函数接口之间进行转换?

时间:2014-09-28 12:15:34

标签: c# generics collections interface

我有一个看起来像这样的方法:

private IEnumerable<T> QueryCollection<T>() where T : BaseObj
{
      IEnumerable<T> items = query<T>();
      return items;
}

我现在有一种情况,我想过滤这个项目集合,如果&#34; T&#34;支持某个界面(可能不是这样我不能简单地将其添加为T的约束)。所以我想要这样的事情:

private IEnumerable<T> QueryCollection<T>() where T : BaseObj
{
     IEnumerable<T> items = query<T>();

     if (typeOf(T).GetInterface(ITeamFilterable) != null)
     {
           items = FilterByTeams(items);
     }
     return items;
}

检查我的泛型类型是否支持某个接口**的推荐方法是什么?然后如果是,则

  1. 在方法中使用它来过滤集合
  2. 但仍然会在类型&#34; T&#34;在整体方法
  3. 注意: FilterByTeams接收:

       IEnumerable<ITeamFilterable> 
    

    AND返回

       IEnumerable<ITeamFilterable>
    

    我是否需要将集合转换2次(一次转换为接口列表然后再转换回T列表?)

1 个答案:

答案 0 :(得分:1)

我担心在这种情况下您无法使用is / as,除非您可以开始枚举查询。

您可以使用这样的反射:

private IEnumerable<T> QueryCollection<T>() where T : BaseObj
{
     IEnumerable<T> items = query<T>();

     if (typeof(ITeamFilterable).IsAssignableFrom(typeof(T)))
           items = (IEnumerable<T>)(object)FilterByTeams(items.Cast<ITeamFilterable>());

     return items;
}

但是如果你可以枚举查询,你可以这样做以避免反思(假设你没有null个项目):

private IEnumerable<T> QueryCollection<T>() where T : BaseObj
{
     IEnumerable<T> items = query<T>();
     ICollection<T> itemsCollection = items as ICollection<T> ?? items.ToList();

     if (itemsCollection.Count > 0)
     {
         var firstItem = itemsCollection.First();
         if (firstItem is ITeamFilterable)
             return (IEnumerable<T>)(object)FilterByTeams(itemsCollection.Cast<ITeamFilterable>());
     }

     return itemsCollection;
}

由于ITeamFilterableT并且IEnumerable<T>是协变的,所以强制转换是有效的,但您必须强制转换为object以满足泛型约束。使用这些演员表,不需要复制项目。