0

I am trying to access a property of a nested class through reflection while looping but cannot find a way to do so. I am much more familiar with JavaScript than C# so I will explain my problem in JS terms and show what I have tried with C#.

What I want to accomplish with working JavaScript:

var myObj = {
  prop1: {p1: 0, p2: 1, p3: 2},
  prop2: {p1: 0, p2: 2, p3: 4},
  prop3: {p1: 0, p2: 4, p3: 8}
};

console.log(myObj.prop2.p2); //2

for( prop in myObj ) {
  //Since I know the inner properties are the same
  myObj[prop].p1++;
  myObj[prop].p2++;
  myObj[prop].p3++;
}

console.log(myObj.prop2.p2); //3

Here is what I have tried in C#, but with no luck:

class myObj
{
    public class myPropObj
    {
        public int p1 {get; set;}
        public int p2 {get; set;}
        public int p3 {get; set;}
        public myPropObj(int one, int two, int three)
        {
            p1 = one;
            p2 = two;
            p3 = three;
        }
    }
    public myPropObj prop1 = new myPropObj(0, 1, 2);
    public myPropObj prop2 = new myPropObj(0, 2, 4);
    public myPropObj prop3 = new myPropObj(0, 4, 8);
}
--------------------------------------------------------------
//Not working
myObj myObject = new myObj();

Console.WriteLine(myObject.prop2.p2);  //2

foreach( var prop in typeof(myObject).GetProperties() )
{
    //I am thinking I need to cast it to the same type as nested class, but unsure how to do this
    ((myObject.myPropObj)prop).p1++;
    ((myObject.myPropObj)prop).p2++;
    ((myObject.myPropObj)prop).p3++;
}

Console.WriteLine(myObj.prop2.p2);  //3

Thank you very much for taking the time to help me.

4
  • Why through reflection when you can just myObject.prop1.p1++;, etc? Is it because you want to loop? Commented Jul 13, 2018 at 22:33
  • This line is wrong: Console.WriteLine(myObj.prop2.p2); Change it to Console.WriteLine(myObject.prop2.p2); and it'll work. No Reflection needed. Commented Jul 13, 2018 at 22:37
  • 2
    It should be noted that your prop1, prop2, and prop3 "properties" are actually fields. Commented Jul 13, 2018 at 22:46
  • 5
    This kind of technique is common in JavaScript but really, really not idiomatic in C#. What you're doing is called an "XY problem". You have some problem, you have some wrong idea of how to solve the problem, and now you're asking a question about that wrong idea. What problem are you actually trying to solve? Say what that problem is, and someone can help you understand what the C# way to solve that problem is. Commented Jul 13, 2018 at 22:57

1 Answer 1

3

Note: As both Eric and I have pointed out, taking such an approach is not the idiomatic way of solving such problems. Without context, it's difficult to suggest alternative solutions, but... beware. Reflection is generally best avoided unless you have a real need for it.

So a number of issues.

1) C# guidelines mandate CapitalCamelCase for class names. I'll be doing that in this answer.

2) public MyPropObj prop1 = new MyPropObj(0, 1, 2);

this is not a property. This is a field, so it's not picked up by GetProperties(). C# guidelines recommend against public fields, so the best approach is to swap to public properties instead:

public MyPropObj prop1 { get; set; } = new MyPropObj(0, 1, 2);

and so on...

3) Calling GetProperties on a Type returns an array of PropertyInfo. These in turn expose a method GetValue, which can be invoked to get the value of the property:

var obj = prop.GetValue(myObject); //this is always of type Object
var propObj = (MyObj.MyPropObj)obj; //so we need to cast it

Now we can take that propObj and

propObj.p1++;
propObj.p2++;
propObj.p3++;

as normal. You don't need reflection for this part.

Putting this all together:

void Main()
{
    MyObj myObject = new MyObj();
    Console.WriteLine(myObject.prop2.p2);  //2
    foreach (var prop in typeof(MyObj).GetProperties())
    {
        var propObj = (MyObj.MyPropObj)prop.GetValue(myObject);
        propObj.p1++;
        propObj.p2++;
        propObj.p3++;
    }
    Console.WriteLine(myObject.prop2.p2);  //3
}

class MyObj
{
    public class MyPropObj
    {
        public int p1 { get; set; }
        public int p2 { get; set; }
        public int p3 { get; set; }

        public MyPropObj(int one, int two, int three)
        {
            p1 = one;
            p2 = two;
            p3 = three;
        }
    }

    public MyPropObj prop1 { get; set; } = new MyPropObj(0, 1, 2);
    public MyPropObj prop2 { get; set; } = new MyPropObj(0, 2, 4);
    public MyPropObj prop3 { get; set; } = new MyPropObj(0, 4, 8);
}

However, this is not idiomatic C#, and the number of times you might choose to attack a problem with (slow) reflection are few and far between. There are almost always better ways to crack the nut.

Sign up to request clarification or add additional context in comments.

3 Comments

prop.GetMethod.Invoke() looks weird to me. Why not prop.GetValue()?
@CamiloTerevinto The point being that now you have a concrete, typed instance, you don't have to do any further accesses via reflection.
Thank you for taking the time to explain this so clearly. As you could probably tell, I am still very new to C#. This was very helpful and as you suggested, I will be investigating better ways to implement this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.