Clase System.Dynamic.ExpandoObject

En este artículo se proporcionan comentarios adicionales a la documentación de referencia de esta API.

La ExpandoObject clase permite agregar y eliminar miembros de sus instancias en tiempo de ejecución y también establecer y obtener valores de estos miembros. Esta clase admite el enlace dinámico, que permite usar la sintaxis estándar, como sampleObject.sampleMember en lugar de una sintaxis más compleja, como sampleObject.GetAttribute("sampleMember").

La ExpandoObject clase implementa la interfaz IDynamicMetaObjectProviderestándar de Dynamic Language Runtime (DLR), que permite compartir instancias de la ExpandoObject clase entre lenguajes que admiten el modelo de interoperabilidad dlr. Por ejemplo, puede crear una instancia de la ExpandoObject clase en C# y pasarla a una función IronPython. Para obtener más información, vea Información general de Dynamic Language Runtime e Introducción a ExpandoObject.

La ExpandoObject clase es una implementación del concepto de objeto dinámico que permite obtener, establecer e invocar miembros. Si desea definir tipos que tengan su propia semántica de distribución dinámica, use la DynamicObject clase . Si desea definir cómo participan los objetos dinámicos en el protocolo de interoperabilidad y administrar el almacenamiento en caché de distribución dinámica rápida de DLR, cree su propia implementación de la IDynamicMetaObjectProvider interfaz.

Creación de una instancia

En C#, para habilitar el enlace en tiempo de espera para una instancia de la ExpandoObject clase , debe usar la dynamic palabra clave . Para obtener más información, vea Uso del tipo dynamic.

En Visual Basic, el enlace en tiempo de entrega admite operaciones dinámicas. Para obtener más información, vea Enlace anticipado y en tiempo de ejecución (Visual Basic).

En el ejemplo de código siguiente se muestra cómo crear una instancia de la ExpandoObject clase .

dynamic sampleObject = new ExpandoObject();
Dim sampleObject As Object = New ExpandoObject()

Agregar nuevos miembros

Puede agregar propiedades, métodos y eventos a instancias de la ExpandoObject clase .

En el ejemplo de código siguiente se muestra cómo agregar una nueva propiedad a una instancia de la ExpandoObject clase .

sampleObject.test = "Dynamic Property";
Console.WriteLine(sampleObject.test);
Console.WriteLine(sampleObject.test.GetType());
// This code example produces the following output:
// Dynamic Property
// System.String
sampleObject.Test = "Dynamic Property"
Console.WriteLine(sampleObject.test)
Console.WriteLine(sampleObject.test.GetType())
' This code example produces the following output:
' Dynamic Property
' System.String

Los métodos representan expresiones lambda que se almacenan como delegados, que se pueden invocar cuando se necesitan. En el ejemplo de código siguiente se muestra cómo agregar un método que incrementa un valor de la propiedad dinámica.

sampleObject.number = 10;
sampleObject.Increment = (Action)(() => { sampleObject.number++; });

// Before calling the Increment method.
Console.WriteLine(sampleObject.number);

sampleObject.Increment();

// After calling the Increment method.
Console.WriteLine(sampleObject.number);
// This code example produces the following output:
// 10
// 11
sampleObject.Number = 10
sampleObject.Increment = Function() sampleObject.Number + 1
' Before calling the Increment method.
Console.WriteLine(sampleObject.number)

sampleObject.Increment.Invoke()

' After calling the Increment method.
Console.WriteLine(sampleObject.number)
' This code example produces the following output:
' 10
' 11

En el ejemplo de código siguiente se muestra cómo agregar un evento a una instancia de la ExpandoObject clase .

class Program
{
    static void Main(string[] args)
    {
        dynamic sampleObject = new ExpandoObject();

        // Create a new event and initialize it with null.
        sampleObject.sampleEvent = null;

        // Add an event handler.
        sampleObject.sampleEvent += new EventHandler(SampleHandler);

        // Raise an event for testing purposes.
        sampleObject.sampleEvent(sampleObject, new EventArgs());
   }

    // Event handler.
    static void SampleHandler(object sender, EventArgs e)
    {
        Console.WriteLine("SampleHandler for {0} event", sender);
    }
}
// This code example produces the following output:
// SampleHandler for System.Dynamic.ExpandoObject event.
Module Module1

Sub Main()
    Dim sampleObject As Object = New ExpandoObject()

    ' Create a new event and initialize it with null.
    sampleObject.sampleEvent = Nothing

    ' Add an event handler.
    Dim handler As EventHandler = AddressOf SampleHandler
    sampleObject.sampleEvent =
        [Delegate].Combine(sampleObject.sampleEvent, handler)

    ' Raise an event for testing purposes.
    sampleObject.sampleEvent.Invoke(sampleObject, New EventArgs())

End Sub

' Event handler.
Sub SampleHandler(ByVal sender As Object, ByVal e As EventArgs)
    Console.WriteLine("SampleHandler for {0} event", sender)
End Sub

' This code example produces the following output:
' SampleHandler for System.Dynamic.ExpandoObject event.

End Module

Pasar como parámetro

