我正在创建一个Unity自定义窗口,此窗口显示来自对象的数据,该对象最终将转换为JSON
。
只要不是我遇到问题的数组,我就能读取并修改数据。
数据如下:
public static class GameData {
private static SaveData data;
public static SaveData save { get { return data.save; } }
[System.Serializable]
public class SaveData {
public int energyCurrent = 100;
public float speed = 2.5f;
public List<int> itm = new List<int>() { 1, 2, 3, 4, 5, 6 };
}
}
然后我有一个对象,可以像这样存储每个项目(它们的键是字段名,值是字段值;例如:key=speed
,value=2.5f
):
class KeyValue {
public string key;
public object value;
public KeyValue(string key, object value) {
this.key = key;
this.value = value;
}
}
然后将其存储在列表中:
List<KeyValue> keyValues = new List<KeyValue>();
我遇到问题的部分是保存,如下所示:
void SaveDataLocal() {
keyValues.ForEach(item => {
// GameData.save is a reference to SaveData
var field = GameData.save.GetType().GetField(item.key);
field.SetValue(GameData.save, GetValue(item));
});
GameData.Save();
}
object GetValue(KeyValue keyVal) {
var value = keyVal.value;
if (value.GetType().IsArray || isList(value)) {
List<object> list = new List<object>();
((List<KeyValue>)value).ForEach(item => {
list.add(GetValue(item));
});
return list;
} else {
return value;
}
}
我尝试了两种更新值的方法,但是,我收到一条错误消息:
ArgumentException:对象类型System.Collections.Generic.List`1 [System.Object]无法转换为目标类型:System.Collections.Generic.List`1 [System.Int32]
我正在尝试使用反射,因为列表类型可以是int
,float
,Vector3
等,所以我需要通过动态方式来使用它,而不能使用动态类型,因为我们没有使用4.x
。
此处发生错误:
field.SetValue(GameData.save, GetValue(item));
GetValue()
在字段为List<object>
时返回List<int>
。如何通过List<object>
?
我尝试过像这样投射它:
public static T Cast<T>(object o) {
return (T)o;
}
keyValues.ForEach(item => {
var field = GameData.save.GetType().GetField(item.key);
var val = GetValue(item);
var castMethod = this.GetType().GetMethod("Cast").MakeGenericMethod(field.FieldType);
var r = castMethod.Invoke(null, new object[] { val });
field.SetValue(GameData.save, r);
});
但是我收到此错误:
InvalidCastException:无法从源类型转换为目标类型。 GameSmart.SaveData.Cast [List`1]
答案 0 :(得分:1)
我不确定这是否是最干净的方法,但是我基本上必须通过循环遍历列表/数组中的所有项目并分别进行转换来进行转换。我似乎无法一次投射整个列表。
public static List<T> CastList<T>(List<object> o) {
var list = new List<T>();
foreach (var i in o) { list.Add((T)i); }
return list;
}
void SaveDataLocal() {
keyValues.ForEach(item => {
var field = GameData.save.GetType().GetField(item.key);
var value = GetValue(item);
if (value.GetType().IsArray || isList(value)) {
Type type;
if (isList(value)) type = field.FieldType.GetGenericArguments().Single();
else type = field.FieldType.GetElementType();
var castMethod = this.GetType().GetMethod("CastList").MakeGenericMethod(type);
value = castMethod.Invoke(null, new object[] { value });
}
field.SetValue(GameData.save, value);
});
GameData.Save();
}