lundi 1 mai 2023

Using C# Reflection to parse a hierarchy of data classes

I have written a data parser for my script engine that uses reflection to get the value of actual program data classes. I have a hierarchy of classes where some of my sub-classes hide other sub-classes.

C#'s runtime binder logic knows how to handle this and won't recognize members of the hidden class, but my logic can't tell the difference between a hidden member and a valid member.

The code below is a super-truncated version that illustrates my issue. As you can see from the output, both the timestamp member of the original PSR class, and the timeStamp (different case) member of the updated PSR class are found.

I'm looking for an attribute or method that can help me decide if the member I'm looking at is hidden or accessible.


using System;
using System.Reflection;`

namespace test
{
    static class PRD
    {
        public static dynamic prdData { get; private set; } = new PRD_P20();
    }

    public abstract class PRD_DATA
    {
        public BLE ble = new BLE();
        public class BLE : PRD_BLE_BASE { }
    }

    public abstract class PRD_BLE_BASE
    {
        public PSR psr = new PSR();
    }
    public class PSR
    {
        public string timestamp = "original";
    }

    public class PRD_P20 : PRD_DATA
    {
        /* Instantiate new version BLE and hide the parent class  */
        public new BLE ble = new BLE();

        public new class BLE
        {
            public PSR psr = new PSR();
        }

        public class PSR
        {
            public string timeStamp = "updated";
        }

    }
    class Program
    {
        static void Main(string[] args)
        {
            var o = PRD.prdData;
            foreach (FieldInfo f in o.GetType().GetFields())
            {
                Console.WriteLine(f.Name + " " + f.DeclaringType);

                object o1 = f.GetValue(o);
                foreach (FieldInfo f1 in o1.GetType().GetFields())
                {
                    Console.WriteLine("----" + f1.Name);

                    object o2 = f1.GetValue(o1);
                    foreach (FieldInfo f2 in o2.GetType().GetFields())
                    {
                        Console.WriteLine("--------" + f2.Name + ": " + f2.GetValue(o2));
                    }
                }
            }

            Console.WriteLine(PRD.prdData.ble.psr.timestamp);   // Fails RuntimeBinderException
            Console.WriteLine(PRD.prdData.ble.psr.timeStamp);

            Console.ReadKey();
        }
    }}

Output:

ble test.PRD_P20
----psr
--------timeStamp: updated
ble test.PRD_DATA
----psr
--------timestamp: original




Aucun commentaire:

Enregistrer un commentaire