2011-09-27 6 views
9

私はリフレクションを介してクラスのインターフェイスでクエリを実行しようとしていますが、メソッドType.GetInterfaces()は継承されたすべてのインターフェイスも返します。継承されていないインターフェイスのみを検索しますか?

など

public class Test : ITest { } 

public interface ITest : ITesting { } 

typeof(Test).GetInterfaces(); 

コードが返されますType[]ITestITesting、私は唯一のITestをしたいと、あなたが相続を指定することができます別の方法がある両方含みますか?

ありがとう、 アレックス。

編集:I以下の回答から がこれを集め、

Type t; 
t.GetInterfaces().Where(i => !t.GetInterfaces().Any(i2 => i2.GetInterfaces().Contains(i))); 

以上が動作しているようですが、それは

+3

'public class Test:ITest、ITesting'の場合はどうなりますか?なぜこれが欲しいのですか? – SLaks

+3

私はクラスが直接継承されているもののインタフェース知っていただきたいと思いますので?そして、ではないインターフェイスは、動的に新しい型を生成するために、間接的に継承されます。それはなぜ重要なのでしょうか? –

+5

厳密に言えば、あなたは*インターフェースを継承せず、それらを実装するので、 'Test'クラスはこの場合に' ITest'と 'ITesting'の実装を提供しています。 「ITest」が「ITesting」から「継承」するという事実は、単に「ITest」を実装するどのタイプもITestingの実装を提供しなければならないことを単に意味する。 – LukeH

答えて

6

あなたが試すことができます...これの実用性は

このコードは地獄のように醜いです)...私には不明であるが、私はちょうどにMonoDevelopは、新規インストール/裸で一緒にそれを投げましたこのような何か:

Type[] interfaces = typeof(Test).GetInterfaces(); 
var exceptInheritedInterfaces = interfaces.Except(interfaces.SelectMany(t => t.GetInterfaces())); 

あなたはこのようなものがあれば、私はもっとエレガントな方法があると思いますが、私は今それを考えることはできません...

public interface A : B 
    { 
    } 

    public interface B : C 
    { 
    } 

    public interface C 
    { 
    } 

    public interface D 
    { 
    } 

    public class MyType : A, D 
    { 
    } 

コードをAD

0

このしようとしていない場合は、コメントで私を修正:

​​
+2

については、以下の私の答えを参照してください。彼がすでにそれを知っていれば、彼は反映する必要はないだろう。 –

+0

私はインタフェースの名前を知らなくてもうまくいく汎用ソリューションが必要です。 –

+0

あなたが正しいです、私はそれを誤解しました。もう一度試してください – ojlovecd

4

私が間違っていると.NETのより大きな専門家が私を修正できますが、これは可能ではないと私は考えています。内部的には、.NETフレームワークは実際にその階層を維持しておらず、ILコードにコンパイルされると平坦化されると私は考えています。

例えば、C#コード:それはILコードに組み込まれた後

class Program : I2 
{ 
    static void Main(string[] args) 
    { 
    } 
} 

interface I1 
{ 
} 

interface I2 : I1 
{ 
} 

、それは:正確class Program : I1, I2


同じである

