2009-12-09 9 views
7

Ich bin ein einfaches Wrapper-Schreiben auf „Ente“ ein dynamic Objekt gegen eine bekannte Schnittstelle:Gibt es ein C# -Aquivalent zu Rubys "respond_to?"?

interface IFoo { string Bar(int fred); } 

class DuckFoo : IFoo 
{ 
    private readonly dynamic duck; 

    public DuckFoo(dynamic duck) 
    { 
     this.duck = duck; 
    } 

    public string Bar(int fred) 
    { 
     return duck.Bar(fred); 
    } 
} 

Dies funktioniert gut, wenn die dynamic Objekt auf die Bar Signatur reagieren kann. Aber wenn das nicht klappt scheitert das nur wenn ich Bar rufe. Ich würde es bevorzugen, wenn es schneller ausfallen könnte, d. H. Mit Argumentvalidierung bei der Konstruktion der DuckFoo-Hülle. Etwas wie folgt aus:

public DuckFoo(dynamic duck) 
{ 
    if(/* duck has no matching Bar method */) 
     throw new ArgumentException("duck", "Bad dynamic object"); 
    this.duck = duck; 
} 

In Ruby gibt es eine respond_to? Methode, die verwendet werden können, um zu testen, ob ein Objekt „hat“ eine bestimmte Methode. Gibt es eine Möglichkeit, das mit dynamischen Objekten in C# 4 zu testen?

(Ich bin mir bewusst, dass auch bei diesem die Bar Anruf überprüfen konnte später scheitern, weil die Dynamik der duck sie Verfahren stoppen lassen auf später zu reagieren.)

Antwort

4

Sie die Methoden für das Objekt verfügbar überprüfen könnten, während der Bauzeit mit Reflection eingewickelt werden.

Rufen Sie einfach auf der Schnittstelle und den Typ, der übergeben wird, und stellen Sie sicher, dass die entsprechenden Methoden vorhanden sind.


Edit:

Wie itowlson vorgeschlagen, gibt es eine Option für dynamischen Typen Handhabung, wie gut. Wenn Sie nach dem Vorhandensein der IDynamicMetaObjectProvider-Schnittstelle für das übergebene Objekt suchen, können Sie dann IDynamicMetaObjectProvider.GetMetaObject() aufrufen. GetDynamicMemberNames(), und verwenden Sie diese Informationen.

Wenn die Schnittstelle nicht existiert, können Sie einfach zu Type.GetMethods() zurückkehren.

Dies sollte auch die "dynamischen" Typen behandeln.

+0

Was passiert, wenn Sie "duck.GetType()" eingeben, wenn "duck" als "dynamische Ente" deklariert ist? Welchen Typ gibt es zurück? – dtb

+0

Wenn das dynamische Objekt ein .NET-Objekt ist, erhalten Sie den Typ des Objekts. –

+0

Ich glaube nicht, dass Sie eine solche Reflektion auf dynamischen Objekten vornehmen können ... Vielleicht, wenn es sich um normale CLR-Objekte handelt, können Sie aber nicht mit Objekten aus IronRuby ... –

0

Verwenden Reflexion für Methoden zu überprüfen:

if (duck.GetType().GetMethod("Bar") == null) { 
    throw new ArgumentException("duck", "Bad dynamic object"); 
} 
+1

Das funktioniert, aber nur mit regulären CLR-Objekten. Wirklich dynamische Objekte haben möglicherweise keine Bar-Methode und reagieren trotzdem auf den Aufruf. –

1

Ich weiß nicht, von einer bestimmten Art und Weise zu überprüfen, ob das Objekt eine bestimmte Methode zur Verfügung stellt. Natürlich könnten Sie die Reflektion verwenden, aber das funktioniert nur, wenn das Objekt ein .NET-Objekt ist. Wenn Sie sicher sind, dass dies der Fall ist, rufen Sie GetType() für das Objekt auf und überprüfen Sie es mit GetMethod().

Auf der anderen Seite, wie Sie selbst gesagt haben, garantiert auch eine Überprüfung an diesem Punkt nicht, dass der Aufruf der Methode später erfolgreich sein wird, also denke ich, dass der Scheck nutzlos ist. Lassen Sie den Anruf einfach fehlschlagen, wenn dies tatsächlich der Fall ist. Es könnte auch sein, dass Ihre Überprüfung besagt, dass das Objekt keine spezifische Methode bereitstellt, aber später, wenn Sie es tatsächlich aufrufen würden, tut es dies.

Verwandte Themen