FieldInfo更新字段的子字段

时间:2016-12-23 09:15:34

标签: c# .net reflection system.reflection

美好的一天,

我需要创建将在Dictionary上迭代的函数,该函数存储变量名和变量的新值。之后,我需要使用该值更新类变量。

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 test
{
    public string age;
}

我会以这种方式使用函数,它会起作用。

UpdateValues(typeof(test), new Dictionary<string, string>{{"age", "17"}});

问题是,如果我有这样的课程,我想更新&#34; subfield&#34; (现场实地)

class test
{
    public string age;
}

class test2
{
    public test data;
}

我认为语法可能是这样的,但我不知道我怎么能这样做。

UpdateValues(typeof(test2), new Dictionary<string, string>{{"data.age", "17"}});

总结一下,我需要创建一个函数来获取存储在另一个类中的类。函数将通过字典迭代并更新类甚至是子字段的字段。

2 个答案:

答案 0 :(得分:1)

我建议为你的方法添加一个递归调用来设置属性。我已经改变了你的方法,因为我没有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创建后你得到{{ 1}}作为类型,对象没有字段object

您使用age作为参数,只允许您设置字符串字段,因此您必须假设您没有任何其他字符串字段。实际上,即使您使用Dictionary<string, string>,我也建议这样做。

答案 1 :(得分:0)

首先,您需要更改要使用的Dictionary变量 Dictionary<string, object>如果你想在这里传递一个类作为参数。 其次这是一个如何使其发挥作用的例子。

class test
{
    public string age;
}

class test2
{
    public test data;
}

假设我已经创建了test类的实例并将其添加到字典中,以获取带反射的字段,然后相应地更新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);