2014-12-01 48 views
1

我需要處理列表中通用接口的所有變體。如何使用Linq中的通用接口類型進行過濾?

在下面的例子中,有DerivedPerson,每個持有對其PersonTemplate的引用。

internal interface ITemplate 
{ 
    int TemplateID { get; set; } 
} 

internal class PersonTemplate : ITemplate 
{ 
    public PersonTemplate(int templateId) 
    { 
     TemplateID = templateId; 
    } 

    public int TemplateID { get; set; } 
} 

internal interface ITemplateInstance<TTemplate> where TTemplate : ITemplate 
{ 
    TTemplate TemplateReference { get; set; } 
} 

internal class DerivedPerson : ITemplateInstance<PersonTemplate> 
{ 
    public DerivedPerson(PersonTemplate template) 
    { 
     TemplateReference = template; 
    } 

    public PersonTemplate TemplateReference { get; set; } 
} 

internal class Program 
{ 
    private static void Main(string[] args) 
    { 
     IList<object> objects = new List<object> 
     { 
      new object(), 
      new DerivedPerson(new PersonTemplate(1)), 
      new DerivedPerson(new PersonTemplate(2)) 
     }; 

     //Count = 2 
     List<ITemplate> personTemplates = objects 
              .OfType<ITemplateInstance<PersonTemplate>>() 
              .Select(pi => pi.TemplateReference as ITemplate) 
              .ToList(); 

     //Count = 0 (!) 
     List<ITemplate> allTemplates = objects 
              .OfType<ITemplateInstance<ITemplate>>() 
              .Select(pi => pi.TemplateReference) 
              .ToList(); 
    } 
} 

Main方法我想處理不僅是PersonTemplate類型的任何模板的所有實例。我正在尋找一種可以處理這個問題的通用方法。

我發現了一個類似的和已經接受的問題here。但我的目標是不與過濾IList<object>但隨着繼續的IList<ITemplate>

+2

好一個'ITemplateInstance '根本*不*一個'ITemplateInstance > ' - 例如,你將無法從一個投射到另一個。如果'TemplateReference'是隻讀的,那麼你可以聲明'ITemplateReference '這可以起作用......對你來說足夠好嗎? – 2014-12-01 16:13:33

+1

OfType查看實例類型並返回可以轉換爲此類型的實例的集合。我們無法投射到界面(如ITemplateInstance )! – hatem87 2014-12-01 17:12:05

+0

@Jon這將是更好的解決方案。然而,我的代碼需要大量的重構來允許協變這裏 – mamuesstack 2014-12-02 05:43:52

回答

3

你可以這樣做:

List<ITemplate> allTemplates 
       = objects.Where(o => o.GetType()                    
            .GetInterfaces() 
            .Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ITemplateInstance<>))) 
         .Select(o => o.GetType() 
            .GetProperty("TemplateReference") 
            .GetValue(o)) 
         .OfType<ITemplate>() 
         .ToList(); 
+0

你是什麼意思?它確實是他要求的,它是用來替換他的「List allTemplates' ......」行。 – svinja 2014-12-01 17:14:53

+0

我的壞...我沒有看到這個問題的底部。對不起? – BenjaminPaul 2014-12-01 17:16:41

+0

沒問題。:-) – svinja 2014-12-01 17:17:19