Thursday, April 14, 2011

Use reflection to set the value of a field in a struct which is part of an array of structs

At the moment my code successfully sets the value of fields/properties/arrays of an object using reflection given a path to the field/property from the root object.

e.g.

//MyObject.MySubProperty.MyProperty
SetValue('MySubProperty/MyProperty', 'new value', MyObject);

The above example would set 'MyProperty' property of the 'MyObject' object to 'new value'

I'm unable to use reflection to set a value of a field in a struct which is part of an array of structs because the struct is a value type (within an array).

Here are some test classes/structs...

public class MyClass {
        public MyStruct[] myStructArray = new MyStruct[] {
            new MyStruct() { myField = "change my value" } 
        };
        public MyStruct[] myOtherStructArray = new MyStruct[] {
            new MyStruct() { myOtherField = "change my value" }, 
            new MyStruct() { myOtherField = "change my other value" } 
        };
}

public struct MyStruct { public string myField; public string myOtherField; }

Below is how I successfully set the value of normal properties/fields and props/fields in lists...

public void SetValue(string pathToData, object newValue, object rootObject)
{
    object foundObject = rootObject;
    foreach (string element in pathToData.Split("/"))
    {
     foundObject = //If element is [Blah] then get the
                      //object at the specified list position
     //OR
        foundObject = //Else get the field/property
    }

    //Once found, set the value (this is the bit that doesn't work for
    //                           fields/properties in structs in arrays)
    FieldInf.SetValue(foundObject, newValue);
}

object myObject = new MyClass();
SetValue("/myStructArray/[0]/myField", "my new value", myObject);
SetValue("/myOtherStructArray/[1]/myOtherField", "my new value", myObject);

After that I want the myObject.myStructArray[0].myField = ''my new value" and myObject.myOtherStructArray[1].myOtherField = ''my new value"

All I need is a replacement for the 'FieldInf.SetValue(foundObject, newValue);' line

thanks in advance

From stackoverflow
  • If I had to guess, the bug is in part of the code you omitted, specifically I'd suspect that:

        foundObject = //If element is [Blah] then get the
                      //object at the specified list position
    

    is (unintentionally) setting foundObject to a copy of the object at the specified list position.

    Mark : Hi thans for answering, please see my feedback below...
  • My question continued...

    The only solution i found to a similar problem I had setting a field/property in a struct that is a field was to use...

    //GrandParentObject is myObject
    //GrandParentType is typeof(MyClass)
    //FieldIWantedToSet is the field info of myStruct.FieldIWantedToSet
    FieldInfo oFieldValueTypeInfo = GrandParentType.GetField("myStruct");
    TypedReference typedRefToValueType = TypedReference.MakeTypedReference(GrandParentObject, new FieldInfo[] { oFieldValueTypeInfo });
    FieldIWantedToSet.SetValueDirect(typedRefToValueType, "my new value");
    

    Problem is how can I use SetValueDirect on a array/list of structs, i'm guessing my old method above will not work when the structs are in an array because I cannot get the FieldInfo for the struct (because its in an array)?

  • Get the FieldInfo for the array object (not the specific element).

    If it's an array, cast it to a System.Array and use Array.SetValue to set the object's value.

    Mark : Thanks for your answer, i don't think that will work because the structure is as follows... MyObject.myStructArray[0].myField So using your method Array.SetValue
    Mark : ... would to pass in a brand new struct, i'm trying to set the value of a field in a struct thats in an array
    Reed Copsey : Yes. Whenever you have an array of structs, that's the best approach. You can copy it to a new, local struct, and only overwrite that member, then pass that back in.
    Reed Copsey : As a rule of thumb, though, typically structs should be immutable, so typically, you should avoid structs where one member can be changed. The design guidelines explain why in details...
    Mark : OK thanks. Looks like i'm catering for situations that are never going to occur in classes. PS Where are these design guidelines you speak of?
    Reed Copsey : Part of the design guidelines for .net frameworks is available on MSDN. There is a book written by 2 MS people that explains all the guidelines in detail, though. Is one I highly recommend.
    Reed Copsey : See http://www.amazon.com/Framework-Design-Guidelines-Conventions-Development/dp/0321545613/ref=sr_1_1?ie=UTF8&s=books&qid=1237751853&sr=8-1
    Mark : Cheers, i've got the book via work. Its very thorough and its good to dip into for a quick info fix while working. Any other good .NET books you could recommend?

0 comments:

Post a Comment