11

このトピックについてはたくさんの質問がありますが、少し変更したバージョンがあります。

次のコードがあります。

interface IFoo { }
interface IBar : IFoo { }
class Foo : IFoo { }
class Bar : IBar { }

bool Implements_IFoo(Type type) { /* ??? */ }

さて、話のひねり:Implements_IFooTypeがIFooのみを実装し、IFooから派生したインターフェイスを実装していない場合にのみ、メソッドはtrueを返す必要があります。ここで説明するために、この方法のいくつかの例を示します。

Implements_IFoo(typeof(Foo)); // Should return true

Implements_IFoo(typeof(Bar)); // Should return false as Bar type 
                              // implements an interface derived from IFoo

IFooから派生した多数のインターフェースが存在する可能性があり、それらの存在について必ずしも知っているとは限らないことに注意してください。

明らかな方法は、リフレクションを介してIFooから派生したすべてのインターフェイスを検索し、typeof(Bar).GetInterfaces()がそこに存在するもののいずれかであるかどうかを確認することです。しかし、誰かがもっとエレガントな解決策を思い付くことができるかどうか疑問に思いました。

PS質問は、クラス()でこのチェックを使用することがわかったコードに由来しますif(obj.GetType() == typeof(BaseClass)) { ... }。現在、その特定のコードでクラスをインターフェースに置き換えています。また、念のため、このチェックをブールフラグとして実装しているため、この質問は純粋に仮説です。

4

6 に答える 6

9

楽しそうだったので試してみましたが、これはあなたの例でうまくいきます:

bool ImplementsIFooDirectly(Type t) {
    if (t.BaseType != null && ImplementsIFooDirectly(t.BaseType)) { 
        return false; 
    }
    foreach (var intf in t.GetInterfaces()) {
        if (ImplementsIFooDirectly(intf)) { 
            return false;
        }
    }
    return t.GetInterfaces().Any(i => i == typeof(IFoo));
}

結果:

ImplementsIFooDirectly(typeof(IFoo)); // false
ImplementsIFooDirectly(typeof(Bar)); // false
ImplementsIFooDirectly(typeof(Foo)); // true
ImplementsIFooDirectly(typeof(IBar)); // true

から派生したすべてのインターフェイスを探すのではなくIFoo、継承/インターフェイス実装チェーンをたどっIFooて、タイプの正確なレベル以外のレベルに存在するかどうかを確認します。

また、インターフェイスが基本型を介して継承されているかどうかも検出します。それがあなたが望むものかどうかはわかりません。

それでも、他の人がすでに言っているように、これが本当に必要な場合は、設計に問題がある可能性があります. (編集:あなたの質問が純粋に仮説に過ぎないことに気付きました。それならもちろん大丈夫です:))

于 2012-04-27T13:47:39.673 に答える
3

これを実装する方法の例については、次のサイトを参照してください。

C#はキーワードの使用法です

基本的に、「is」キーワードを使用して、オブジェクトがそのクラス継承スタックの一部としてクラスタイプに存在するかどうかを判断できます。

class Director  : Owner { }
class Developer : Employee { }
..
var dave = new Developer();
var steve = new Director();
var isEmployee = dave is Employee; // true
var isAlsoEmploye = steve is Employee; // false

サンプル関数に沿って:

bool Implements_Type(object instance, Type type) { 
return instance is type;
}
于 2012-04-27T13:40:28.060 に答える
2
static bool Implements_IFoo(Type type)
{
  if (typeof(IFoo).IsAssignableFrom(type.BaseType))
    return false;

  var barInterfaces = type.GetInterfaces()
    .Where(iface => typeof(IFoo).IsAssignableFrom(iface))
    .ToArray();

  return barInterfaces.Length > 0 
     && barInterfaces.Length == barInterfaces.Count(iface => iface == typeof(IFoo));
}
static bool Implements_IFoo_Optimized(Type type)
{
  if (typeof(IFoo).IsAssignableFrom(type.BaseType))
    return false;

  return type.GetInterfaces()
    .Where(iface => typeof(IFoo).IsAssignableFrom(iface))
    .Count() == 1;
}
于 2012-04-27T13:48:25.860 に答える
1

これでうまくいくはずです:

 public bool ImplementsIFooOnly(Type type)
 {
     return !type.GetInterfaces().Any(t => 
              { 
                   return t is IFoo && !t.Equals(typeof(IFoo)); 
              });
 }

おそらくもっと効率的な方法があります。

于 2012-04-27T13:58:29.083 に答える
0

Type クラスには、使用できる GetInterface というメソッドがあります。

    bool Implements_IFoo(Type t)
    {
        return t.GetInterface(typeof(IFoo).Name) != null;
    }
于 2012-04-27T13:47:16.913 に答える
0

キーワードを使用しようとしましたisか?

ところで、一般に、あるクラスが何らかの基本クラスの型である必要があるが、継承者の 1 つではないという論理的なケースがある場合、それはおそらく間違った OO 設計であり、Liskov 置換原則に違反している可能性があります。

于 2012-04-27T13:35:10.117 に答える