2009-07-10 10 views
8

Dato il nuovo supporto dinamico in C# 4, è possibile scrivere una classe in modo tale che se un metodo viene richiamato su un istanza e quel metodo non è presente, la spedizione è passata ad un altro metodo? Questo potrebbe essere simile:Gestione di un metodo C# non definito su un oggetto dinamico (aka respond_to/method_missing)

public class Apple : ... { 
    // ... 

    private ... MethodMissing(string name, ...) { 
    if (name == "TurnIntoOrange") { 
     // do something 
    } 
    } 
} 

dynamic d = new Apple(); 
d.TurnIntoOrange();  // Not actually defined on Apple; will pass to MethodMissing. 

Altre lingue chiamerebbe questo "supporto method_missing", sotto il titolo più generale di metaprogrammazione. Non sono sicuro di ciò che C# chiama specificamente. Ma è possibile?

risposta

17

Assolutamente. Implementare IDynamicMetaObjectProvider o derivare da DynamicObject per un percorso molto più semplice. Vedi lo DLR documentation per alcuni buoni esempi.

Ecco un rapido esempio di DynamicObject:

using System; 
using System.Dynamic; 

public class MyDynamic : DynamicObject 
{ 
    public override bool TryInvokeMember 
     (InvokeMemberBinder binder, 
     object[] args, 
     out object result) 
    { 
     Console.WriteLine("I would have invoked: {0}", 
          binder.Name); 
     result = "dummy"; 
     return true; 
    } 

    public string NormalMethod() 
    { 
     Console.WriteLine("In NormalMethod"); 
     return "normal"; 
    } 
} 

class Test 
{ 
    static void Main() 
    { 
     dynamic d = new MyDynamic(); 
     Console.WriteLine(d.HelloWorld()); 
     Console.WriteLine(d.NormalMethod()); 
    } 
} 

<plug>

Ho un esempio grande di DynamicObject nel 2nd edition of C# in Depth ma non hanno ancora attuato IDyamicMetaObjectProvider. Lo farò prima della pubblicazione del libro, ma l'edizione di accesso anticipato ha solo l'esempio DynamicObject al momento. A proposito, se lo compri oggi è a metà prezzo - usa il codice twtr0711. Io modificare questa risposta in seguito per rimuovere la sequenza :)

</plug>

+0

Wow, grazie Jon! –

+1

Ho accennato a questo nel mio titolo ma non l'ho chiesto direttamente nel corpo: esiste un override simile che userei per simulare un metodo "responds_to"? Vedo che posso controllare il risultato di TryInvokeMember, ma che potrebbe causare effetti collaterali indesiderati. –

+0

No, non credo che ci sia un modo per chiedere un metodo dinamico se gestirà qualcosa, anche se potresti chiamare GetDynamicMemberNames come punto di partenza. –

Problemi correlati