3

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

Mark
  • 245
  • 4
  • 10
  • Possible duplicate of [Is there a way to set properties on struct instances using reflection?](https://stackoverflow.com/questions/6280506/is-there-a-way-to-set-properties-on-struct-instances-using-reflection) – StayOnTarget May 02 '18 at 19:24

4 Answers4

3

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.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • 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 Mar 21 '09 at 10:20
  • ... 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 – Mark Mar 21 '09 at 10:22
  • 1
    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 Mar 21 '09 at 16:53
  • 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... – Reed Copsey Mar 21 '09 at 16:54
  • 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? – Mark Mar 21 '09 at 20:09
  • 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 Mar 22 '09 at 19:56
  • 1
    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 – Reed Copsey Mar 22 '09 at 19:57
  • 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? – Mark Mar 30 '09 at 18:26
2

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;
Erwin Mayer
  • 18,076
  • 9
  • 88
  • 126
1

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.

MarkusQ
  • 21,814
  • 3
  • 56
  • 68
0

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

Mark
  • 245
  • 4
  • 10