最近感觉在调试时总是要把一些对象的属性都打印出来,比如收到网络协议后把各个值打印出来看看。感觉可以利用反射直接获取对象的内容,这样就不用每次都手写了。
这里是unity平台的c#代码,test挂到空物体上就能执行了。因为用了反射所以先禁止在运行时执行了。
思路大概就是这样,直接上代码。
核心代码如下:
using System;
using System.Collections;
using System.Text;
public static class GetObjectInfo
{
public static string GetObjInfo(this object obj, int maxDeep=3, bool propertie=false)
{
#if !UNITY_EDITOR
return "";
#endif
_maxDeep = maxDeep;
_propertie = propertie;
return GetObjInfoHelp(obj, 0);
}
private static int _maxDeep = 3; // 有些类拿的引用可能太复杂了,需要限制深度
private static bool _propertie = false; // 访问属性还是有风险的,加个开关
private static string GetObjInfoHelp(this object t, int deep)
{
#if !UNITY_EDITOR
return "";
#endif
if (t == null) { return "null"; }
if (t.GetType().IsValueType) return t.ToString();
if (t is string) return $"\"{t}\"";
if (deep >= _maxDeep) return "\"深度已达最大\"";
string tab = "";
for (int i = 0; i < deep; i++) { tab += "\t"; }
StringBuilder tStr = new StringBuilder();
// 如果是容器应该把里面的东西搞出来
var enumer = t as IEnumerable;
if (enumer != null)
{
tStr.Append(tab + $"[ // {t.GetType()}\n");
foreach (var item in enumer)
{
//if (item == null) continue;
var type = item?.GetType();
string value = GetObjInfoHelp(item, deep + 1);
tStr.Append(tab + $"\t{value}, // {type}\n");
}
tStr.Append(tab + $"],\n");
//不返回,可能还有其他字段属性
//return tStr.ToString();
}
// 如果是类
tStr.Append(tab + $"{{ // {t.GetType()}\n");
//获取所有字段
var fields = t.GetType().GetFields();
foreach (var item in fields)
{
//如果标记为 Obsolete 就不要访问了
if (item.IsDefined(typeof(ObsoleteAttribute), true)) { continue; }
string value = GetObjInfoHelp(item.GetValue(t), deep + 1);
tStr.Append(tab + $"\t\"{item.Name}\" : {value}, // {item.FieldType}\n");
}
//获取所有属性
if (_propertie)
{
var properties = t.GetType().GetProperties();
foreach (var item in properties)
{
//如果标记为 Obsolete 就不要访问了
if (item.IsDefined(typeof(ObsoleteAttribute), true)) { continue; }
string value;
//this[]有可能报TargetParameterCountException异常
try { value = GetObjInfoHelp(item.GetValue(t), deep + 1); }
catch (Exception e) { value = "\"error!\n" + e + "\""; }
tStr.Append(tab + $"\t\"{item.Name}\" : {value}, // {item.PropertyType}\n");
}
}
tStr.Append(tab + $"}}\n");
return tStr.ToString();
}
}
测试代码如下:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
public class GetObjectInfoTest : MonoBehaviour
{
[ContextMenu("执行")]
void Start()
{
StringBuilder builder = new StringBuilder();
var obj = new Data()
{
numInt = 111,
numFloat = 123.456f,
text = "abc",
};
obj.left = new Data();
obj.right = new Data();
builder.AppendLine();
builder.AppendLine(11.GetObjInfo());
builder.AppendLine(11.5.GetObjInfo());
builder.AppendLine("字符串".GetObjInfo());
builder.AppendLine(GetObjectInfo.GetObjInfo(null));
builder.AppendLine((new Data().GetObjInfo()));
builder.AppendLine(obj.GetObjInfo());
obj.right = obj;//考虑一下循环引用的问题吧
builder.AppendLine(obj.GetObjInfo());
obj.right = new Data();
var list = new List() { 1, 2, 3, 4, 5 };
builder.AppendLine(list.GetObjInfo());
obj.list = new List() { 1, 2, 3, 4, 5 };
builder.AppendLine(obj.GetObjInfo());
var tf = GameObject.Find("Main Camera").GetComponent();
builder.AppendLine(tf.GetObjInfo());
var go = GameObject.Find("Main Camera");
builder.AppendLine(go.GetObjInfo());
var c = GameObject.Find("Main Camera").GetComponent();
builder.AppendLine(c.GetObjInfo());
var dic = new Dictionary() { { 1, 111 }, { 2, 222 }, { 3, 333 }, };
builder.AppendLine(dic.GetObjInfo());
var array = new Data[] { obj, obj.left, obj.right };
builder.AppendLine(array.GetObjInfo());
var array2 = new Data[] { obj, obj.left, null, obj.right, new SubData() };
builder.AppendLine(array2.GetObjInfo());
Debug.Log(builder);
}
}
public class Data
{
public int numInt;
public float numFloat;
public string text;
public Data left;
public Data right;
public List list;
}
public class SubData : Data
{
int subData;
}
测试代码的的输出如下:
11
11.5
"字符串"
null
{ // Data
"numInt" : 0, // System.Int32
"numFloat" : 0, // System.Single
"text" : null, // System.String
"left" : null, // Data
"right" : null, // Data
"list" : null, // System.Collections.Generic.List`1[System.Int32]
}
{ // Data
"numInt" : 111, // System.Int32
"numFloat" : 123.456, // System.Single
"text" : "abc", // System.String
"left" : { // Data
"numInt" : 0, // System.Int32
"numFloat" : 0, // System.Single
"text" : null, // System.String
"left" : null, // Data
"right" : null, // Data
"list" : null, // System.Collections.Generic.List`1[System.Int32]
}
, // Data
"right" : { // Data
"numInt" : 0, // System.Int32
"numFloat" : 0, // System.Single
"text" : null, // System.String
"left" : null, // Data
"right" : null, // Data
"list" : null, // System.Collections.Generic.List`1[System.Int32]
}
, // Data
"list" : null, // System.Collections.Generic.List`1[System.Int32]
}
{ // Data
"numInt" : 111, // System.Int32
"numFloat" : 123.456, // System.Single
"text" : "abc", // System.String
"left" : { // Data
"numInt" : 0, // System.Int32
"numFloat" : 0, // System.Single
"text" : null, // System.String
"left" : null, // Data
"right" : null, // Data
"list" : null, // System.Collections.Generic.List`1[System.Int32]
}
, // Data
"right" : { // Data
"numInt" : 111, // System.Int32
"numFloat" : 123.456, // System.Single
"text" : "abc", // System.String
"left" : { // Data
"numInt" : 0, // System.Int32
"numFloat" : 0, // System.Single
"text" : null, // System.String
"left" : null, // Data
"right" : null, // Data
"list" : null, // System.Collections.Generic.List`1[System.Int32]
}
, // Data
"right" : { // Data
"numInt" : 111, // System.Int32
"numFloat" : 123.456, // System.Single
"text" : "abc", // System.String
"left" : "深度已达最大", // Data
"right" : "深度已达最大", // Data
"list" : null, // System.Collections.Generic.List`1[System.Int32]
}
, // Data
"list" : null, // System.Collections.Generic.List`1[System.Int32]
}
, // Data
"list" : null, // System.Collections.Generic.List`1[System.Int32]
}
[ // System.Collections.Generic.List`1[System.Int32]
1, // System.Int32
2, // System.Int32
3, // System.Int32
4, // System.Int32
5, // System.Int32
],
{ // System.Collections.Generic.List`1[System.Int32]
}
{ // Data
"numInt" : 111, // System.Int32
"numFloat" : 123.456, // System.Single
"text" : "abc", // System.String
"left" : { // Data
"numInt" : 0, // System.Int32
"numFloat" : 0, // System.Single
"text" : null, // System.String
"left" : null, // Data
"right" : null, // Data
"list" : null, // System.Collections.Generic.List`1[System.Int32]
}
, // Data
"right" : { // Data
"numInt" : 0, // System.Int32
"numFloat" : 0, // System.Single
"text" : null, // System.String
"left" : null, // Data
"right" : null, // Data
"list" : null, // System.Collections.Generic.List`1[System.Int32]
}
, // Data
"list" : [ // System.Collections.Generic.List`1[System.Int32]
1, // System.Int32
2, // System.Int32
3, // System.Int32
4, // System.Int32
5, // System.Int32
],
{ // System.Collections.Generic.List`1[System.Int32]
}
, // System.Collections.Generic.List`1[System.Int32]
}
[ // UnityEngine.Transform
],
{ // UnityEngine.Transform
}
{ // UnityEngine.GameObject
}
{ // UnityEngine.Camera
"onPreCull" : null, // UnityEngine.Camera+CameraCallback
"onPreRender" : null, // UnityEngine.Camera+CameraCallback
"onPostRender" : null, // UnityEngine.Camera+CameraCallback
}
[ // System.Collections.Generic.Dictionary`2[System.Int32,System.Int32]
[1, 111], // System.Collections.Generic.KeyValuePair`2[System.Int32,System.Int32]
[2, 222], // System.Collections.Generic.KeyValuePair`2[System.Int32,System.Int32]
[3, 333], // System.Collections.Generic.KeyValuePair`2[System.Int32,System.Int32]
],
{ // System.Collections.Generic.Dictionary`2[System.Int32,System.Int32]
}
[ // Data[]
{ // Data
"numInt" : 111, // System.Int32
"numFloat" : 123.456, // System.Single
"text" : "abc", // System.String
"left" : { // Data
"numInt" : 0, // System.Int32
"numFloat" : 0, // System.Single
"text" : null, // System.String
"left" : null, // Data
"right" : null, // Data
"list" : null, // System.Collections.Generic.List`1[System.Int32]
}
, // Data
"right" : { // Data
"numInt" : 0, // System.Int32
"numFloat" : 0, // System.Single
"text" : null, // System.String
"left" : null, // Data
"right" : null, // Data
"list" : null, // System.Collections.Generic.List`1[System.Int32]
}
, // Data
"list" : [ // System.Collections.Generic.List`1[System.Int32]
1, // System.Int32
2, // System.Int32
3, // System.Int32
4, // System.Int32
5, // System.Int32
],
{ // System.Collections.Generic.List`1[System.Int32]
}
, // System.Collections.Generic.List`1[System.Int32]
}
, // Data
{ // Data
"numInt" : 0, // System.Int32
"numFloat" : 0, // System.Single
"text" : null, // System.String
"left" : null, // Data
"right" : null, // Data
"list" : null, // System.Collections.Generic.List`1[System.Int32]
}
, // Data
{ // Data
"numInt" : 0, // System.Int32
"numFloat" : 0, // System.Single
"text" : null, // System.String
"left" : null, // Data
"right" : null, // Data
"list" : null, // System.Collections.Generic.List`1[System.Int32]
}
, // Data
],
{ // Data[]
}
[ // Data[]
{ // Data
"numInt" : 111, // System.Int32
"numFloat" : 123.456, // System.Single
"text" : "abc", // System.String
"left" : { // Data
"numInt" : 0, // System.Int32
"numFloat" : 0, // System.Single
"text" : null, // System.String
"left" : null, // Data
"right" : null, // Data
"list" : null, // System.Collections.Generic.List`1[System.Int32]
}
, // Data
"right" : { // Data
"numInt" : 0, // System.Int32
"numFloat" : 0, // System.Single
"text" : null, // System.String
"left" : null, // Data
"right" : null, // Data
"list" : null, // System.Collections.Generic.List`1[System.Int32]
}
, // Data
"list" : [ // System.Collections.Generic.List`1[System.Int32]
1, // System.Int32
2, // System.Int32
3, // System.Int32
4, // System.Int32
5, // System.Int32
],
{ // System.Collections.Generic.List`1[System.Int32]
}
, // System.Collections.Generic.List`1[System.Int32]
}
, // Data
{ // Data
"numInt" : 0, // System.Int32
"numFloat" : 0, // System.Single
"text" : null, // System.String
"left" : null, // Data
"right" : null, // Data
"list" : null, // System.Collections.Generic.List`1[System.Int32]
}
, // Data
null, //
{ // Data
"numInt" : 0, // System.Int32
"numFloat" : 0, // System.Single
"text" : null, // System.String
"left" : null, // Data
"right" : null, // Data
"list" : null, // System.Collections.Generic.List`1[System.Int32]
}
, // Data
{ // SubData
"numInt" : 0, // System.Int32
"numFloat" : 0, // System.Single
"text" : null, // System.String
"left" : null, // Data
"right" : null, // Data
"list" : null, // System.Collections.Generic.List`1[System.Int32]
}
, // SubData
],
{ // Data[]
}
UnityEngine.Debug:Log (object)
GetObjectInfoTest:Start () (at Assets/018反射获取属性/GetObjectInfoTest.cs:59)
目前感觉还有改进的空间,如缩进有时不对啥的,以后再说吧。
在项目里用了用感觉还是挺方便的。