Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PropertyInfo.SetValue() not working but no errors

I'm writing my own method to convert an object graph to a custom object since the JavaScriptSerializer fires errors on null values.

So this is what I have so far:

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;
}

Now the pi.SetValue() method runs, and doesn't fire an error but when I look at the properties of generic, it's still the same as it was before hand.

The first property it goes through is a boolean so the values end up like this

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

Then after the SetValue method runs, generic.property is still set to false.

like image 639
James Hay Avatar asked Mar 14 '12 00:03

James Hay


People also ask

How to use SetValue in c#?

To use the SetValue method, first get a Type object that represents the class. From the Type, get the PropertyInfo object. From the PropertyInfo object, call the SetValue method.

What is SetValue?

SetValue() Function Sets the value of a given control. Syntax: SetValue(id,value) Parameters: id - Control Identifier to assign value to.

How does reflection set property value?

To set property values via Reflection, you must use the Type. GetProperty() method, then invoke the PropertyInfo. SetValue() method. The default overload that we used accepts the object in which to set the property value, the value itself, and an object array, which in our example is null.


2 Answers

PropertyInfo.SetValue/GetValue worked with struct with accurate using

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

Correct way to change struct:

  • box struct
  • change property of boxed struct
  • assign boxed struct to source
like image 72
Serj-Tm Avatar answered Oct 25 '22 12:10

Serj-Tm


Found the answer. Apparently, PropertyInfo.SetValue() and PropertyInfo.GetValue() do not work for structures, only classes.

MyCustomType was unfortunately a struct, so changing this to a class made it work.

The 3rd reply in this thread states why structures do not work and classes do.

EDIT: It does work with structs, see the marked answer.

like image 32
James Hay Avatar answered Oct 25 '22 13:10

James Hay