Search code examples
c#arraysreflectionaccessibilityprivate

To access private arrays, classes are double-wrapped


Array variable included and class in class. I know how to use general reflection, but the class is duplicated and the intermediate variable is in the form of an array. Can you help me solve this problem?

using System.Reflection;
using space1;
using space2;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace space1
{
    public class BigClass
    {
        BigClass.SmallClass[] CustomArrays;

        public BigClass()
        {
            this.CustomArrays = new BigClass.SmallClass[2];
            CustomArrays[0] = new SmallClass(17);
            CustomArrays[1] = new SmallClass(18);
        }

        private class SmallClass
        {
            private int MyGoal;
            public SmallClass(int a)
            {
                MyGoal = a;
            }
        }
    }
}

namespace space2
{
    class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Start");
            BigClass a = new BigClass();

            FieldInfo fieldinfo1 = typeof(BigClass).GetField("CustomArrays", BindingFlags.Instance | BindingFlags.NonPublic);


            Console.WriteLine();
            //Console.WriteLine(fieldinfo2.ToString());
        }
    }
}

I would like to finally get the MyGoal value of space1 and return the number 18 by making the value +1. Do I have to access Field first and then access Field again? I tried GetType(), GetTypeof(), etc. after I approached the first Field, but I couldn't access the next Field. Also, since it's declared Array, how do I tell if it's [0] or [1]? If print out the field with the code written above, it will only be displayed as CustomArray. How can I use this separately by Array?


Solution

  • I'm guessing the advice I gave you last time didn't help, seeing that you've reposted. It's still a really bad idea to do this - if you need access to some data, make it public. If it's not public, there's generally a good reason why it's not.

    With this structure

    public class Parent
    {
        private Child[] childRefs;
    
        public Parent()
        {
            childRefs = [new Child(5), new Child(6), new Child(7)];
        }
    
        private class Child
        {
            private int innerValue;
    
            public Child(int value)
            {
                innerValue = value;
            }
        }
    }
    

    You can get the values of innerValue by using reflection twice. No need to use the type Child directly in your code.

    var parent = new Parent();
    
    FieldInfo childRefField = typeof(Parent).GetField("childRefs", BindingFlags.Instance | BindingFlags.NonPublic)!;
    IEnumerable childRefFieldValues = (childRefField.GetValue(parent) as IEnumerable)!;
    
    foreach (var childRefFieldValue in childRefFieldValues)
    {
        FieldInfo childInternalField = childRefFieldValue.GetType().GetField("innerValue", BindingFlags.Instance | BindingFlags.NonPublic)!;
        int? childInternalValue = childInternalField.GetValue(childRefFieldValue) as int?;
        Console.WriteLine(childInternalValue);
    }
    

    Arrays implement IEnumerable<T> as well as IEnumerable, the non-generic version, which this solution uses. childRefFieldValue is treated as an object, so you can continue using reflection from there.

    This prints 5, 6, 7.