Compartilhar via


Classe System.Dynamic.ExpandoObject

Este artigo fornece comentários complementares à documentação de referência para esta API.

A ExpandoObject classe permite que você adicione e exclua membros de suas instâncias em runtime e também defina e obtenha valores desses membros. Essa classe dá suporte à associação dinâmica, o que permite que você use a sintaxe padrão, como sampleObject.sampleMember em vez de uma sintaxe mais complexa, como sampleObject.GetAttribute("sampleMember").

A ExpandoObject classe implementa a interface IDynamicMetaObjectProviderDLR (Dynamic Language Runtime) padrão, que permite compartilhar instâncias da ExpandoObject classe entre idiomas que dão suporte ao modelo de interoperabilidade de DLR. Por exemplo, você pode criar uma instância da ExpandoObject classe em C# e, em seguida, passá-la para uma função IronPython. Para obter mais informações, consulte a visão geral do Dynamic Language Runtime e apresentando o ExpandoObject.

A ExpandoObject classe é uma implementação do conceito de objeto dinâmico que permite obter, definir e invocar membros. Se você quiser definir tipos que têm sua própria semântica de despacho dinâmico, use a classe DynamicObject. Se você quiser definir como os objetos dinâmicos participam do protocolo de interoperabilidade e gerenciam o cache de expedição dinâmica rápida de DLR, crie sua própria implementação da interface IDynamicMetaObjectProvider.

Criar uma instância

Em C#, para habilitar a associação tardia para uma instância da ExpandoObject classe, você deve usar a dynamic palavra-chave. Para mais informações, consulte Using Type dynamic.

No Visual Basic, as operações dinâmicas são suportadas por vinculação tardia. Para obter mais informações, consulte Associação antecipada e tardia (Visual Basic).

O exemplo de código a seguir demonstra como criar uma instância da ExpandoObject classe.

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

Adicionar novos membros

Você pode adicionar propriedades, métodos e eventos a instâncias da ExpandoObject classe.

O exemplo de código a seguir demonstra como adicionar uma nova propriedade a uma instância da ExpandoObject classe.

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

Os métodos representam expressões lambda armazenadas como delegados, que podem ser invocadas quando são necessárias. O exemplo de código a seguir demonstra como adicionar um método que incrementa um valor da propriedade 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

O exemplo de código a seguir demonstra como adicionar um evento a uma instância da ExpandoObject classe.

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

Passar como um parâmetro

Você pode passar instâncias da ExpandoObject classe como parâmetros. Observe que essas instâncias são tratadas como objetos dinâmicos em C# e objetos com associação tardia no Visual Basic. Isso significa que você não tem o IntelliSense para membros do objeto e não recebe erros do compilador quando chama membros inexistentes. Se você chamar um membro que não existe, ocorrerá uma exceção.

O exemplo de código a seguir demonstra como você pode criar e usar um método para imprimir os nomes e valores das propriedades.

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($"{person.Name} is {person.Age} years old.");
        // The following statement causes an exception
        // if you pass the employee object.
        // Console.WriteLine($"Manages {person.TeamSize} people");
    }
}
// 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 e excluir membros

A classe ExpandoObject implementa a interface IDictionary<String, Object>. Isso permite a enumeração de membros adicionados à instância da ExpandoObject classe em runtime. Isso pode ser útil se você não souber em tempo de compilação quais membros uma instância pode ter.

O exemplo de código a seguir mostra como você pode converter uma instância da ExpandoObject classe na IDictionary<TKey,TValue> interface e enumerar os membros da instância.

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

Em linguagens que não têm sintaxe para excluir membros (como C# e Visual Basic), você pode excluir um membro lançando implicitamente uma instância da ExpandoObjectIDictionary<String, Object> interface e excluindo o membro como um par chave/valor. Isso é mostrado no exemplo a seguir.

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")

Receber notificações de alterações de propriedade

A ExpandoObject classe implementa a INotifyPropertyChanged interface e pode gerar um PropertyChanged evento quando um membro é adicionado, excluído ou modificado. Isso permite a integração da classe ExpandoObject com a vinculação de dados do Windows Presentation Foundation (WPF) e outros ambientes que exigem notificação sobre alterações no conteúdo do objeto.

O exemplo de código a seguir demonstra como criar um manipulador de eventos para o 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($"{e.PropertyName} has changed.");
    }
}
' 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