views:

59

answers:

3

I am trying to set a value through reflection. I created this little test program

    struct headerIndexes
    {
        public int AccountNum{ get; set; }
        public int other { get; set; }
        public int items { get; set; }
    }
    static void Main(string[] args)
    {

        headerIndexes headers = new headerIndexes();
        headers.AccountNum = 1;
        Console.WriteLine("Old val: {0}", headers.AccountNum);
        foreach (var s in headers.GetType().GetProperties())
        {
            if (s.Name == "AccountNum")
                s.SetValue(headers, 99, null);
        }
        Console.WriteLine("New val: {0}", headers.AccountNum);
        Console.ReadKey();
    }

Steping thorugh the program i see it correctly does the command s.SetValue(headers, 99, null); however the value of headers.AccountNum stays at 1 when setValue is run.

Am I missing a obvious step?

+3  A: 

I think headers might be getting boxed into a new object since it's a struct, then the object is getting garbage collected as soon as SetValue returns. Change it to a class and see if the problem goes away.

Rodrick Chapman
That was it, changing it from a struct to a class solved the issue.
Scott Chamberlain
A: 

SetValue is expecting an object which causes a boxing operation on headers. As headers is a struct, it is a value type. Therefore a copy is made and what you are modifying is the boxed object and not headers.

You should seriously consider avoiding mutable value types.

From Eric Lippert:

This is yet another reason why mutable value types are evil. Try to always make value types immutable.

Jason
A: 

Also you can use unboxed version of struct.
object unboxedHeader=headers;
s.SetValue(unboxedHeader, 99, null);

struct headerIndexes 
{ 
    public int AccountNum{ get; set; } 
    public int other { get; set; } 
    public int items { get; set; } 
} 
static void Main(string[] args) 
{ 

    headerIndexes headers = new headerIndexes(); 
    headers.AccountNum = 1; 
    Console.WriteLine("Old val: {0}", headers.AccountNum); 
    object unboxedHeader=headers;
    foreach (var s in headers.GetType().GetProperties()) 
    { 
        if (s.Name == "AccountNum") 
            s.SetValue(unboxedHeader, 99, null); 
    } 
    Console.WriteLine("New val: {0}", headers.AccountNum); 
    Console.ReadKey(); 
} 
Avram