Access fields of a Struct in an Object with Reflection

18.7k views Asked by At

I'm trying to use reflection (ultimately on unknown at compile time) object which include struct. I've got as far as TypedReference.MakeTypedReference but I've hit a wall.

Here's my Class and Struct

public class MyObject
{
    public int Id;
    public Money Amount; 
}

public struct Money
{
    public int Vaule;
    public string Code;
}

And here is how I am trying to set "Code" of "Amount" in MyObject using reflection. As I mention above, I'm looking for a solution which does not know about these types at compile time (that would be too easy!)

Here's the code I have so far (I've used [0], [1] to make the code simpler)

var obj = new MyObject() { Id = 1 };
obj.Amount.Vaule = 10;
obj.Amount.Code = "ABC";

FieldInfo[] objFields = obj.GetType().GetFields();
FieldInfo[] moneyFields = objFields[1].GetValue(obj).GetType().GetFields();

List<FieldInfo> fields = new List<FieldInfo>() { objFields[1] };
fields.AddRange( moneyFields );

TypedReference typeRef = TypedReference.MakeTypedReference( 
                           objFields[1].GetValue( obj ), fields.ToArray() );

moneyFields[1].SetValueDirect( typeRef, "XXX" );

The TypedReference.MakeTypedReference blows up with; "FieldInfo does not match the target Type." Likewise if I just pass objFields[1]. And if pass just moneyFields I get "TypedReferences cannot be redefined as primitives."

Why? Let's say I'm creating Random test fixtures and want to populate class fields with random data :)

1

There are 1 answers

5
Marc Gravell On BEST ANSWER

Frankly, there's no need whatsoever for TypedReference here - just a boxed struct should work fine:

    var amountField = obj.GetType().GetField("Amount");
    object money = amountField.GetValue(obj);
    var codeField = money.GetType().GetField("Code");
    codeField.SetValue(money, "XXX");
    amountField.SetValue(obj, money);

However! I will advise you of a few things:

  • public fields instead of properties are not usually a good idea; that will often bite you later
  • mutable structs (i.e. structs that can be changed after creation) are almost never a good idea, and will bite even more often, and bite harder
  • combining mutable structs and public fields compounds it, but making it very problematic to change later