Get it on Google Play


Wm뮤 :: 리플렉션

블로그 이미지
가끔 그림그리거나 3D모델링하거나
취미로 로봇만드는
퇴직한 전자과 게임프로그래머
2020.3.48f1 , 2022.3.6f1 주로 사용
모카쨩
@Ahzkwid

Recent Comment

Archive


2020. 12. 23. 15:34 Unity/C#

 

현재 클래스 명


public class ParentClass
{
  public class TestClass
  {
      public void Log()
      {
        var className = GetType().Name
        Debug.Log(className);  //TestClass가 나옴
      }
  }
}

현재 클래스 명 (부모포함)

var className = typeof(TestClass).FullName
Debug.Log(className);   //ParentClass+TestClass가 나옴

 

해당 클래스가 존재하는지

public static bool CheckClassExists(string className)
{
    return System.Type.GetType(className) != null;
}

 

 

현재 함수 명

var methodName = System.Reflection.MethodBase.GetCurrentMethod().Name;
Debug.Log(methodName);

 

 

필드명들


string[] GetClassFieldNames<T>(T targetClass)
{
    var fields = typeof(T).GetFields();
    return System.Array.ConvertAll(fields, x => x.Name);
}

 

필드명들2

string[] GetClassFieldNames<T>(T targetClass)
{
    var fields = typeof(T).GetFields();
    return Array.ConvertAll(fields, x => $"{x.Name} - type: {x.FieldType}");
}

 

 

 

 

 

특정클래스의 필드명과 함수명에 접근

var methods = typeof(Class).GetMethods();
foreach (var method in methods)
{
    EditorGUILayout.LabelField(method.Name);
}

var fields = typeof(Class).GetFields();
foreach (var field in fields)
{
    EditorGUILayout.LabelField(field.Name);
}

 

 

 

클래스할당과 연동

구조체에는 씨알도 안 먹히니 헛고생 하지 말자


public class SampleClass
{
    string numStr = "0.5";
    int num = 1;
    float value = 1.5f;
    public SampleClass() { }
    public SampleClass (string stringData)
    {

        var fields = typeof(SampleClass).GetFields();
        var targetClass = this;

        for (int i = 0; i < fields.Length; i++)
        {
            if (fields[i].FieldType == typeof(string))
            {
                fields[i].SetValue(targetClass, stringData);
            }
            else if (fields[i].FieldType == typeof(bool))
            {
                fields[i].SetValue(targetClass, bool.Parse(stringData));
            }
            else if (fields[i].FieldType == typeof(char))
            {
                fields[i].SetValue(targetClass, char.Parse(stringData));
            }
            else if (fields[i].FieldType == typeof(int))
            {
                fields[i].SetValue(targetClass, int.Parse(stringData));
            }
            else if (fields[i].FieldType == typeof(uint))
            {
                fields[i].SetValue(targetClass, uint.Parse(stringData));
            }
            else if (fields[i].FieldType == typeof(long))
            {
                fields[i].SetValue(targetClass, long.Parse(stringData));
            }
            else if (fields[i].FieldType == typeof(ulong))
            {
                fields[i].SetValue(targetClass, ulong.Parse(stringData));
            }
            else if (fields[i].FieldType == typeof(float))
            {
                fields[i].SetValue(targetClass, float.Parse(stringData));
            }
            else if (fields[i].FieldType == typeof(double))
            {
                fields[i].SetValue(targetClass, double.Parse(stringData));
            }
            else
            {
                fields[i].SetValue(targetClass, stringData);
            }
        }
    }
    
    public override string ToString()
    {
        var fields = GetType().GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
        return string.Join("\n",System.Array.ConvertAll(fields, x => $"{x.Name}: {x.GetValue(x)}" ));
    }
    /*
    public override string ToString()
    {
        var fields = typeof(SampleClass).GetFields();
        string returnString = "";
        for (int i = 0; i < fields.Length; i++)
        {
            if (i>0)
            {
                returnString += "\n";
            }
            returnString += $"{fields[i].Name}:{fields[i].GetValue(this)}";
        }

        return returnString;
    }
    */
    public static implicit operator string(SampleClass _this) //암시적 형변환, 명시적은 explicit 
    {
        return _this.ToString();
    }

}

public class MainClass : MonoBehaviour
{
	void Start()
    {
        Debug.Log("new SampleClass()\n" + new SampleClass());
        Debug.Log("new SampleClass(\"123\")\n" + new SampleClass("123"));
    }
}

 

생성자 자동 할당

public class SampleClass
{
    public int number;
    public string name;
    public SampleClass()//생성자(자동)
    {
        var targetClass = new SampleClass(123, "Name");

        //this.number = targetClass.number;
        //this.name = targetClass.name;
        //이렇게 안쳐도 됨

        var fields = GetType().GetFields();
        foreach (var field in fields)
        {
            field.SetValue(this, field.GetValue(targetClass));
        }
    }
    public SampleClass(int number, string name)//생성자
    {
        this.number = number;
        this.name = name;
    }

}

 

