뇌를 자극하는 C# 4.0 프로그래밍/ 리플렉션과 애트리뷰트

리플렉션

  • 리플렉션은 객체의 형식 정보를 들여다보는 기능으로 이 기능을 이용하면 프로그램 실행 중에 객체의 형식 이름부터, 프로퍼티 목록, 필드, 이벤트 목록까지 모두 열어 볼 수 있다.
  • 형식의 이름만 있다면 동적으로 인스턴스를 만들 수도 있고, 그 인스턴스의 메소드를 호출할 수도 있다. 또한 새로운 데이터 형식을 동적으로 만들 수도 있다.
  • .NET 팀은 모든 형식을 들여다 볼 수 있는 장치를 설계했다. 모든 데이터 형식의 조상인 Object 형식에 GetType() 메소드를 만들어 놓은 것이 그것이다.

Object.GetType() 메소드와 Type 클래스

// GetType() 메소드와 Type 형식을 사용하는 방법 예시
int a = 0;

Type type1 = a.GetType();
FieldInfo[] fields = type1.GetFields();

foreach (FieldInfo field in fields)
{
    Console.WriteLine("Type: {0}, Name:{1}", field.FieldType.Name, field.Name);
}

// GetFields(), GetMethods() 에 검색 옵션 지정하는 예시
// 옵션은 System.Reflection.BindingFlags 열거형으로 구성된다.
Type type2 = a.GetType();

// Public 인스턴스 필드 조회
var fields1 = type.GetFields( BindingFlags.Public | BindingFlags.Intance );

// 비 Public 인스턴스 필드 조회
var fields1 = type.GetFields( BindingFlags.NonPublic | BindingFlags.Intance );

// Public 정적 필드 조회
var fields1 = type.GetFields( BindingFlags.Public | BindingFlags.Static );

// 비 Public 정적 필드 조회
var fields1 = type.GetFields( BindingFlags.NonPublic | BindingFlags.Static );
Type 형식의 메소드 반환 형식 설명
GetConstructors() ConstructorInfo[] 해당 형식의 모든 생성자 목록을 반환
GetEvents() EventInfo[] 해당 형식의 이벤트 목록을 반환
GetFields() FieldInfo[] 해당 형식의 필드 목록을 반환
GetGenericArguments() Type[] 해당 형식의 형식 매개 변수 목록을 반환
GetInterfaces() Type[] 해당 형식이 상속하는 인터페이스 목록을 반환
GetMembers() MemberInfo[] 해당 형식의 멤버 목록을 반환
GetMethods() MethodInfo[] 해당 형식의 메소드 목록을 반환
GetNestedTypes() Type[] 해당 형식의 내장 형식 목록을 반환
GetProperties() PropertyInfo[] 해당 형식의 프로퍼티 목록을 반환

리플렉션을 이용해서 객체 생성하고 이용하기

// 인스턴스를 동적으로 만드는 예제
class Profile
{
    public Name { get; set; }
    public Phone { get; set; }
}

static void Main ()
{
    Type type = typeof(Profile);

    // Activator.CreateInstance()는 입력받은 형식의 인스턴스를 생성하여 반환한다.
    Object profile = Activator.CreateInstance(type);

    // PropertyInfo 객체는 SetValue(), GetValue()를 통해 값을 할당하고 읽어올 수 있다.
    PropertyInfo name = type.PropertyInfo("Name");
    PropertyInfo phone = type.PropertyInfo("Phone");

    // SetValue(), GetValue()의 마지막 매개 변수는 인덱서의 인덱스를 위해 사용된다. 
    // 프로퍼티는 인덱서가 필요 없으므로 null을 할당.
    name.SetValue(profile, 박찬호", null);
    phone.SetValue(profile, "010-1234-5678", null);

    Console.WriteLine("{0}, {1}", name.GetValue(profile, null), phone.GetValue(profile, null));
}

형식 내보내기

  • 리플렉션을 이용하면 런타임에 원하는 형식의 정보를 읽어 낼 수 있고, 그 형식의 인스턴스도 만들 수 있으며, 프로퍼티나 필드에 값을 할당하고 메소드를 호출할 수도 있다.
  • C#은 여기에 한 술 떠서 프로그램 실행 중에 새로운 형식을 만들어 낼 수도 있다.
  • (이하 내용은 어셈블리 단의 내용을 다루는데, 개인적으로는 흥미가 없으므로 생략)

애트리뷰트

애트리뷰트 사용하기

// 애트리뷰트 사용 방법
[ 애트리뷰트이름 (애트리뷰트매개변수) ]
public void MyMethod ()
{
    // ...
}

// 애트리뷰트 사용 예시
class MyClass
{
    [Obsolete("OldMethod()는 폐기되었습니다. NewMethod()를 이용하세요")]
    public void OldMethod ()
    {
        // ...
    }

    public void NewMethod ()
    {
        // ...
    }
}

내가 만드는 애트리뷰트

// 애트리뷰트 만드는 방법
class History : System.Attribute
{
    private string programmer;

    public double Version { get; set; }
    public string Changes { get; set; }

    // 생성자
    public History (string programmer)
    {
        this.programmer = programmer;
        Version = 1.0;
        Changes = "First Release";
    }

    public string Programmer
    {
        get { return programmer; }
    }
}

// 만든 애트리뷰트 사용 방법
[History("Sean", Version = 0.1, Changes = "2010-11-01 Created class stub")]
class MyClass
{
    // ...
}
  • 모든 애트리뷰트는 System.Attribute 클래스의 상속을 받아 만들어진다. 따라서 System.Attribute를 상속 받는 것만으로도 애트리뷰트 하나를 만든 셈이 된다.
  • 사용할 때는 [와 ] 안에 애트리뷰트 이름을 넣어 사용하면 된다.

애트리뷰트의 애트리뷰트

// System.AttributeUsage 사용 예시
[System.AttributeUsage(System.AttributeTarget.Class | System.AttributeTarget.Method, AllowMultiple = true)]
class History : System.Attribute
{
    // ...
}
  • System.AttributeUsage는 애트리뷰트의 애트리뷰트이다. 선언하는 애트리뷰트 위에 위와 같이 System.AttributeUsage 애트리뷰트를 사용하면 애트리뷰트에 대한 설정을 할 수 있다.
Attribute Target 설명
All 이 표의 모든 요소
Assembly 어셈블리
Module 모듈
Interface 인터페이스
Class 클래스
Struct 구조체
ClassMembers 클래스 안에 선언된 클래스나 구조체를 포함한 클래스의 모든 멤버
Constructor 생성자
Delegate 델리게이트
Enum 열거형
Event 이벤트
Field 필드
Property 프로퍼티
Method 메소드
Parameter 메소드의 매개 변수
ReturnValue 메소드의 반환값
[ssba]

The author

지성을 추구하는 디자이너/ suyeongpark@abyne.com

댓글 남기기