728x90
컴파일러에게 변수의 Type을 체크하지 않도록 하고
런타임시까지는 해당 타입을 알 수 없음을 표시
// 1. dynamic은 중간에 형을 변환할 수 있다.
dynamic v = 1;
// System.Int32 출력
Console.WriteLine(v.GetType());
v = "abc";
// System.String 출력
Console.WriteLine(v.GetType());
=====================================
// 2. dynamic은 cast가 필요없다
object o = 10;
// 틀린표현
// (에러: Operator '+' cannot be applied to operands of type 'object' and 'int')
o = o + 20;
// 맞는 표현: object 타입은 casting이 필요하다
o = (int)o + 20;
// dynamic 타입은 casting이 필요없다.
dynamic d = 10;
d = d + 20;
익명타입 객체를 dynamic 에 할당하고 이를 다른 클래스 메서드에 파라미터로 전달하는 예시
- 문제1 : 익명타입은 한번 생성된 후 다시 새로운 속성을 추가할 수 없다
- 문제2 : 익명타입 자체가 메서드 이벤트 등을 갖지 못함
// 동일 어셈블리에서 익명타입에 dynamic 사용한 경우
class Class1
{
public void Run()
{
dynamic t = new { Name = "Kim", Age = 25 };
var c = new Class2();
c.Run(t);
}
}
class Class2
{
public void Run(dynamic o)
{
// dynamic 타입의 속성 직접 사용
Console.WriteLine(o.Name);
Console.WriteLine(o.Age);
}
}
ExpandoObject : dynamic 타입에 속성, 메서드, 이벤트를 동적으로 쉽게 할당할 수 있게 도와주는 클래스
dynamic 타입을 쉽게 생성하도록 도와주는 ExpandoObject 클래스
보다 유연한 Customization을 위한 고급 dynamic 기능을 지원하는 DynamicObject 클래스가 있는데
여기선 ExpandoObject 를 보자.
//ExpandoObject
public class Myclass
{
public void M1()
{
// ExpandoObject에서 dynamic 타입 생성
dynamic person = new ExpandoObject();
// 속성 지정
person.Name = "Kim";
person.Age = 10;
// 메서드 지정
person.Display = (Action)(() =>
{
Console.WriteLine("{0} {1}", person.Name, person.Age);
});
person.ChangeAge = (Action<int>)((age) => {
person.Age = age;
if (person.AgeChanged != null)
{
person.AgeChanged(this, EventArgs.Empty);
}
});
// 이벤트 초기화
person.AgeChanged = null; //dynamic 이벤트는 먼저 null 초기화함
// 이벤트핸들러 지정
person.AgeChanged += new EventHandler(OnAgeChanged);
// 타 메서드에 파라미터로 전달
M2(person);
}
private void OnAgeChanged(object sender, EventArgs e)
{
Console.WriteLine("Age changed");
}
// dynamic 파라미터 전달받음
public void M2(dynamic d)
{
// dynamic 타입 메서드 호출
d.Display();
d.ChangeAge(20);
d.Display();
}
}
ExpandoObject의 dynamic 멤버 보기
ExpandoObject 클래스는 동적으로 추가되는 멤버들을 내부 해시테이블에 저장하고 있는데, 필요한 경우 이 정보를 IDictionary<String, Object> 인터페이스를 통해 쉽게 엑세스할 수 있다.
즉, ExpandoObject 클래스 자체가 IDictionary<String, Object> 인터페이스 구현하고 있어서 이 클래스 객체를 IDictionary<String, Object> 인터페이스로 캐스팅하여 내부 멤버 데이타를 엑세스할 수 있다.
using System;
using System.Collections.Generic;
using System.Dynamic;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
M11 aa = new M11();
aa.M1();
}
}
class M11
{
public void M1()
{
dynamic person = new ExpandoObject();
person.Name = "Kim";
person.Age = 10;
person.Display = (Action)(() => { });
person.ChangeAge = (Action<int>)((age) => { person.Age = age; });
person.AgeChanged = null;
person.AgeChanged += new EventHandler((s, e) => { });
// ExpandoObject를 IDictionary로 변환
var dict = (IDictionary<string, object>)person;
// person 의 속성,메서드,이벤트는
// IDictionary 해시테이블에 저정되어 있는데
// 아래는 이를 출력함
foreach (var d in dict)
{
Console.WriteLine("{0}: {1}", d.Key, d.Value);
}
}
}
}
728x90