제네릭 타입의 클래스의 필드 혹은 프로퍼티에 접근해야할 때가 있다.
그러나 타입을 정확히 모르기 때문에 직접 접근할 수는 없는데 이를 해결하는 것이 FieldInfo와 PropertyInfo이다.
재사용성이 높은 코드를 작성하기에 유용하며, 본 포스팅의 예제 외에도 다양한 용도로 활용될 수 있을 것 같다.
다른 설명 필요없이 코드로 직접 확인하는 게 가장 이해하기 쉽다.
GetFields
public void GetFields<T>(T obj){
System.Reflection.FieldInfo[] fields = typeof(T).GetFields();
foreach(var field in fields){
Debug.Log (string.Format ("{0}.{1} = {2}",
typeof(T).Name, field.Name, field.GetValue (obj)));
}
}
GetProperties
public void GetProperties<T>(T obj){
System.Reflection.PropertyInfo[] props = typeof(T).GetProperties();
foreach(var prop in props){
Debug.Log (string.Format ("{0}.{1} = {2}",
typeof(T).Name, prop.Name, prop.GetValue (obj, null)));
}
}
GetID
public string GetID<T>(T obj){
if (typeof(T).GetField ("id") != null)
return typeof(T).GetField ("id").GetValue(obj).ToString();
if (typeof(T).GetProperty ("id") != null)
return typeof(T).GetProperty ("id").GetValue (obj, null).ToString();
else
return null;
}
제네릭타입의 obj를 인자로 받아서 id라는 필드 혹은 프로퍼티에 접근하여 값을 가져온다.
실험을 위한 테스트 클래스 정의
public class ExampleA{
public int id;
public string name;
public float strength;
}
public class ExampleB{
public int id;
public string name;
public float defense;
}
public class ExampleC{
public int id {get; set;}
public string name {get; set;}
public float strength {get; set;}
}
public class ExampleD{
public int id {get; set;}
public string name {get; set;}
public float defense {get; set;}
}
예제 코드
ExampleA expA = new ExampleA ();
expA.id = 1001;
expA.name = "Test";
expA.strength = 50.5f;
ExampleB expB = new ExampleB ();
expB.id = 1002;
expB.name = "Test2";
expB.defense = 59.5f;
ExampleC expC = new ExampleC ();
expC.id = 1003;
expC.name = "Test3";
expC.strength = 53.5f;
ExampleD expD = new ExampleD ();
expD.id = 1004;
expD.name = "Test4";
expD.defense = 55.5f;
Debug.Log ("----- GetFields -----");
GetFields<ExampleA> (expA);
GetFields<ExampleB> (expB);
GetFields<ExampleC> (expC);
GetFields<ExampleD> (expD);
Debug.Log ("----- GetProperties -----");
GetProperties<ExampleA> (expA);
GetProperties<ExampleB> (expB);
GetProperties<ExampleC> (expC);
GetProperties<ExampleD> (expD);
Debug.Log ("----- GetID -----");
Debug.Log(GetID<ExampleA> (expA));
Debug.Log(GetID<ExampleB> (expB));
Debug.Log(GetID<ExampleC> (expC));
Debug.Log(GetID<ExampleD> (expD));
전체 코드
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TypeofTest : MonoBehaviour {
void Start()
{
ExampleA expA = new ExampleA ();
expA.id = 1001;
expA.name = "Test";
expA.strength = 50.5f;
ExampleB expB = new ExampleB ();
expB.id = 1002;
expB.name = "Test2";
expB.defense = 59.5f;
ExampleC expC = new ExampleC ();
expC.id = 1003;
expC.name = "Test3";
expC.strength = 53.5f;
ExampleD expD = new ExampleD ();
expD.id = 1004;
expD.name = "Test4";
expD.defense = 55.5f;
Debug.Log ("----- GetFields -----");
GetFields<ExampleA> (expA);
GetFields<ExampleB> (expB);
GetFields<ExampleC> (expC);
GetFields<ExampleD> (expD);
Debug.Log ("----- GetProperties -----");
GetProperties<ExampleA> (expA);
GetProperties<ExampleB> (expB);
GetProperties<ExampleC> (expC);
GetProperties<ExampleD> (expD);
Debug.Log ("----- GetID -----");
Debug.Log(GetID<ExampleA> (expA));
Debug.Log(GetID<ExampleB> (expB));
Debug.Log(GetID<ExampleC> (expC));
Debug.Log(GetID<ExampleD> (expD));
}
public void GetFields<T>(T obj){
System.Reflection.FieldInfo[] fields = typeof(T).GetFields();
foreach(var field in fields){
Debug.Log (string.Format ("{0}.{1} = {2}",
typeof(T).Name,
field.Name,
field.GetValue (obj)));
}
}
public void GetProperties<T>(T obj){
System.Reflection.PropertyInfo[] props = typeof(T).GetProperties();
foreach(var prop in props){
Debug.Log (string.Format ("{0}.{1} = {2}",
typeof(T).Name,
prop.Name,
prop.GetValue (obj, null)));
}
}
public string GetID<T>(T obj){
if (typeof(T).GetField ("id") != null)
return typeof(T).GetField ("id").GetValue(obj).ToString();
if (typeof(T).GetProperty ("id") != null)
return typeof(T).GetProperty ("id").GetValue (obj, null).ToString();
else
return null;
}
}
public class ExampleA{
public int id;
public string name;
public float strength;
}
public class ExampleB{
public int id;
public string name;
public float defense;
}
public class ExampleC{
public int id {get; set;}
public string name {get; set;}
public float strength {get; set;}
}
public class ExampleD{
public int id {get; set;}
public string name {get; set;}
public float defense {get; set;}
}
'아카이빙 > C#' 카테고리의 다른 글
[C#] this() 생성자 (0) | 2018.06.18 |
---|---|
[C#] 얕은 복사와 깊은 복사 (0) | 2018.06.18 |
[C#] static 필드와 메소드 (0) | 2018.06.18 |
[C#] 유니티에서 foreach 성능은 개선되었을까 (1) | 2017.05.06 |
[C#] Activator.CreateInstance와 new 차이 (4) | 2017.04.15 |