Mark
Mark

Reputation: 245

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

Upvotes: 3

Views: 8328

Answers (4)

Erwin Mayer
Erwin Mayer

Reputation: 18670

Due to boxing/unboxing, the following should do exactly what you are looking for, for any kind of struct member:

var property = this.GetType().GetProperty(myPropertyName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
ValueType vthis = this;
property.SetValue(vthis, myValue, null); // myValue is the value/object to be assigned to the property.
this = (UnderlyingsList)vthis;

Upvotes: 2

Reed Copsey
Reed Copsey

Reputation: 564851

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.

Upvotes: 3

Mark
Mark

Reputation: 245

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)?

Upvotes: 0

MarkusQ
MarkusQ

Reputation: 21950

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.

Upvotes: 1

Related Questions