2012-05-09 12 views
8

Im tratando de agregar la función de tiempo de ejecución, algo así:usando Dynamic para agregar métodos?

static void Main() 
{ 
dynamic d = new Duck(); 
d.Quack =(Action) (() => Console.WriteLine("1")); //decalre a new method on runtime ?? 
d.Quack(); 

} 

public class Duck : System.Dynamic.DynamicObject 
{ 
    //... 
} 

'UserQuery.Duck' no contiene una definición para

dinámica Isnt 'Quack' debería permitir que lo haga yo?

¿la nueva solución es ExpandoObject?

tengo mi clase de pato ya. ¿Cómo puedo hacerlo Expando? - ¿Puedo hacer que el pato actúe como expando?

+0

Por algunas razones absolutamente oscuros fue eliminado mi puesto. Por cierto, no puede derivar de ExpandoObject, y si desea que su objeto se comporte como ese, tiene 2 soluciones, imo: 1. Cree Expando y agregue inicialmente todas las propiedades y métodos que tiene en Duck, y no lo haga usa pato 2. Genera tu propio ExpandoObject. Mire aquí: [Comportamiento dinámico en objetos en tiempo de ejecución con ExpandoObject personalizado] (http://www.codeproject.com/Articles/91889/Dynamic-Behaviour-on-Objects-at-Runtime-With-Custo) para obtener un ejemplo más detallado y deriva Pato de ella. – Tigran

Respuesta

14

No puede agregar propiedades de ningún tipo (incluso funciones) a un tipo existente .

dynamic d = new Duck(); 
d.Quack = "Quack";//fails because there is no such property on duck 

Usted podría utilizar ExpandoObject sin embargo:

dynamic d = new ExpandoObject(); 
d.Quack = (Action)(() => System.Console.WriteLine("1")); 
d.Quack(); 

no se confunda con lo que el tipo dinámico.

void speak(dynamic d) 
{ 
d.Quack();//this is NOT checked at compile time 
} 

ahora que puedo hacer: y speak(new Goose());, va a compilar y ejecutar si ambos Duck y Goose tienen el método Quack(), si no lo hacen, se genera una excepción. (El mismo que obtienes)

Cuando llamas a un método/propiedad en un tipo dynamic, solo resuelve eso en tiempo de ejecución y no hace una verificación del compilador.

El ExpandoObject le permite crear propiedades sobre la marcha.


Para responder a su pregunta sobre el comentario, la forma en que lo veo es, si usted necesita su propia clase que necesita la capacidad de crear nuevas propiedades se podía heredar de DynamicObject. Como esto (adaptado de this msdn page):

class DynamicDuck : DynamicObject 
{ 
     Dictionary<string, object> dictionary 
      = new Dictionary<string, object>(); 
    public int Count 
    { 
     get 
     { 
      return dictionary.Count; 
     } 
    } 
    public override bool TryGetMember(
      GetMemberBinder binder, out object result) 
    { 
      string name = binder.Name.ToLower(); 
      return dictionary.TryGetValue(name, out result); 
    } 
    public override bool TrySetMember(
     SetMemberBinder binder, object value) 
    { 
      dictionary[binder.Name.ToLower()] = value; 
      return true; 
    } 
} 

Entonces que podría hacer:

dynamic d = new DynamicDuck(); 
d.firstname = "Gideon"; 
d.Quack = (Action)(() => System.Console.WriteLine("Quack")); 
+0

pero ¿por qué querría heredar de System.Dynamic.DynamicObject? el único escenario que veo - es anular los métodos tryGetXXX etc. ... –

+0

Si no quiere usar su clase como un "diccionario", p. si representa un archivo xml o csv donde puede acceder dinámicamente a columnas y elementos, como 'file.nameOfSecondColumn [row]' – phg

+0

@RoyiNamir Actualicé mi respuesta. – gideon