System.Dynamic.ExpandoObject 클래스

이 문서에서는 이 API에 대한 참조 설명서에 대한 추가 설명서를 제공합니다.

ExpandoObject 클래스를 사용하면 런타임에 해당 인스턴스의 멤버를 추가 및 삭제하고 이러한 멤버의 값을 설정하고 가져올 수 있습니다. 이 클래스는 동적 바인딩을 지원하므로 다음과 같이 더 복잡한 구문 대신 표준 sampleObject.sampleMember 구문을 사용할 수 있습니다 sampleObject.GetAttribute("sampleMember").

이 클래스는 ExpandoObject 표준 DLR(동적 언어 런타임) 인터페이스를 구현합니다. 이 인터페이스 IDynamicMetaObjectProvider를 사용하면 DLR 상호 운용성 모델을 지원하는 언어 간에 클래스 인스턴스 ExpandoObject 를 공유할 수 있습니다. 예를 들어 C#에서 클래스의 인스턴스를 ExpandoObject 만든 다음 IronPython 함수에 전달할 수 있습니다. 자세한 내용은 동적 언어 런타임 개요ExpandoObject 소개를 참조하세요.

클래스 ExpandoObject 는 멤버 가져오기, 설정 및 호출을 가능하게 하는 동적 개체 개념의 구현입니다. 고유한 동적 디스패치 의미 체계가 있는 형식을 정의하려면 클래스를 DynamicObject 사용합니다. 동적 개체가 상호 운용성 프로토콜에 참여하는 방법을 정의하고 DLR 빠른 동적 디스패치 캐싱을 관리하려면 고유한 인터페이스 구현을 IDynamicMetaObjectProvider 만듭니다.

인스턴스 만들기

C#에서 클래스 인스턴스에 대해 지연 바인딩을 ExpandoObject 사용하도록 설정하려면 키워드(keyword) 사용해야 dynamic 합니다. 자세한 내용은 dynamic 형식 사용을 참조하세요.

Visual Basic에서 동적 작업은 지연 바인딩에서 지원됩니다. 자세한 내용은 초기 바인딩 및 지연 바인딩(Visual Basic)을 참조하세요.

다음 코드 예제에서는 클래스의 인스턴스를 만드는 방법을 보여 줍니다 ExpandoObject .

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

새 멤버 추가

클래스의 ExpandoObject 인스턴스에 속성, 메서드 및 이벤트를 추가할 수 있습니다.

다음 코드 예제에서는 클래스의 인스턴스에 새 속성을 추가 하는 방법을 보여 줍니다 ExpandoObject .

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

메서드는 대리자로 저장되는 람다 식을 나타내며 필요할 때 호출할 수 있습니다. 다음 코드 예제에서는 동적 속성의 값을 증가 하는 메서드를 추가 하는 방법을 보여 줍니다.

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

다음 코드 예제에서는 클래스의 인스턴스에 이벤트를 추가 하는 방법을 보여 줍니다 ExpandoObject .

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

매개 변수로 전달

클래스의 ExpandoObject 인스턴스를 매개 변수로 전달할 수 있습니다. 이러한 인스턴스는 C#의 동적 개체 및 Visual Basic의 런타임에 바인딩된 개체로 처리됩니다. 즉, 개체 멤버에 대한 IntelliSense가 없으며 존재하지 않는 멤버를 호출할 때 컴파일러 오류가 표시되지 않습니다. 존재하지 않는 멤버를 호출하면 예외가 발생합니다.

다음 코드 예제에서는 메서드를 만들고 사용하여 속성의 이름과 값을 인쇄하는 방법을 보여 줍니다.

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

멤버 열거 및 삭제

ExpandoObject 클래스가 IDictionary<String, Object> 인터페이스를 구현합니다. 이렇게 하면 런타임에 클래스 인스턴스에 추가된 멤버를 ExpandoObject 열거할 수 있습니다. 이는 컴파일 시간에 인스턴스에 있을 수 있는 멤버를 모르는 경우에 유용할 수 있습니다.

다음 코드 예제에서는 클래스의 ExpandoObject 인스턴스를 인터페이스로 IDictionary<TKey,TValue> 캐스팅하고 인스턴스의 멤버를 열거하는 방법을 보여 줍니다.

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

멤버를 삭제하는 구문(예: C# 및 Visual Basic)이 없는 언어에서는 인터페이스에 인스턴스 ExpandoObject 를 암시적으로 캐스팅한 다음 멤버를 키/값 쌍으로 삭제하여 멤버를 삭제할 IDictionary<String, Object> 수 있습니다. 이 방법은 다음 예제에서 확인할 수 있습니다.

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

속성 변경 알림 받기

클래스는 ExpandoObject 인터페이스를 INotifyPropertyChanged 구현하고 멤버가 PropertyChanged 추가, 삭제 또는 수정될 때 이벤트를 발생할 수 있습니다. 이렇게 하면 ExpandoObject WPF(Windows Presentation Foundation) 데이터 바인딩 및 개체 콘텐츠 변경에 대한 알림이 필요한 기타 환경과 클래스를 통합할 수 있습니다.

다음 코드 예제에서는 이벤트에 대 한 이벤트 처리기를 만드는 방법을 보여 줍니다 PropertyChanged .

// 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