Puede pasar instancias de la ExpandoObject clase como parámetros. Tenga en cuenta que estas instancias se tratan como objetos dinámicos en C# y objetos enlazados en tiempo de ejecución en Visual Basic. Esto significa que no tiene IntelliSense para los miembros del objeto y no recibe errores del compilador al llamar a miembros no existentes. Si llama a un miembro que no existe, se produce una excepción.

En el ejemplo de código siguiente se muestra cómo puede crear y usar un método para imprimir los nombres y los valores de las propiedades.

class Program
{
    static void Main(string[] args)
    {
        dynamic employee, manager;

        employee = new ExpandoObject();
        employee.Name = "John Smith";
        employee.Age = 33;

        manager = new ExpandoObject();
        manager.Name = "Allison Brown";
        manager.Age = 42;
        manager.TeamSize = 10;

        WritePerson(manager);
        WritePerson(employee);
    }
    private static void WritePerson(dynamic person)
    {
        Console.WriteLine("{0} is {1} years old.",
                          person.Name, person.Age);
        // The following statement causes an exception
        // if you pass the employee object.
        // Console.WriteLine("Manages {0} people", person.TeamSize);
    }
}
// This code example produces the following output:
// John Smith is 33 years old.
// Allison Brown is 42 years old.
Sub Main()
    Dim employee, manager As Object

    employee = New ExpandoObject()
    employee.Name = "John Smith"
    employee.Age = 33

    manager = New ExpandoObject()
    manager.Name = "Allison Brown"
    manager.Age = 42
    manager.TeamSize = 10

    WritePerson(manager)
    WritePerson(employee)
End Sub

Private Sub WritePerson(ByVal person As Object)

    Console.WriteLine("{0} is {1} years old.",
                      person.Name, person.Age)
    ' The following statement causes an exception
    ' if you pass the employee object.
    ' Console.WriteLine("Manages {0} people", person.TeamSize)

End Sub

Enumerar y eliminar miembros

La clase ExpandoObject implementa la interfaz IDictionary<String, Object>. Esto habilita la enumeración de miembros agregados a la instancia de la ExpandoObject clase en tiempo de ejecución. Esto puede ser útil si no sabe en tiempo de compilación qué miembros podría tener una instancia.

En el ejemplo de código siguiente se muestra cómo se puede convertir una instancia de la ExpandoObject clase en la IDictionary<TKey,TValue> interfaz y enumerar los miembros de la instancia.

dynamic employee = new ExpandoObject();
employee.Name = "John Smith";
employee.Age = 33;

foreach (var property in (IDictionary<String, Object>)employee)
{
    Console.WriteLine(property.Key + ": " + property.Value);
}
// This code example produces the following output:
// Name: John Smith
// Age: 33
Dim employee As Object = New ExpandoObject()
employee.Name = "John Smith"
employee.Age = 33
For Each member In CType(employee, IDictionary(Of String, Object))
    Console.WriteLine(member.Key & ": " & member.Value)
Next
' This code example produces the following output:
' Name: John Smith
' Age: 33

En los lenguajes que no tienen sintaxis para eliminar miembros (como C# y Visual Basic), puede eliminar un miembro mediante la conversión implícita de una instancia de en ExpandoObject la IDictionary<String, Object> interfaz y, a continuación, eliminar el miembro como par clave-valor. Esta implementación se muestra en el ejemplo siguiente.

dynamic employee = new ExpandoObject();
employee.Name = "John Smith";
((IDictionary<String, Object>)employee).Remove("Name");
Dim employee As Object = New ExpandoObject()
employee.Name = "John Smith"
CType(employee, IDictionary(Of String, Object)).Remove("Name")

Recibir notificaciones de cambios de propiedad

La ExpandoObject clase implementa la INotifyPropertyChanged interfaz y puede generar un PropertyChanged evento cuando se agrega, elimina o modifica un miembro. Esto permite la ExpandoObject integración de clases con el enlace de datos de Windows Presentation Foundation (WPF) y otros entornos que requieren notificación sobre los cambios en el contenido del objeto.

En el ejemplo de código siguiente se muestra cómo crear un controlador de eventos para el PropertyChanged evento.

// Add "using System.ComponentModel;" line
// to the beginning of the file.
class Program
{
    static void Test()
    {
        dynamic employee = new ExpandoObject();
        ((INotifyPropertyChanged)employee).PropertyChanged +=
            new PropertyChangedEventHandler(HandlePropertyChanges);
        employee.Name = "John Smith";
    }

    private static void HandlePropertyChanges(
        object sender, PropertyChangedEventArgs e)
    {
        Console.WriteLine("{0} has changed.", e.PropertyName);
    }
}
' Add "Imports System.ComponentModel" line 
' to the beginning of the file.
Sub Main()
    Dim employee As Object = New ExpandoObject
    AddHandler CType(
        employee, INotifyPropertyChanged).PropertyChanged,
        AddressOf HandlePropertyChanges
    employee.Name = "John Smith"
End Sub

Private Sub HandlePropertyChanges(
       ByVal sender As Object, ByVal e As PropertyChangedEventArgs)
    Console.WriteLine("{0} has changed.", e.PropertyName)
End Sub