2009-07-10 5 views
8

Étant donné le nouveau support dynamique dans C# 4, est-il possible d'écrire une classe de telle manière que si une méthode est invoquée sur un instance et cette méthode n'est pas présent, dispatch est passé à une autre méthode? Cela pourrait ressembler à:Gestion d'une méthode C# qui n'est pas définie sur un objet dynamique (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. 

Autres langues appelleraient ce « soutien method_missing », sous la rubrique plus générale de métaprogrammation. Je ne suis pas sûr de ce que C# appelle cela spécifiquement. Mais est-ce possible?

Répondre

17

Absolument. Mettez en œuvre IDynamicMetaObjectProvider ou dérivez de DynamicObject pour un itinéraire beaucoup plus simple. Voir le DLR documentation pour quelques bons exemples.

Voici un exemple rapide de 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>

J'ai un plus grand exemple de DynamicObject dans le 2nd edition of C# in Depth mais je n'ai pas encore mis en œuvre IDyamicMetaObjectProvider. Je le ferai avant la sortie du livre, mais l'édition d'accès anticipé n'a pour l'instant que l'exemple DynamicObject. Btw, si vous l'achetez aujourd'hui c'est la moitié prix - utilisez le code twtr0711. Je vais modifier cette réponse plus tard pour enlever ce petit :)

</plug>

+0

Wow, merci Jon! –

+1

J'ai fait allusion à cela dans mon titre mais je ne l'ai pas directement demandé dans le corps: Y at-il un remplacement similaire que j'utiliserais pour imiter une méthode "responds_to"? Je vois que je peux vérifier le résultat de TryInvokeMember, mais cela pourrait entraîner des effets secondaires indésirables. –

+0

Non, je ne crois pas qu'il existe un moyen de demander à une méthode dynamique si elle va gérer quelque chose - bien que vous puissiez appeler GetDynamicMemberNames comme point de départ. –

Questions connexes