繁体   English   中英

将动态类型添加到列表 <object> 使用反射

[英]Add dynamic type to List<object> using reflection

我正在创建一个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是字段名,value是字段值;例如: key=speedvalue=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]

我正在尝试使用Reflection,因为列表类型可以是intfloatVector3等,所以我需要通过动态方式来实现,并且由于我们未使用4.x ,因此无法使用动态类型。

错误发生在这里:

field.SetValue(GameData.save, GetValue(item));

当字段是List<int>时, 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]

我不确定这是否是最干净的方法,但是我基本上必须通过循环遍历列表/数组中的所有项目并分别进行转换来进行转换。 我似乎无法一次投放整个清单。

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();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM