프로그램의 런타임중에 코드에 대한 정보를 조사하고 조작할 수 있는 기능
Reflection
을 사용하면 객체가 가지고 있는 모든 정보를 런타임에 동적으로 뜯어보고 분석할 수 있고, 정보를 얻어 직접 메서드를 호출하거나 프로퍼티를 변경할 수 있다.
// Program.cs
class Program
{
private class Monster
{
public int hp;
protected int attack;
private float speed;
private void Attack() { }
}
private static void Main(string[] args)
{
Monster monster = new Monster();
Type type = monster.GetType();
// fieldInfo[]로 반환된다.
var fields = type.GetFields(System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.NonPublic
| System.Reflection.BindingFlags.Static
| System.Reflection.BindingFlags.Instance);
foreach (var field in fields)
{
string access = "protected";
if (field.IsPublic)
access = "public";
else if(field.IsPrivate)
access = "IsPrivate";
Console.WriteLine($"{access} {field.FieldType.Name} {field.Name}");
}
}
}
C#의 모든 객체들은 Object
에서 파생되어 나오기 때문에 Object
에 정의된 함수들을 사용할 수 있다
GetType(), Equals(), ToString(), GetHashCode()
등등GetType()
GetType()
을 이용하여 객체가 가지고 있는 모든 정보를 알 수 있고, 그 정보를 Type
자료형에 담을 수 있다.GetFields()
GetFields()
를 이용하여 Type
이 가지고 있는 멤버들 즉, 필드를 FieldInfo
타입의 배열로 반환한다.BindingFlags
를 매개변수로 하여 검색 조건을 설정할 수 있다.System.Reflection.BindingFlags.Public
→ public인 멤버 추출FieldInfo
```csharp
foreach (var field in fields) // field는 FieldInfo를 의미함.
{
string access = "protected";
if (field.IsPublic) // 필드가 public인지 판별
access = "public";
else if(field.IsPrivate) // 필드가 private인지 판별
access = "IsPrivate";
// 접근 한정자, 필드의 자료형, 필드의 이름을 출력
Console.WriteLine($"{access} {field.FieldType.Name} {field.Name}");
}
```
access
: foreach
문 안의 조건문을 이용하여 접근 한정자를 기록한다.field.FieldType.Name
: 필드의 자료형을 반환한다.field.Name
: 필드의 이름을 반환한다.Single
은 float
과 같다.Reflection을 이용하면 클래스의
x-ray
를 찍는 것과 같다.
코드에 메타데이터를 추가하는 방법을 제공한다.
주석은 프로그래머들이 정보를 전달하기 위한 참고사항일 뿐 컴퓨터 입장에서 보면 컴파일 하지 않고 지나가지만
Attribute
를 이용하면 런타임에서 참고할 수 있는 메타데이터(힌트)를 남길 수 있다.
System.Attribute
를 상속받는다.[Attribute 이름]
을 써준다.// Program.cs
using System.Reflection;
class Program
{
class Important : System.Attribute
{
private string messege;
public Important(string messege) // 생성자를 이용하여 메세지를 입력한다.
{
this.messege = messege;
}
}
private class Monster
{
[Important("Very Important")] // Attribute를 이용하여 중요한 멤버임을 나타낸다.
public int hp;
protected int attack;
private float speed;
private void Attack() { }
}
private static void Main(string[] args)
{
Monster monster = new Monster();
Type type = monster.GetType();
var fields = type.GetFields(System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.NonPublic
| System.Reflection.BindingFlags.Static
| System.Reflection.BindingFlags.Instance);
foreach (var field in fields)
{
string access = "protected";
if (field.IsPublic)
access = "public";
else if(field.IsPrivate)
access = "IsPrivate";
Console.WriteLine($"{access} {field.FieldType.Name} {field.Name}");
var attributes = field.GetCustomAttributes();
}
}
}
Custom Attribute 클래스 생성
class Important : System.Attribute
{
private string messege;
public Important(string messege) // 생성자를 이용하여 메세지를 입력한다.
{
this.messege = messege;
}
}
Important
라는 클래스를 만들고 System.Attribute
를 상속받아 Custom Attribute를 만든다.
생성자에 messege
라는 매개변수를 넣어 메세지를 남긴다.
Custom Attribute 사용
[Important("Very Important")]
public int hp;
hp
라는 멤버에 Important
를 추가해 Attribute를 붙여준다.
hp
는Important
라는 정보를 런타임에 알 수 있게 된 것이다.
추가적으로 hp
는 "Very Important"
라는 메세지를 담고 있는 것을 확인할 수 있다.
Attribute 확인
var attributes = field.GetCustomAttributes();
GetCustomAttributes()
를 이용하여 Attribute를 불러올 수 있다.
Reflection
을 이용하여 런타임 중 객체의 모든 정보에 접근할 수 있다.Attribute
를 이용하여 런타임 중 참고할 수 있는 메타데이터를 남길 수 있다.
인프런 [C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part1: C# 기초 프로그래밍 입문 강의를 듣고 공식 문서를 참고하여 정리한 글 입니다.
개인 공부를 정리한 글이기 때문에 틀린 부분이 있을 수 있습니다.
진짜 지려요..