C#에서 동적 프로그래밍은 개발자에게 런타임에 객체의 속성과 메서드를 정의할 수 있는 유연성을 제공합니다. 이 글에서는 C#의 동적 프로그래밍의 두 가지 주요 구성 요소인 ExpandoObject와 DynamicObject를 중심으로 그 활용 방법과 장점을 살펴보겠습니다.
동적 프로그래밍 개요
동적 프로그래밍은 컴파일 시간에 타입을 정의하는 대신 런타임에 동적으로 타입을 정의할 수 있게 합니다. 이는 데이터 구조가 변경될 수 있는 시나리오나 보다 유연한 접근이 필요한 시스템과 통합할 때 특히 유용합니다.
- 유연성: 멤버(속성, 메서드)를 즉석에서 추가하거나 제거할 수 있습니다.
- 상호 운용성: COM 객체, JSON API 및 기타 동적 소스와의 통합이 용이합니다.
- 단순성: 한 번만 사용될 클래스 생성을 위한 보일러플레이트 코드를 줄여줍니다.
ExpandoObject
ExpandoObject는 .NET에서 제공하는 클래스이며, IDynamicMetaObjectProvider를 구현하여 동적 동작을 지원합니다. 이는 사전처럼 작동하지만 속성 변경 알림과 같은 추가 기능을 제공합니다.
주요 기능
- 속성 동적 추가: 사전 정의된 클래스 없이 런타임에 속성을 추가할 수 있습니다.
- LINQ 쿼리 지원: 컬렉션이기 때문에 LINQ를 활용하여 내용을 쿼리할 수 있습니다.
- 쉬운 직렬화/역직렬화: Newtonsoft.Json과 같은 JSON 직렬화 라이브러리와 잘 작동합니다.
사용 예시
using System;
using System.Dynamic;
class Program
{
static void Main()
{
// ExpandoObject 인스턴스 생성
dynamic person = new ExpandoObject();
// 속성 동적 추가
person.Name = "John Doe";
person.Age = 30;
// 메서드 동적 추가
person.Introduce = (Action)(() =>
Console.WriteLine($"Hello! My name is {person.Name} and I am {person.Age} years old."));
// 메서드 호출
person.Introduce();
// 반사와 유사한 구문을 사용하여 추가된 속성 접근
var dict = (IDictionary<string, object>)person;
foreach(var kvp in dict)
Console.WriteLine($"{kvp.Key}: {kvp.Value}");
}
}
이 예시에서는 ExpandoObject의 인스턴스를 생성하고, 속성(Name, Age)과 메서드(Introduce)를 동적으로 추가했습니다. 기본 사전 인터페이스를 통한 반사와 유사한 접근을 사용하여 반복했습니다.
DynamicObject
ExpandoObject가 동적 타입을 생성하는 간단한 방법을 제공하는 반면, DynamicObject는 기본 클래스의 특정 메서드를 재정의하여 멤버의 동작을 보다 세밀하게 제어할 수 있습니다.
주요 기능
- 사용자 정의 동작:
TryInvokeMember,TryGetMember등의 메서드를 재정의하여 멤버에 접근할 때 객체의 동작을 사용자 정의할 수 있습니다. - 멤버에 대한 더 많은 제어: 값의 가져오기/설정 또는 함수 호출에 대한 특정 로직을 정의할 수 있습니다.
- 통합 유연성: 사용자 정의 동작이 필요한 다양한 프레임워크(예: ASP.NET)에 통합할 수 있습니다.
사용 예시
using System;
using System.Dynamic;
public class Person : DynamicObject
{
private readonly Dictionary<string, object> _properties = new();
public override bool TryGetMember(GetMemberBinder binder, out object? result)
{
return _properties.TryGetValue(binder.Name, out result);
}
public override bool TrySetMember(SetMemberBinder binder, object? value)
{
_properties[binder.Name] = value;
return true;
}
}
class Program
{
static void Main()
{
dynamic person = new Person();
// 속성 동적 설정
person.Name = "Jane Doe";
person.Age = 28;
Console.WriteLine($"Name: {person.Name}, Age: {person.Age}");
}
}
이 예시에서는 DynamicObject에서 파생된 사용자 정의 클래스를 생성하고, 재정의된 메서드(TryGetMember, TrySetMember)를 사용하여 멤버 접근 동작을 구현하고, 자체 저장 메커니즘(_properties)을 관리했습니다.
결론
ExpandoObject와 DynamicObject 모두 C#에서 동적 데이터를 다루기 위한 강력한 도구를 제공합니다. 간단한 키-값 저장소가 필요한 경우와 객체의 상호작용에 대한 보다 정교한 동작 제어가 필요한 경우 중에서 선택할 수 있습니다. 이러한 기능을 효과적으로 활용하면 변화하는 요구 사항에 원활하게 적응하면서도 깔끔한 코드 아키텍처를 유지하는 애플리케이션을 구축할 수 있습니다.
'프로그래밍 > C#' 카테고리의 다른 글
| C#에서 P/Invoke를 활용한 상호 운용성의 이해 (0) | 2025.09.16 |
|---|---|
| 고급 C#에서의 COM 상호 운용성: 효율성과 재사용성 극대화 (0) | 2025.09.15 |
| C#에서의 동적 프로그래밍: 유연성과 적응력의 새로운 지평 (0) | 2025.09.15 |
| C# 리플렉션과 동적 코드 생성의 심층 분석 (0) | 2025.09.15 |
| C# 리플렉션: 런타임 객체 조작의 강력한 도구 (0) | 2025.09.15 |