#c# #json #reflection #setvalue #fieldinfo
Вопрос:
у меня тут вопрос,надеюсь, разработчик warmheat поможет.
это проблема, с которой я сталкиваюсь:
я хочу сохранить поля экземпляра класса из-за отражения кода ниже:
private void SaveFields() { fieldItemList.Clear(); FieldInfo[] fields = GetType().GetFields(BindingFlags.Public | BindingFlags.Instance); for (int i = 0; i lt; fields.Length; i ) { FieldInfo finfo = fields[i]; FieldItem item = new FieldItem() { ValName = finfo.Name, ValType = finfo.FieldType, ValValue = finfo.GetValue(this), }; fieldItemList.Add(item); } string json = JsonModule.GetInstance().Serialize(fieldItemList); json = JsonModule.GetInstance().FormatJsonString(json); Debug.LogFormat("json = {0}", json); File.WriteAllText(@"E:GithubRepoShaderSamplesShaderSamplesfields.json", json); }
это работает,и сохраненный json выглядит так:
[ { "ValName": "fVar", "ValType": "System.Single, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "ValValue": 2.0 }, { "ValName": "iVar", "ValType": "System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "ValValue": 1 }, { "ValName": "Gears", "ValType": "GearParam[], Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "ValValue": [ { "Vec3": { "x": 1.0, "y": 2.0, "z": 3.0 }, "Vec2": { "x": 1.0, "y": 2.0 }, "FVar": 1.0, "IVar": 2 } ] }
]
затем,когда я использую его для заполнения полей нового экземпляра класса, используйте такой код:
private void ApplyFields() { string json = File.ReadAllText(@"E:GithubRepoShaderSamplesShaderSamplesfields.json"); fieldItemList = JsonModule.GetInstance().Deserializelt;Listlt;FieldItemgt;gt;(json); Debug.LogFormat("fieldItemList = {0}", fieldItemList.Count); FieldInfo[] fields = GetType().GetFields(BindingFlags.Public | BindingFlags.Instance); for (int i = 0; i lt; fields.Length; i ) { FieldInfo finfo = fields[i]; for (int k = 0; k lt; fieldItemList.Count; k ) { FieldItem item = fieldItemList[k]; if (finfo.Name == item.ValName) { finfo.SetValue(this, item.ValValue); } } } }
это вызывает ошибку:
Исключение ArgumentException: Объект типа ‘Система.Система Double «не может быть преобразована в тип».Одинок». Система.Тип времени выполнения.Контрольное значение (Система.Значение объекта, Система.Отражение.Связующее связующее, Система.Глобализация.Культура, культура, система.Отражение.BindingFlags invokeAttr) (в :0) Система.Отражение.МоноФильм.Значение SET (Система.Объект obj, Система.Объект val, Система.Отражение.BindingFlags вызывает, система.Отражение.Связующее связующее, Система.Глобализация.Культура (культура) (в :0) Система.Отражение.FieldInfo.setValue (Система.Объект obj, Система.Значение объекта) (в :0) TestReflectEnum.ApplyFields () (в активах/Скриптах/TestReflectEnum.cs:82)
я думаю, что для заполнения reflect fieldinfo.setvalue нужен именно тип объекта,поэтому я изменяю код следующим образом:
object obj = Convert.ChangeType(item.ValValue, item.ValType); finfo.SetValue(this, obj);
но все равно вызывает ошибку:
Исключение InvalidCastException: Объект должен реализовать функцию IConvertible. Система.Преобразовать.Тип изменения (Система.Значение объекта, Система.Тип преобразования Тип, Система.Поставщик IFormatProvider) (в :0) Система.Преобразовать.Тип изменения (Система.Значение объекта, Система.Тип преобразования типа) (в :0) TestReflectEnum.ApplyFields () (в активах/Скриптах/TestReflectEnum.cs:82)
теперь единственный способ для меня-выписать все виды условий типа объекта и изменять тип объекта один за другим,это такой хлопотный способ,я надеюсь,что есть общая функция для чтения объекта из txt/json и может правильно установить значение — —
Комментарии:
1. Вы пробовали
finfo.SetValue(this, Convert.ChangeType(value, propertyInfo.PropertyType), null);
2. во-первых,спасибо,но я не нашел функции переопределения трех параметров(setvalue), я использую .netframework 4.0 и 4.8, какую .netframework или .netcore вы используете?