Добавить динамический тип в список <object>, используя отражение - PullRequest
0 голосов
/ 06 февраля 2019

Я создаю пользовательское окно 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]

Я пытаюсьиспользуйте Reflection, потому что тип списка может быть int, float, Vector3 и т. д., поэтому мне нужно, чтобы он был динамическимic, и я не могу использовать динамический тип, потому что мы не используем 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]

1 Ответ

0 голосов
/ 06 февраля 2019

Я не уверен, что это самый чистый способ, но мне в основном пришлось выполнять приведение, перебирая все элементы в списке / массиве и подбирая их по отдельности.Кажется, я не могу разыграть весь список сразу.

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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...