.class private auto ansi beforefieldinit ReflectionTest.Program 
     extends [mscorlib]System.Object 
     implements ReflectionTest.I2, 
        ReflectionTest.I1 
{ 
    ... 

しかし、ILにおいても:

.class interface private abstract auto ansi ReflectionTest.I2 
     implements ReflectionTest.I1 
{ 
    ... 

これは、あなたは彼らが他人のものを実装するかどうかを確認するために、これらの各インターフェイスを照会し、その後、Programクラスから(私の例から)I1I2を得るために、いくつかのロジックを記述することができることを意味は...つまり typeof(I2).GetInterfaces()I1が含まれているので、あなたはtypeof(Program).GetInterfaces()戻りI1I2いるので、その後、Program直接コードでI1を継承していないかもしれないと推測することができます。

これも有効なC#のコードであり、同じILコードになるだろう(とも同じ反射の結果)ので、私はかもしれないを強調:今すぐ

class Program : I1, I2 
{ 
    static void Main(string[] args) 
    { 
    } 
} 

interface I1 
{ 
} 

interface I2 : I1 
{ 
} 

Program両方の直接および間接的I1を継承します。..

1

私の前の試みでは成功できませんでした。

Type[] types = typeof(Test).GetInterfaces(); 

var directTypes = types.Except 
        (types.SelectMany(t => t.GetInterfaces())); 

    foreach (var t in directTypes) 
    { 

    } 

これは誰かを助けることを望みます。

+0

downvoterからの肯定的なコメントを求めています。 – adatapost

+1

これは完璧に動作するように見えます。代替の非LINQの構文:。 'typeof演算(テスト).GetInterfaces()(。I => i.GetInterfaces()長さ> = 1).SingleOrDefault();'クラスが直接実装場合 –

+1

は、この転倒ではないだろう2つのインタフェース。 'Test:ITestInterface1、ITestInterface2'? (落下によりIクラスが直接1つの以上のインターフェースを実装し表示するために無視を意味上)私は途中で合意...インターフェースAは、インタフェースBから継承し、Bは、インターフェースCを継承している場合 – Phill

1

基本的にコンパイルすると、次はまったく同じですこれを行うには些細なメソッド呼び出しはありません表示されます。

MyClass : IEnumerable<bool> 

MyClass : IEnumerable<bool>,IEnumerable 

をあなたが各インターフェイスに質問し、そのために頼むことができますが、インターフェイス。そして彼らがフォーマーズリストに入っているかどうかを見てください。珍しく、クラスGetInterfacesメソッドのために再帰的です。つまり、すべてのレベルの継承が得られます。インタフェースの場合、再帰的ではありません。例えば: IList戻りIListICollectionが、ICollectionによって実装されている程度IEnumerableには言及していません。

はしかし、あなたが最も可能性の高いあなたがメソッドGetInterfaceMap(Type)を使用することができ、その場合には、各インターフェイスとその結合によって独自に実装する方法に興味を持っています。

0
Type t = typeof(Test); 
    int max = 0; 
    List<Type> results = new List<Type>(); 
    foreach (Type type in t.GetInterfaces()) 
    { 
     int len = type.GetInterfaces().Length; 
     if (len > max) 
     { 
      max = len; 
      results.Add(type); 
     } 
    } 
    if (results.Count > 0) 
     foreach (Type type in results) 
      Console.WriteLine(type.FullName); 
2

それは単に即時のインターフェイスを取得することはできませんが、我々はそれを把握するために必要なタイプのメタデータを持っています。

継承チェーン全体からのインターフェイスのフラット化されたリストがあり、各インターフェイスが実装/必要な(それが行っている)兄弟のどちらを示している場合は、実装または必要なすべてのインターフェイスを再帰的に削除できます親にあなたはすぐにクラスにIFooIBarを宣言し、IFooIBarによって必要とされている場合

このアプローチは、その中で、少しオーバー積極的で、それが削除されます(しかし、本当に、これは好奇心の練習よりも何ですか?

public static void Main (string[] args) 
{ 
    var nonInheritedInterfaces = typeof(Test).GetImmediateInterfaces(); 
    foreach(var iface in nonInheritedInterfaces) 
    { 
     Console.WriteLine(iface); 
    } 
    Console.Read(); 
} 

class Test : ITest { } 

interface ITest : ITestParent { } 

interface ITestParent { } 

public static class TypeExtensions 
{ 
    public static Type[] GetImmediateInterfaces(this Type type) 
    { 
     var allInterfaces = type.GetInterfaces(); 
     var nonInheritedInterfaces = new HashSet<Type>(allInterfaces); 
     foreach(var iface in allInterfaces) 
     { 
      RemoveInheritedInterfaces(iface, nonInheritedInterfaces); 
     } 
     return nonInheritedInterfaces.ToArray(); 
    } 

    private static void RemoveInheritedInterfaces(Type iface, HashSet<Type> ifaces) 
    { 
     foreach(var inheritedIface in iface.GetInterfaces()) 
     { 
      ifaces.Remove(inheritedIface); 
      RemoveInheritedInterfaces(inheritedIface, ifaces); 
     } 
    } 
} 

private static void RemoveInheritedInterfaces(Type iface, Dictionary<Type, Type> interfaces) 
{ 
    foreach(var inheritedInterface in iface.GetInterfaces()) 
    { 
     interfaces.Remove(inheritedInterface); 
     RemoveInheritedInterfaces(inheritedInterface, interfaces); 
    } 
} 
関連する問題