FieldInfo 更新字段的子字段
FieldInfo update subfield of field
美好的一天,
我需要创建一个函数来迭代存储变量名和变量新值的字典。之后,我需要用该值更新 class 变量。
void UpdateValues(Type type, Dictionary<string, string> values)
{
foreach (var value in values)
{
var fieldInfo = selected.GetComponent(type).GetType().GetField(value.Key);
if (fieldInfo == null) continue;
fieldInfo.SetValue(selected.GetComponent(type), value.Value);
}
}
它有效,但我想要的改进很少,我绝对不知道它是否可能。
如您所见,该函数可以接受任何 class,而不仅仅是一个特定的。
如果我有class这样的
class test
{
public string age;
}
我会这样使用函数,它会起作用。
UpdateValues(typeof(test), new Dictionary<string, string>{{"age", "17"}});
问题是如果我有这样的 class 并且我想更新 "subfield"(字段中的字段)
class test
{
public string age;
}
class test2
{
public test data;
}
我在想语法可以是这样的,但我不知道我该怎么做。
UpdateValues(typeof(test2), new Dictionary<string, string>{{"data.age", "17"}});
总而言之,我需要制作一个函数,它将使用存储在另一个 class 中的 class。函数将遍历字典并更新 class 甚至她的子字段的字段。
我建议向您的方法添加递归调用,以设置属性。我稍微改变了你的方法,因为我没有 selected
对象,它需要一个对象作为参数
void UpdateValues<T>(T obj, Dictionary<string, string> values)
{
foreach (var value in values)
{
SetProperty(obj, value.Key, value.Value);
}
}
public void SetProperty<T>( T obj, string valueKey, string value, Type type= null)
{
var typeToUse = type ?? typeof(T);
var pointIndex = valueKey.IndexOf(".");
if (pointIndex!=-1)
{
var subKey = valueKey.Substring(0, pointIndex);
var fieldInfo = typeToUse.GetField(subKey);
var propObj = fieldInfo.GetValue(obj)
?? Activator.CreateInstance(fieldInfo.FieldType);
SetProperty(propObj, valueKey.Substring(pointIndex+1), value, fieldInfo.FieldType);
fieldInfo.SetValue(obj, propObj);
}
else
{
var fieldInfo = typeToUse.GetField(valueKey);
if (fieldInfo != null)
fieldInfo.SetValue(obj, value);
}
}
即使您定义
也能正常工作
class test3
{
public test2 data;
}
并致电
UpdateValues(t, new Dictionary<string, string>{{"age", "17"}});
UpdateValues(t2, new Dictionary<string, string> { { "data.age", "17" } });
UpdateValues(t3, new Dictionary<string, string> { { "data.data.age", "17" } });
SetProperty
方法的第三个参数不是很好,我会避免它,但我不知道如何用泛型解决它,用 Activator
创建后你得到 object
作为类型,对象没有字段 age
您正在使用 Dictionary<string, string>
作为仅允许设置字符串字段的参数,因此您必须假设您没有任何其他字段。实际上,即使您将使用 Dictionary<string, object>
,我也建议这样做。
首先,您需要更改 Dictionary
变量以使用
Dictionary<string, object>
如果你想在这里传递一个 class 作为参数。
其次这是一个如何让它工作的例子。
class test
{
public string age;
}
class test2
{
public test data;
}
假设我已经创建了 test
class 的实例并将其添加到字典中,以获取具有反射的字段,然后相应地更新 test2
的实例。
public void UpdateValues(object test2, Dictionary<string, object> dict)
{
var fieldValues = test2.GetType()
.GetFields()
.ToList();
foreach (var value in dict)
{
foreach (var field in fieldValues)
{
if (value.Key == field.Name)
{
bool obj = field.FieldType == typeof(test);
if (obj)
{
if (dict.ContainsKey("data"))
{
var prop = test2.GetType().GetField("data", System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.Instance);
prop.SetValue(test2, dict["data"]);
break;
}
}
else
{
var prop = test2.GetType().GetField(value.Key, System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.Instance);
prop.SetValue(test2, value.Value);
break;
}
}
}
}
}
最后调用你的函数我创建了一个 Dictionary<string,object>
实例来将它作为参数发送给函数
object test2 = new test2();
test t = new test();
t.age = "10";
Dictionary<string, object> dict = new Dictionary<string, object>();
dict.Add("data", t);
UpdateValues(test2, dict);
美好的一天,
我需要创建一个函数来迭代存储变量名和变量新值的字典。之后,我需要用该值更新 class 变量。
void UpdateValues(Type type, Dictionary<string, string> values)
{
foreach (var value in values)
{
var fieldInfo = selected.GetComponent(type).GetType().GetField(value.Key);
if (fieldInfo == null) continue;
fieldInfo.SetValue(selected.GetComponent(type), value.Value);
}
}
它有效,但我想要的改进很少,我绝对不知道它是否可能。 如您所见,该函数可以接受任何 class,而不仅仅是一个特定的。
如果我有class这样的
class test
{
public string age;
}
我会这样使用函数,它会起作用。
UpdateValues(typeof(test), new Dictionary<string, string>{{"age", "17"}});
问题是如果我有这样的 class 并且我想更新 "subfield"(字段中的字段)
class test
{
public string age;
}
class test2
{
public test data;
}
我在想语法可以是这样的,但我不知道我该怎么做。
UpdateValues(typeof(test2), new Dictionary<string, string>{{"data.age", "17"}});
总而言之,我需要制作一个函数,它将使用存储在另一个 class 中的 class。函数将遍历字典并更新 class 甚至她的子字段的字段。
我建议向您的方法添加递归调用,以设置属性。我稍微改变了你的方法,因为我没有 selected
对象,它需要一个对象作为参数
void UpdateValues<T>(T obj, Dictionary<string, string> values)
{
foreach (var value in values)
{
SetProperty(obj, value.Key, value.Value);
}
}
public void SetProperty<T>( T obj, string valueKey, string value, Type type= null)
{
var typeToUse = type ?? typeof(T);
var pointIndex = valueKey.IndexOf(".");
if (pointIndex!=-1)
{
var subKey = valueKey.Substring(0, pointIndex);
var fieldInfo = typeToUse.GetField(subKey);
var propObj = fieldInfo.GetValue(obj)
?? Activator.CreateInstance(fieldInfo.FieldType);
SetProperty(propObj, valueKey.Substring(pointIndex+1), value, fieldInfo.FieldType);
fieldInfo.SetValue(obj, propObj);
}
else
{
var fieldInfo = typeToUse.GetField(valueKey);
if (fieldInfo != null)
fieldInfo.SetValue(obj, value);
}
}
即使您定义
也能正常工作class test3
{
public test2 data;
}
并致电
UpdateValues(t, new Dictionary<string, string>{{"age", "17"}});
UpdateValues(t2, new Dictionary<string, string> { { "data.age", "17" } });
UpdateValues(t3, new Dictionary<string, string> { { "data.data.age", "17" } });
SetProperty
方法的第三个参数不是很好,我会避免它,但我不知道如何用泛型解决它,用 Activator
创建后你得到 object
作为类型,对象没有字段 age
您正在使用 Dictionary<string, string>
作为仅允许设置字符串字段的参数,因此您必须假设您没有任何其他字段。实际上,即使您将使用 Dictionary<string, object>
,我也建议这样做。
首先,您需要更改 Dictionary
变量以使用
Dictionary<string, object>
如果你想在这里传递一个 class 作为参数。
其次这是一个如何让它工作的例子。
class test
{
public string age;
}
class test2
{
public test data;
}
假设我已经创建了 test
class 的实例并将其添加到字典中,以获取具有反射的字段,然后相应地更新 test2
的实例。
public void UpdateValues(object test2, Dictionary<string, object> dict)
{
var fieldValues = test2.GetType()
.GetFields()
.ToList();
foreach (var value in dict)
{
foreach (var field in fieldValues)
{
if (value.Key == field.Name)
{
bool obj = field.FieldType == typeof(test);
if (obj)
{
if (dict.ContainsKey("data"))
{
var prop = test2.GetType().GetField("data", System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.Instance);
prop.SetValue(test2, dict["data"]);
break;
}
}
else
{
var prop = test2.GetType().GetField(value.Key, System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.Instance);
prop.SetValue(test2, value.Value);
break;
}
}
}
}
}
最后调用你的函数我创建了一个 Dictionary<string,object>
实例来将它作为参数发送给函数
object test2 = new test2();
test t = new test();
t.age = "10";
Dictionary<string, object> dict = new Dictionary<string, object>();
dict.Add("data", t);
UpdateValues(test2, dict);