본 내용은 CODE4IT의 C# Tip: Convert ExpandoObjects to IDictionary의 내용을 보완한 글입니다.
ExpandoObject
숙련된 C# 개발자라도 ExpandoObject를 처음 들었거나 알기는 하지만 사용해보지 않았을 수 있습니다.
ExpandoObject 는 dynamic 형식을 통해 동적으로 속성을 추가하고 사용할 수 있게 해줍니다.
dynamic myObj = new ExpandoObject();
myObj.Name = "Davide";
myObj.Age = 30;
myObj 인스턴스는 ExpandoObject 인스턴스이지만 dynamic 형식이므로 속성의 존재 유무를 컴파일 시점에서 확인하지 않으며 속성을 사용하는 런타임 시점에서 새로운 속성명으로 값을 설정하고 읽을 수 있습니다.
마치 파이썬과 같은 동적 언어 같지요?
동적으로 추가된 속성은 어떻게 조회할 수 있나요?
ExpandoObject 인스턴스는 동적으로 속성이 계속 추가될 수 있기 때문에 어떤 속성이 추가되었는지 조회가 필요합니다.
이는 ExpandoObject가 구현한 인터페이스를 통해 가능한데요
public sealed class ExpandoObject : ICollection<KeyValuePair<string, object?>>, IEnumerable<KeyValuePair<string, object?>>, IEnumerable, IDictionary<string, object?>, INotifyPropertyChanged, IDynamicMetaObjectProvider
KeyValuePair<string,object?>의 ICollection 인터페이스 및 IDictionary<string,object?> 인터페이스가 구현되어 있기 때문에 다음 처럼 사용할 수 있습니다.
using System.ComponentModel;
using System.Dynamic;
dynamic p = new ExpandoObject();
// Console.WriteLine(p.Name); // 아직 Name 속성이 없으므로 예외
p.Name = "David";
p.Age = 30;
IDictionary<string, object?> dic = p;
dic["■■■"] = "Male";
Console.WriteLine(p.■■■);
foreach (var kv in p)
{
Console.WriteLine(kv);
}
| 출력
Male
[Name, David]
[Age, 30]
[■■■, Male]
반응 개체로도 사용
ExpandoObject는 또한 INotifyPropertyChanged 인터페이스를 구현해서 다음처럼 속성이 변경될 때 반응할 수 있습니다.
using System.ComponentModel;
using System.Dynamic;
dynamic p = new ExpandoObject();
(p as INotifyPropertyChanged)!.PropertyChanged += (s, e) =>
{
Console.WriteLine($"Changed Property : {e.PropertyName}");
};
// Console.WriteLine(p.Name); // 아직 Name 속성이 없으므로 예외
p.Name = "David";
p.Age = 30;
IDictionary<string, object?> dic = p;
dic["■■■"] = "Male";
Console.WriteLine(p.■■■);
foreach (var kv in p)
{
Console.WriteLine(kv);
}
| 출력
Changed Property : Name
Changed Property : Age
Changed Property : ■■■
Male
[Name, David]
[Age, 30]
[■■■, Male]
