【问题标题】:Set variables from an object using reflection doesn't work使用反射从对象设置变量不起作用
【发布时间】:2017-09-24 21:11:31
【问题描述】:

我想使用反射从对象中设置变量。

对于简单的对象,这是可行的。 (属性)

但是具有类变量(字段)的对象不起作用。在这里,我总是得到一个“对象与目标类型不一致”的异常。

这里有人知道它会怎么走吗?

class Program
{
    static void Main(string[] args)
    {
        var genericDataSet = new GenericDataSet<DataObjekt>();
        var returnObjekt = genericDataSet.KeepElementsData();
    }
}

public class DataObjekt
{
    public string Name { get; set; }
    public ObjektData ModelTyp;
    public DataObjekt() { ModelTyp = new ObjektData(); }
}

public class ObjektData
{
    public string Typ { get; set; }
    public string Data { get; set; }
}

public class GenericDataSet<T> where T : class, new()
{
    public T KeepElementsData()
    {
        var item = new T();
        //Propertys durchlaufen
        foreach (var Property in item.GetType().GetProperties())
        {
            item.GetType().GetProperty(Property.Name).SetValue(item, "TestData");  //this works
        }

        //Fields durchlaufen
        foreach (var Field in item.GetType().GetFields())
        {
            foreach (var FieldProperty in item.GetType().GetField(Field.Name).FieldType.GetProperties())
            {
                var data = item.GetType().GetField(Field.Name).FieldType.GetProperty(FieldProperty.Name);
                data.SetValue(item, "TestData not work", null); // this doesent work
            }
        }
        return item;
    }
}

【问题讨论】:

  • 你为什么打电话给item.GetType().GetField(Field.Name)而不是只用Field? (我还敦促您开始遵循 .NET 命名约定 - 您的局部变量通常是 fieldfieldProperty。)

标签: c# reflection properties field


【解决方案1】:

它不起作用的原因是因为您在错误的对象上设置了值:

data.SetValue(item, "TestData not work", null);

item 没有这个属性,它是拥有它的字段。
您需要创建该字段的实例(如果它为 null),然后填充其属性,然后将其设置为该字段。

以下内容对您有用:

public class GenericDataSet<T> where T : class, new()
{
    public T KeepElementsData()
    {
        var item = new T();
        //Propertys durchlaufen
        foreach (var propertyInfo in item.GetType().GetProperties())
        {
            item.GetType().GetProperty(propertyInfo.Name).SetValue(item, "TestData");  //this works
        }

        //Fields durchlaufen
        foreach (var fieldInfo in item.GetType().GetFields())
        {
            object fieldObject = Activator.CreateInstance(fieldInfo.FieldType);

            // Or if it's already instantiated: 
            // object fieldObject = fieldInfo.GetValue(item);

            foreach (var fieldProperty in fieldInfo.FieldType.GetProperties())
            {
                fieldProperty.SetValue(fieldObject, "TestData not work", null); // this doesent work
            }
            fieldInfo.SetValue(item, fieldObject);
        }
        return item;
    }
}

【讨论】:

  • 谢谢,这正是我想做的:)
【解决方案2】:

据我所知,这甚至不适用于属性,因为您只提供字符串数据,而并非所有属性都具有字符串类型。无论如何,在你的字段循环中,为什​​么你有一个嵌套循环?您正在循环每个字段 type 的属性,我猜这很有趣。因此,如果您的字段具有类型字符串,您将在内部循环中迭代来自String 的所有字段。您应该能够省略内部循环并编写与属性相同的内容。此外,您可以直接设置当前item的属性值。

var item = new T();
//Propertys durchlaufen
foreach (var property in item.GetType().GetProperties())
{
    property.SetValue(item, "TestData");  //this works
}

//Fields durchlaufen
foreach (var field in item.GetType().GetFields())
{
    field.SetValue(item, "TestData");
}

【讨论】:

  • @BRAHIMKamel 为什么?我已经提到过这些字段并不全是字符串,所以当然它不会对所有人都有效,但至少对于第一个是 OP 实际要求的。
  • @HimBromBeere 是的,不仅有带字符串的属性,但为此我有一个解决方案。
【解决方案3】:

试试这个:

public T KeepElementsData()
{
    var item = new T();
    //Propertys durchlaufen
    foreach (var property in item.GetType().GetProperties())
    {
        property.SetValue(item, "TestData");  //this works
    }

    //Fields durchlaufen
    foreach (var field in item.GetType().GetFields())
    {
        var value = field.GetValue(item);
        var type = value.GetType();

        foreach (var fieldProperty in type.GetProperties())
        {
            fieldProperty.SetValue(value, "TestData works");
        }
    }
    return item;
}

您在 PropertyInfo->PropertyInfo 的名称->PropertyInfo 之间来回切换...另外,您正在将 item 对象与其字段混合...

【讨论】:

    猜你喜欢
    • 2010-10-11
    • 1970-01-01
    • 2011-01-13
    • 1970-01-01
    • 1970-01-01
    • 2015-10-13
    • 2014-11-13
    • 1970-01-01
    相关资源
    最近更新 更多