2010-11-18 32 views
6

Bir arabirimin yansıma yoluyla bana verdiği tüm yöntemleri bulmaya çalışıyorum. Tüm arabirimleri ayıklamak için, yalnızca arabirimleri olduğunu doğruladığım bir tür dizim var. Ne yazık ki, typeof (IList) .GetMethods() gibi bir şey yaparsam, yalnızca IList üzerinde ICollection üzerinde olmayan yöntemleri döndürürse, veya IEnumerable Aşağıdaki linq sorgusunu denedim, ancak dış arabirimlerde bulunan yöntemleri döndürmez. Sorgumu nasıl düzeltebilirim? Bu SQL olsaydıLINQ kullanarak tüm yöntemleri bir [] arabirim [] üzerinde alın?

from outerInterfaces in interfaces 
from i in outerInterfaces.GetInterfaces() 
from m in i.GetMethods() 
select m 

Hepinize sendikayla bir özyinelemeli CTE gibi bir şey olabilir, ama böyle bir sözdizimi C# var sanmıyorum. Burada yardımcı olan var mı?

cevap

6

Nasıl böyle bir şey hakkında:

typeof(IList<>).GetMethods().Concat(typeof(IList<>) 
       .GetInterfaces() 
       .SelectMany(i => i.GetMethods())) 
       .Select(m => m.Name) 
       .ToList().ForEach(Console.WriteLine); 

DÜZENLEME: Yorumlara Tepki.

public interface IFirst 
    { 
     void First(); 
    } 

    public interface ISecond : IFirst 
    { 
     void Second(); 
    } 

    public interface IThird :ISecond 
    { 
     void Third(); 
    } 

    public interface IFourth : IThird 
    { 
     void Fourth(); 
    } 

Testi kodu:

bu kod ile test edilmiştir

 typeof(IFourth).GetMethods().Concat(typeof(IFourth) 
      .GetInterfaces() 
      .SelectMany(i => i.GetMethods())) 
      .Select(m => m.Name) 
      .ToList().ForEach(Console.WriteLine); 

Ve çıktısı:

Fourth 
Third 
Second 
First 
+0

@LukeH: my düzenlemek bakınız. GetInterfaces() tüm arabirimleri alır ve sizin için hiyerarşi ağacını açar. – BFree

+0

@LukeH: Vay, bunu hiç bilmiyordum. Bununla ilgili bazı belgeleri görmeyi çok isterim. Diğer dillerin (özellikle de VB.Net) bunu da yapıp yapmadığını merak ediyorum ... – BFree

+0

@BFree: Biraz daha araştırma yaparken yorumumu sildim. Bundan emin değilim, eminim ki onu yetkili bir yerde okudum. Bunu söyledikten sonra, "GetInterfaces" nin yinelemeli olduğunu düşünüyorum, bu da gerçek davranışı cevabınızla alakasız hale getirecektir. – LukeH

4

(Bildiğim kadarıyla o) hayır "yerleşik" LINQ tekrarlama yok, ama Tüm alt almak için yerleştirilmiş önemsiz LINQ uzantısı oluşturabilirsiniz: (uyarı: not defteri derlenmiş) Sonra

static public class RecursionExtensions 
{ 
    static public IEnumerable<T> AllDescendants<T>(this IEnumerable<T> source, 
               Func<T, IEnumerable<T>> descender) 
    { 
     foreach (T value in source) 
     { 
      yield return value; 

      foreach (T child in descender(value).AllDescendants<T>(descender)) 
      { 
       yield return child; 
      } 
     } 
    } 
} 

from ifaceType in interfaces.AllDescendants(t=> t.GetInterfaces()) 
from m in ifaceType.GetMethods() 
select m 
: Eğer yöntem seçici oluşturabileceği

from ifaceType in interfaces.AllDescendants(t => t.GetInterfaces()) 

Verilen: bir ağaç baz tipleri soyundan düğümleri tedavi, bu gibi kullanabilirsiniz Size interfaces koleksiyonundaki tüm arayüzleri tüm yöntemler vermelidir

, artı tüm baz arayüzleri

İlgili konular