2008-08-26 8 views
6

ヘッカーバの時間があるのですが、私は何かが分かりにくいと感じています。私はSystem.Web.UI.WebControls.Buttonから継承し、私が設定したインターフェースを実装するコントロールを持っています。そう考えて...ASP.NETで特定のインターフェイスを使用するコントロールを見つける

public class Button : System.Web.UI.WebControls.Button, IMyButtonInterface { ... } 

ページのコードビハインドで、私はこのボタンのすべてのインスタンスをASPXから探したいと思います。 タイプが実際に何をしようとしているのか分からないので、インターフェイスが実装されています。これはコントロールツリーをループするときに必要なことです。つまり、オブジェクトがインタフェースを使用しているかどうかを判断する必要はありませんでした。 コントロールツリーをループして、IMyButtonInterfaceを実装しているものをすべてクリーンな方法でヤンクできますか?(Linqは問題ありません)?再び

、それは明らかに何かを知っているが、ちょうど今重くインターフェースを使用して開始し、私はGoogleが:)

編集それを把握するのに十分な結果焦点を当てるように見えることはできません:、実際のクラスを返しGetType()をインターフェイスを返さないので、私はそれをテストできません(例えば、 "IMyButtonInterface"の代わりに "MyNamespace.Button"を返します)。再帰関数で「as」または「is」を使用しようとすると、typeのパラメータは関数内で認識されません。それはむしろ奇妙です。だから

if(ctrl.GetType() == typeToFind) //ok 

if(ctrl is typeToFind) //typeToFind isn't recognized! eh? 

私はこの1つの上に私の頭を傷つける。

答えて

7

Longhorn213は、ほぼ正しい答えを持っていますが、ショーン・チェンバースとbdukesが言うようにと、あなたの代わりに

ctrl is IInterfaceToFind 

を使用する必要があります

ctrl.GetType() == aTypeVariable 

rあなたが.GetType()を使用すると、オブジェクトの真の型が得られるでしょう。なぜなら、それが継承/インターフェイス実装チェーンでもキャストできるものではないからです。また、.GetType()は、抽象型またはインタフェースを新規に作成することができないため、抽象型/インタフェースを返すことはありません。 GetType()は、コンクリート型のみを返します。変数typeToFindのタイプは、実際にはその値を設定したタイプSystem.RuntimeTypeではありませんので、これは

if(ctrl is typeToFind) 

動作しない

理由です。たとえば、文字列の値を "foo"に設定した場合、そのタイプはまだ "foo"の文字列ではありません。私はそれが理にかなったことを願うタイプを扱うときに混乱するのは非常に簡単です。私は彼らと一緒に働くときに慢性的に混乱しています。

longhorn213の回答についての最も注目すべき点は、です。再帰を使用する必要があるか、ページのコントロールの一部を見逃している可能性があります。

私たちはここで働くソリューションを持っていますが、LINQでこれを行うためのより簡潔な方法があるかどうかを知りたいと思います。

+2

タイプが1つの場合、この特定のケースではIsAssignableFromを使用できます。 –

1

インターフェイスは、同じように感じるはずのタイプに十分近いです。 as operatorを使用します。

foreach (Control c in this.Page.Controls) { 
    IMyButtonInterface myButton = c as IMyButtonInterface; 
    if (myButton != null) { 
     // do something 
    } 
} 

また、必要に応じてis operatorを使用してテストすることもできます。

if (c is IMyButtonInterface) { 
    ... 
} 
1

"is"演算子は使用できますか?

if (myControl is ISomeInterface) 
{ 
    // do something 
} 
5

インターフェイスでのみ検索できます。また、コントロールに子コントロールがある場合、つまりボタンがパネル内にある場合は、再帰が使用されます。

private List<Control> FindControlsByType(ControlCollection controls, Type typeToFind) 
{ 
    List<Control> foundList = new List<Control>(); 

    foreach (Control ctrl in this.Page.Controls) 
    { 
     if (ctrl.GetType() == typeToFind) 
     { 
      // Do whatever with interface 
      foundList.Add(ctrl); 
     } 

     // Check if the Control has Child Controls and use Recursion 
     // to keep checking them 
     if (ctrl.HasControls()) 
     { 
      // Call Function to 
      List<Control> childList = FindControlsByType(ctrl.Controls, typeToFind); 

      foundList.AddRange(childList); 
     } 
    } 

    return foundList; 
} 

// Pass it this way 
FindControlsByType(Page.Controls, typeof(IYourInterface)); 
0

もしそのタイプのものであれば、私が使っているのはTryCastです。

Dim c as IInterface = TryCast(obj, IInterface) 
If c IsNot Nothing 
    'do work 
End if 
0

あなたは常にだけのキャストとして使用することができます。

c as IMyButtonInterface; 

if (c != null) 
{ 
    // c is an IMyButtonInterface 
} 
3

私は少しこれをクリーンアップするためにLonghorn213の例を次のように変更したい:

private List<T> FindControlsByType<T>(ControlCollection controls) 
{ 
    List<T> foundList = new List<T>(); 

    foreach (Control ctrl in this.Page.Controls) 
    { 
     if (ctrl as T != null) 
     { 
      // Do whatever with interface 
      foundList.Add(ctrl as T); 
     } 

     // Check if the Control has Child Controls and use Recursion 
     // to keep checking them 
     if (ctrl.HasControls()) 
     { 
      // Call Function to 
      List<T> childList = FindControlsByType<T>(ctrl.Controls); 

      foundList.AddRange(childList); 
     } 
    } 

    return foundList; 
} 

// Pass it this way 
FindControlsByType<IYourInterface>(Page.Controls); 

使用する別のキャストを必要としない所望の種類のオブジェクトの一覧を取り戻す。この道を。私はまた、他の人が指摘した "as"演算子に必要な変更を加えました。

関連する問題