클래스 깊은복사, 간단한 형식만 된다. 다중 클래스등은 불가 (문자열도 안되는듯?)

public class SampleClass
{
    public int number;
    public string name;
    public SampleClass Clone()
    {
        var targetClass = new SampleClass();
        var fields = GetType().GetFields();
        foreach (var field in fields)
        {
            field.SetValue(this, field.GetValue(targetClass));
        }
        return targetClass;
    }

}

 

BindingFlags 옵션들 (지정 안되면 논퍼블릭까지 전부 반환함)

System.Reflection.BindingFlags.NonPublic //퍼블릭이 아닌것들
System.Reflection.BindingFlags.Public //퍼블릭인것들
System.Reflection.BindingFlags.Instance  //일반적인 변수들 (지역변수)
System.Reflection.BindingFlags.Static  //전역변수들


//예시 (일반적인 필드값 불러오기)
var fields = GetType().GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
        

 

 

Type검사

field.FieldType.IsValueType //bool,int,float
field.FieldType.IsArray //bool[], int[], float[]
field.FieldType.IsClass //bool[], int[], float[], string, SubClass
field.FieldType.IsEnum //Enum타입
field.FieldType.Equals(typeof(string)) //string




//클래스인지 검사
var fieldType = field.FieldType;
if (fieldType.IsClass&&(fieldType.IsArray==false)&&(fieldType.Equals(typeof(string)) == false))
{
 //Sub클래스일경우에만
}


//List인지 검사
if((fieldType.IsGenericType) && fieldType.GetGenericTypeDefinition() == typeof(List<>))

 

오브젝트에서 ?배열을 반환

이런 X같은 코드도 쓸데가 있다

object objData;
var arrDatas = (System.Collections.IList)objData;

Debug.Log($"arrDatas[0]: {arrDatas[0]}");
Debug.Log($"arrDatas[1]: {arrDatas[1]}");
Debug.Log($"arrDatas.Count: {arrDatas.Count}");

 

 

오브젝트 리스트나 오브젝트 배열을 특정 형배열로 변환

using System.Linq;

//오브젝트 리스트를 float 배열로 변환
var objList=new List<object>();
float[] floatArray=objList.Cast<float>().ToArray();


//오브젝트 배열을 string 배열로 변환
object[] objArray = new object[1];
string[] stringArray = objArray.Cast<string>().ToArray();

 

 

문자열을 FieldType으로 변환

var text = "105.0";

var converter = TypeDescriptor.GetConverter(field.FieldType);
var data = converter.ConvertFrom(text);
field.SetValue(tempClass, data);

 

 

 

배열에 할당된 변수명 추출

v1

더보기
string[] ArrayToFieldNames(object containingClassWithArray, object[] array)
{
    var fields = containingClassWithArray.GetType().GetFields();
    var fieldNames = System.Array.ConvertAll(array, x => fields.First(field => field.GetValue(containingClassWithArray) == x).Name);
    return fieldNames;
}

/* 
예시 

public class Coordinator : MonoBehaviour
{
    public BodyPart head;
    public BodyPart top;
    public BodyPart bottom;
    public BodyPart gloves;
    public BodyPart shoes;

    public BodyPart hair;
    public BodyPart eye;
    public BodyPart skin;
    public BodyPart[] bodyParts
    {
        get
        {
            return new BodyPart[] { head, top, bottom, gloves, shoes, hair, eye, skin };
        }
    }
}
이렇게 있을때

var bodyPartNames = ArrayToFieldNames(coordinator, coordinator.bodyParts);
Debug.Log(string.Join(",",bodyPartNames));
하면 head,top,bottom,gloves,shoes,hair,eye,skin로 나온다
*/

 

 

 

 

v2

v1과 구조상으로는 동일한데 클래스내부로 넣어버렸다.

이게 더 편함


string[] ArrayToFieldNames(object[] array)
{
    var fields = GetType().GetFields();
    var fieldNames = System.Array.ConvertAll(array, x => fields.First(field => field.GetValue(this) == x).Name);
    return fieldNames;
}
/*
//샘플
    public BodyPart head;
    public BodyPart top;
    public BodyPart bottom;
    public BodyPart gloves;
    public BodyPart shoes;

    public BodyPart hair;
    public BodyPart eye;
    public BodyPart skin;
    public BodyPart[] bodyParts
    {
        get
        {
            return new BodyPart[] { head, top, bottom, gloves, shoes, hair, eye, skin };
        }
    }
    public string[] bodyPartNames
    {
        get
        {
            return ArrayToFieldNames(bodyParts);
        }
    }
*/

근데 이방법 쓸바엔 그냥 클래스 안에 name값 넣어서 써라

'Unity > C#' 카테고리의 다른 글

MapBorder  (0) 2020.12.24
그래디언트효과  (0) 2020.10.20
유니티 에디터 관련  (0) 2020.10.05
posted by 모카쨩

  • total
  • today
  • yesterday

Recent Post

저사양 유저용 블로그 진입