2009-07-10 9 views
8

Dado el nuevo soporte dinámico en C# 4, es posible escribir una clase de tal manera que si se invoca un método en un instancia y ese método no está presente, el envío se pasa a otro método? Esto podría ser algo como:Manejando un método C# que no está definido en un objeto dinámico (también conocido como responder_aliminar/eliminar método)

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. 

Otros idiomas llamaría a esto "apoyo method_missing", bajo el título más general de metaprogramming. No estoy seguro de lo que C# llama esto específicamente. ¿Pero es posible?

Respuesta

17

Absolutamente. O implemente IDynamicMetaObjectProvider o derive de DynamicObject para una ruta mucho más simple. Vea el DLR documentation para algunos buenos ejemplos.

Aquí hay un ejemplo rápido 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>

Tengo un ejemplo más grande de DynamicObject en el 2nd edition of C# in Depth pero todavía no han aplicado IDyamicMetaObjectProvider. Lo haré antes del lanzamiento del libro, pero la edición de acceso anticipado solo tiene el ejemplo DynamicObject en este momento. Por cierto, si lo compras hoy es la mitad del precio, usa el código twtr0711. Voy a editar esta respuesta más adelante para eliminar esa parte :)

</plug>

+0

Wow, gracias Jon! –

+1

Aludí a esto en mi título, pero no lo pregunté directamente en el cuerpo: ¿hay una anulación similar que usaría para imitar un método de "responde a".? Veo que puedo verificar el resultado de TryInvokeMember, pero eso puede provocar efectos secundarios indeseables. –

+0

No, no creo que haya ninguna forma de preguntarle a un método dinámico si manejará algo, aunque podría llamar a GetDynamicMemberNames como punto de partida. –

Cuestiones relacionadas