我是反思的新手,递归迭代对象的最佳方法是什么,将通用列表和普通数组作为包含其他对象的字段?
更多信息
实际上,我创建了以下属性来标记将要导出以进行翻译的字段:
using System;
[AttributeUsage(AttributeTargets.Field)]
public class ExportForTranslationAttribute : System.Attribute
{
public ExportForTranslationAttribute() { }
}
然后我从某个物体开始,然后从那里走得更远。 (我现在复制了整个方法。)
private Int64 timesMaxDeepnessReached = 0;
private void searchForExportableStringsInObject(object obj, int deepness)
{
if (deepness > maxDeepness)
{
timesMaxDeepnessReached++;
return;
}
if (obj != null)
{
//only follow serializable objects!
var objAttributes = obj.GetType().GetCustomAttributes(true);
foreach (var oa in objAttributes)
{
if (oa.GetType() == typeof(SerializableAttribute))
{
var fields = obj.GetType().GetFields();
if (fields == null || !fields.Any())
{ return; }
foreach (var fieldInfo in fields)
{
//1. handle string fields that are directly on the component
#region directly on object
var attributes = fieldInfo.GetCustomAttributes(true);
bool hadExportAttribute = false;
foreach (var a in attributes)
{
if (a.GetType() == typeof(ExportForTranslationAttribute))
{
Debug.Log("found something!");
hadExportAttribute = true;
if (fieldInfo.FieldType == typeof(string))
{
try
{
Debug.Log("info.GetValue= " + fieldInfo.GetValue(obj));
addKeyWhenNotExisting((string)fieldInfo.GetValue(obj));
}
catch (Exception ex) { Debug.Log("error while getting value to export: " + ex); }
}
else if (fieldInfo.FieldType == typeof(string[]))
{
Debug.Log("found string[]!");
try
{
Debug.Log("info.GetValue= " + fieldInfo.GetValue(obj));
foreach (var item in (string[])fieldInfo.GetValue(obj))
{
addKeyWhenNotExisting(item);
}
}
catch (Exception ex) { Debug.Log("error while getting value to export: " + ex); }
}
else if (fieldInfo.FieldType == typeof(List<string>))
{
Debug.Log("found List<string>!");
try
{
Debug.Log("info.GetValue= " + fieldInfo.GetValue(obj));
foreach (var item in (List<string>)fieldInfo.GetValue(obj))
{
addKeyWhenNotExisting(item);
}
}
catch (Exception ex) { Debug.Log("error while getting value to export: " + ex); }
}
else
{
Debug.LogWarning("Can only add ExportForTranslation-Attribute to string values and collection of string values. Not on the type: " + fieldInfo.FieldType);
}
}
}
#endregion //directly on object
}
}
else if (oa.GetType() == typeof(List<>))
{
try
{
foreach (var item in (IList)oa)
{
searchForExportableStringsInObject(item, ++deepness);
}
}
catch (Exception ex) { }//{ Debug.Log("error while getting value to export: " + ex); }
}
else if (oa.GetType() == typeof(Array))
{
try
{
foreach (var item in (Array)oa)
{
searchForExportableStringsInObject(item, ++deepness);
}
}
catch (Exception ex) { }//{ Debug.Log("error while getting value to export: " + ex); }
}
}
}
else
{
return;
}
}
答案 0 :(得分:1)
oa.GetType()
为您提供实例的类型,而不是您需要oa.PropertyType
的属性类型。
修改
我可能已经四处走动,把它放在一起,我打赌有更好的,或者至少更简洁的方式,但也许这就像你在寻找的东西:
class Program
{
static void Main(string[] args)
{
var testType = new TestType {GenList = new List<string> {"test", "type"}};
foreach(var prop in typeof (TestType).GetProperties())
{
if (prop.PropertyType.IsGenericType)
{
var genericTypeArgs = prop.PropertyType.GetGenericArguments();
if (genericTypeArgs.Length!=1 || !(genericTypeArgs[0] == typeof(string)))
continue;
var genEnum = typeof (IEnumerable<>).MakeGenericType(genericTypeArgs);
if (genEnum.IsAssignableFrom(prop.PropertyType))
{
var propVal = (IList<string>)prop.GetValue(testType, BindingFlags.GetProperty, null, null, null);
foreach (var item in propVal)
Console.WriteLine(item);
}
}
}
Console.ReadLine();
}
}
public class TestType
{
public IList<string> GenList { get; set; }
}
答案 1 :(得分:1)
属性永远不是List<>
。所以oa.GetType() == typeof(List<>)
永远都是假的。
也许您希望获取包含GetFields()
的字段或包含GetProperties()
的属性,而不是获取自定义属性。
您可能还想检查类型是否实现IEnumerable<T>
,而不是检查它是否与List<T>
相同。