2010-06-04 10 views
47

simplemente explorando C# 4. Tratando de entender todo esto dinámico. Lo siento si esta pregunta es tonta, no hay experiencia en este dominio.Agregando propiedades desconocidas (en tiempo de diseño) a un ExpandoObject

Si tengo un ExpandoObject y quiero agregar propiedades públicas (con get y set) en el tiempo de ejecución, ¿cómo podría hacerlo?

Por ejemplo, tengo una documentTemplate y un documento, que tiene una propiedad que apunta hacia documentTemplate. Este documento La plantilla tiene algunos títulos de etiquetas (por ejemplo, capacidades desarrolladas entre los estudiantes), que deben abordarse al hacer el documento (por ejemplo, concentración, memoria, etc.). Entonces, tan pronto como se establece la plantilla en el documento, quiero crear una clase, que tenga propiedades con los mismos nombres que los títulos de las etiquetas en la Plantilla, y luego usar algún elemento de UI, como PropertyGrid, puedo hacer que el usuario complete los valores de las etiquetas con la etiqueta Títulos.

¡Gracias por leer!

+4

Solo quería agregar que leí la edición de árbol muerto de este artículo en ExpandoObject: http://msdn.microsoft.com/en-us/magazine/ff796227.aspx No estoy seguro si responde sus preguntas, pero fue un gran trabajo para mí. – Yoopergeek

Respuesta

92

Me preguntaba cómo podría ser posible añadir miembros a una clase "sobre la marcha" y se acercó con esta muestra:

using System; 
using System.Collections.Generic; 
using System.Dynamic; 

class Program 
{ 
    static void Main() 
    { 
     dynamic expando = new ExpandoObject(); 
     var p = expando as IDictionary<String, object>; 

     p["A"] = "New val 1"; 
     p["B"] = "New val 2"; 

     Console.WriteLine(expando.A); 
     Console.WriteLine(expando.B); 
    } 
} 

El punto de este fragmento de código es que el los miembros A y B se definen como literales de cadena (codificados/codificados) y se agregan a través de la interfaz IDictionary de ExpandoObject. Probamos la existencia y los valores de las claves (y probamos el concepto) accediéndolos directamente y enviando a la consola.

+0

No se puede aplicar la indexación con [] a una expresión de tipo 'System.Dynamic.ExpandoObject'. ¿Algunas ideas? –

+0

@JasonFoglia: Sí. Por favor, publique esto como una pregunta y muestre un código que incluya la entrada y el resultado esperado. Solo podemos adivinar lo que podría estar pasando de un comentario ... –

3

Sí, ExpandoObject está diseñado para agregar dinámicamente propiedades a una "bolsa de propiedades". Sin embargo, no se admite la idea de otorgar tal propiedad a getter y setter. Tal vez eso quede claro si lo piensas un poco: ya no sería una propiedad dinámica si ya sabes lo que deben hacer el getter y el setter. Lo más cercano que puede obtener es implementar el evento INotifyPropertyChanged para que pueda detectar cambios. Un código de ejemplo:

using System; 
using System.Dynamic; 
using System.ComponentModel; 

class Program { 
    static void Main(string[] args) { 
    dynamic obj = new ExpandoObject(); 
    obj.test = 42;  // Add a property 
    Console.WriteLine(obj.test); 

    var inpc = (INotifyPropertyChanged)obj; 
    inpc.PropertyChanged += inpc_PropertyChanged; 
    obj.test = "foo"; 
    Console.ReadLine(); 
    } 

    static void inpc_PropertyChanged(object sender, PropertyChangedEventArgs e) { 
    Console.WriteLine("'{0}' property changed", e.PropertyName); 
    } 

} 
+0

Gracias por la explicación y el código Hans. Sin embargo, mi consulta es ligeramente diferente. Quiero saber que es posible agregar la propiedad "prueba" en tiempo de ejecución? Quiero decir que ni siquiera sabemos el nombre de la propiedad en el momento del diseño. Algo así como: obj.SetProperty (stringVariable) = anotherStringVariable. – virtualmic

+0

Erm, no.¿Por qué no simplemente usas un Diccionario ? –

+0

Para que pueda enlazar fácilmente a Windows Forms UI – virtualmic

4

Es posible añadir propiedades delegar a un ExpandoObject, que a su vez actúa (casi) igual que métodos. por ejemplo,

dynamic obj = new ExpandoObject(); 
obj.GetDocumentTemplate =() => { ... }; 
... 
obj.GetDocumentTemplate(); // invokes delegate 
2

Las respuestas hasta el momento cubren los fundamentos bastante bien, pero me sentí este artículo MSDN Magazine valía la pena compartir, así:

http://msdn.microsoft.com/en-us/magazine/ff796227.aspx

Cubre algunos ejemplos del uso de XML de entrada dinámica para crear y utilizar de forma dinámica ExpandoObjects.

2

Acabo de descubrir este hecho interesante: Los enlaces XAML a un objeto ExpandoObject también crearán las propiedades a las que el enlace está intentando acceder.

Todavía necesito más creatividad para descubrir para qué podría ser bueno. Creación de objeto dinámico en la interfaz de usuario? suena genial: D intentaré algo.

Cuestiones relacionadas