아카이빙/C#

[C#] FieldInfo와 PropertyInfo

셩님 2017. 5. 6. 01:54

[C#] FieldInfo, PropertyInfo

제네릭 타입의 클래스의 필드 혹은 프로퍼티에 접근해야할 때가 있다.

그러나 타입을 정확히 모르기 때문에 직접 접근할 수는 없는데 이를 해결하는 것이 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;}
}