2009-12-09 19 views
7

Sto scrivendo un semplice wrapper per "duck" un oggetto dynamic contro un'interfaccia nota:Esiste un equivalente in C# a `reply_to? 'Di Ruby?

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); 
    } 
} 

Questo funziona bene se l'oggetto dynamic può rispondere alla firma Bar. Ma se non può fallire solo quando chiamo Bar. Preferirei se potesse fallire più velocemente, cioè con la convalida dell'argomento sulla costruzione del wrapper DuckFoo. Qualcosa di simile:

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

In Ruby c'è un metodo respond_to? che può essere utilizzato per verificare se un oggetto "ha" un certo metodo. C'è un modo per testarlo con oggetti dinamici in C# 4?

(mi rendo conto che anche con questo controllare la chiamata bar potrebbe non riuscire più tardi perché la natura dinamica del duck lo lascia smettere di rispondere a metodi più tardi.)

risposta

4

Si potrebbe verificare i metodi disponibili per l'oggetto essere avvolto usando Reflection, al momento della costruzione.

Basta chiamare Type.GetMethods() sull'interfaccia e sul tipo che si sta inoltrando e assicurarsi che esistano i metodi appropriati.


Edit:

Come suggerito da itowlson, c'è un'opzione per la gestione di tipi dinamici, pure. Se si controlla l'esistenza dell'interfaccia IDynamicMetaObjectProvider sull'oggetto passato, è possibile chiamare IDynamicMetaObjectProvider.GetMetaObject(). GetDynamicMemberNames() e utilizzare queste informazioni.

Se l'interfaccia non esiste, è possibile tornare a Type.GetMethods().

Questo dovrebbe gestire anche i tipi "dinamici".

+0

Cosa succede quando si esegue 'duck.GetType()' se 'duck' è dichiarato come' dynamic duck'? Che tipo restituisce? – dtb

+0

Se l'oggetto dinamico è un oggetto .NET, si ottiene il Tipo dell'oggetto. –

+0

Non penso che si possa fare una riflessione del genere su oggetti dinamici ... Forse se sono oggetti CLR regolari è possibile, ma non si può con oggetti provenienti da IronRuby, ad esempio ... –

0

Usa riflessione per verificare la presenza di metodi:

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

Questo funziona, ma solo con oggetti CLR regolari. Gli oggetti veramente dinamici potrebbero non avere un metodo Bar e rispondere comunque alla chiamata. –

1

Non so di un modo preciso per verificare se l'oggetto fornisce un metodo specifico. Naturalmente, è possibile utilizzare la riflessione, ma funziona solo se l'oggetto è un oggetto .NET. Se sei sicuro che sia, allora, come già detto, nessun problema, chiama semplicemente GetType() sull'oggetto e controlla con GetMethod().

D'altra parte, come hai detto tu stesso, anche un controllo a questo punto non garantisce che la chiamata al metodo avrà successo in seguito, quindi penso che il controllo sia inutile. Lascia che la chiamata fallisca quando effettivamente lo fa. Potrebbe anche essere che il tuo assegno affermi che l'oggetto non fornisce un metodo specifico, ma in seguito, quando lo chiameresti effettivamente, lo farà.

Problemi correlati