PropertyInfo.SetValue () не работает, но ошибок нет - PullRequest
5 голосов
/ 14 марта 2012

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

Итак, это то, что у меня есть:

internal static T ParseObjectGraph<T>(Dictionary<string, object> oGraph)
{
    T generic = (T)Activator.CreateInstance<T>();
    Type resType = typeof(T);
    foreach (PropertyInfo pi in resType.GetProperties())
    {
        object outObj = new object();
        if (oGraph.TryGetValue(pi.Name.ToLower(), out outObj))
        {
            Type outType = outObj.GetType();
            if (outType == pi.PropertyType)
            {                        
                pi.SetValue(generic, outObj, null);
            }
        }
    }
    return generic;
}

Теперь метод pi.SetValue() запускается и не выдает ошибку, но когда я смотрю на свойства generic, он все равно остается прежним.

Первое свойство, к которому он идетthrough является логическим значением, поэтому значения заканчиваются следующим образом:

generic = an object of type MyCustomType
generic.property = false
outObj = true
pi = boolean property
outType = boolean

Затем, после запуска метода SetValue, generic.property по-прежнему имеет значение false.

Ответы [ 3 ]

6 голосов
/ 14 марта 2012

PropertyInfo.SetValue / GetValue работал со структурой с точным использованием

struct Z
{
  public int X { get; set; }
}

  Z z1 = new Z();
  z1.GetType().GetProperty("X").SetValue(z1, 100, null);
  Console.WriteLine(z1.X); //z1.X dont changed

  object z2 = new Z();
  z2.GetType().GetProperty("X").SetValue(z2, 100, null);
  Console.WriteLine(((Z)z2).X); //z2.x changed to 100

  Z z3 = new Z();
  object _z3 = z3;
  _z3.GetType().GetProperty("X").SetValue(_z3, 100, null);
  z3 = (Z)_z3;
  Console.WriteLine(z3.X); //z3.x changed to 100

Правильный способ изменить структуру:

  • структура коробки
  • изменить свойство штучной структуры
  • назначить коробочную структуру источнику
6 голосов
/ 14 марта 2012

Итак, я взял ваш метод и провел его модульное тестирование:

class PropertySetTest
{
    static readonly Type resType = typeof(Car);
    internal static T ParseObjectGraph<T>(Dictionary<string, object> oGraph)
    {
        T generic = (T)Activator.CreateInstance<T>();
        foreach (PropertyInfo pi in resType.GetProperties())
        {
            //No need to new() this
            object outObj; // = new object();
            if (oGraph.TryGetValue(pi.Name.ToLower(), out outObj))
            {
                Type outType = outObj.GetType();
                if (outType == pi.PropertyType)
                {
                    pi.SetValue(generic, outObj, null);
                }
            }
        }
        return generic;
    }

    [Test]
    public void Test()
    {
        var typeData = new Dictionary<String, Object> {{"color", "Blue"}};
        var myCar = ParseObjectGraph<Car>(typeData);
        Assert.AreEqual("Blue", myCar.Color);
    }
}

internal class Car
{
    public String Color { get; set; }
}

Это проходит. Можете ли вы сделать так, чтобы это не проходило так, как вы видите?

РЕДАКТИРОВАТЬ: С вашей структурой, это только немного сложнее. Смотрите ответ Джона Скита здесь о том, что происходит. Что касается рабочего кода:

class PropertySetTest
{
    static readonly Type resType = typeof(Car);
    internal static T ParseObjectGraph<T>(Dictionary<string, object> oGraph)
    {
        Object generic = Activator.CreateInstance<T>();
        foreach (var pi in resType.GetProperties())
        {
            //No need to new() this
            object outObj; // = new object();
            if (oGraph.TryGetValue(pi.Name.ToLower(), out outObj))
            {
                var outType = outObj.GetType();
                if (outType == pi.PropertyType)
                    pi.SetValue(generic, outObj, null);
            }
        }
        return (T)generic;
    }

    [Test]
    public void Test()
    {
        var typeData = new Dictionary<String, Object> {{"color", "Blue"}};
        var myCar = ParseObjectGraph<Car>(typeData);
        Assert.AreEqual("Blue", myCar.Color);
    }
}

internal struct Car
{
    public String Color { get; set; }
}
5 голосов
/ 14 марта 2012

Нашел ответ.Очевидно, PropertyInfo.SetValue () и PropertyInfo.GetValue () не работают для структур, а только для классов.

MyCustomType, к сожалению, был структурой, поэтому изменение этого класса на класс заставило его работать.

Третий ответ в этом потоке указывает, почему структуры не работают, а классы работают.

РЕДАКТИРОВАТЬ: Он работает со структурами, см. Отмеченный ответ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...