2014-09-28 43 views
1

我有一個看起來像這樣的方法:如何判斷泛型類型是否支持某個接口併爲該接口轉換爲某個函數?

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

我現在有我想要的篩選此項目集合的情況如果「T」支持某個接口(也可能不會,所以我不能簡單地將它作爲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. 但仍返回集合在「T」型的總體方法

注: FilterByTea MS發生在一個:

IEnumerable<ITeamFilterable> 

,並返回

IEnumerable<ITeamFilterable> 

我需要投收集2次(一次轉換爲界面的列表,然後再轉換回的T名單? )

+2

或者只是使用'is' /'as' +'!= null'。 http://stackoverflow.com/questions/410227/test-if-object-implements-interface – 2014-09-28 12:17:38

+0

這是**不是重複**因爲鏈接的問題不處理協變 – 2014-09-29 14:37:43

回答

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; 
} 

的因爲ITeamFilterableTIEnumerable<T>是協變的,但您必須在中間施加object以滿足泛型約束。使用這些演員表,不需要複製項目。

+0

看到我的問題的更新。你的回答不起作用,因爲FilterByTeams不返回T的集合,而是收集ITeamFilterable接口 – leora 2014-09-28 13:12:29

+0

@leora答案更新後,這應該工作 – 2014-09-28 13:19:22

+0

所以你的答案,簡而言之,是的,你需要來回投擲 – leora 2014-09-28 13:52:19

相關問題