Чтение свойств иерархических классов в общем, используя отражение в C # - PullRequest
0 голосов
/ 13 декабря 2011

У меня есть набор классов, которые создаются с помощью xsd.exe на основе файлов * .xsd. Каждый набор классов, сгенерированный для каждого набора файлов * .xsd, практически одинаков, за исключением того, что в каждом классе есть несколько разных свойств. Например, как в наборе 1, так и в наборе 2 у класса Shape может быть другое свойство.

Я хочу использовать метод для чтения значения указанных свойств ( ОБНОВЛЕНИЕ ) всех классов в одном наборе за раз ( Обновление ). Там может быть много уровней класса. Метод (например, GetProperty метод) должен знать только о своем типе параметра и строковом представлении всех свойств. Метод только для чтения свойства.

Есть ли лучший способ сделать это:

    internal class DynPropertyTest
    {
        public static void Set1Test()
        {
            Shape shape = new Shape()
            {
                Name = "Shape",
                Shape2 = new Shape2()
                {
                   Name = "Shape2",
                   Shape3 = new Shape3() { Name = "Shape3" }
                }
            };

            GetProperty(shape);
        }

        public static void Set2Test() {
            ...
           }

UPDATE Я хотел бы знать альтернативный способ достижения функции, аналогичной приведенной ниже методике

 //Should store all properties value in a collection, rather than display it
           //And somehow store/know the type of the property.
        public static void GetProperty(ShapeBase shape)
        {
            //shape.Name             


                Console.WriteLine(shape.GetType().GetProperty("Name").GetValue(shape, null));

            //Shape.Shape2
            object shape2 = shape.GetType().GetProperty("Shape2").GetValue(shape, null);
            Console.WriteLine(shape2);

            //Shape.Shape2.Name
            object shape2Name = shape.GetType().GetProperty("Shape2").PropertyType.GetProperty("Name")
                .GetValue(shape2, null);
            Console.WriteLine(shape2Name);

            //shape.shape2.shape3
            object shape3 = shape2.GetType().GetProperty("Shape3").GetValue(shape2, null);
            Console.WriteLine(shape3);

            //shape.shape2.shape3.Name
            object shape3Name = shape2.GetType().GetProperty("Shape3").PropertyType.GetProperty("Name")
                .GetValue(shape3, null);
            Console.WriteLine(shape3Name);
        }
    }

    abstract class ShapeBase { }

   //Example only. 
    namespace Set1
    {
        class Shape : ShapeBase
        {
            public string Name { get; set; }
            public Shape2 Shape2 { get; set; }
        }

        class Shape2
        {
            public string Name { get; set; }
            public Shape3 Shape3 { get; set; }
        }

        class Shape3
        {
            public string Name { get; set; }

        }
    }

    namespace Set2
    {
        class Shape : ShapeBase{}
       ...
    }

1 Ответ

2 голосов
/ 13 декабря 2011

Вот как мы реализуем эту функцию (это для получения строкового значения для динамического SQL, но вы должны иметь возможность применить его к вашей ситуации:

    public static string GetFieldValueForSQL(object oRecord, string sName)
    {
        PropertyInfo theProperty = null;
        FieldInfo theField = null;
        System.Type oType = null;

        try
        {
            oType = oRecord.GetType();

            // See if the column is a property in the record
            theProperty = oType.GetProperty(sName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public, null, null, new Type[0], null);
            if (theProperty == null)
            {
                theField = oType.GetField(sName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public);
                if (theField != null)
                {
                    return theField.GetValue(oRecord).ToString();
                }
            }
            else
            {
                return theProperty.GetValue(oRecord, null).ToString();
            }
        }
        catch (Exception theException)
        {
            // Do something with the exception
            return string.empty;
        }
    }

Обновление

Для обработки всех свойств вы можете использовать код, подобный следующему (обратите внимание, что это не учитывает реализации IEnumerable, но это должно быть довольно просто):

    public static void GetAllProperties(object oRecord)
    {
        System.Type oType = null;
        try
        {
            oType = oRecord.GetType();

            PropertyInfo[] cProperties;

            cProperties = oType.GetProperties(BindingFlags.Instance | BindingFlags.Public);

            foreach (PropertyInfo theProperty in cProperties)
            {
                if (theProperty.PropertyType.IsClass)
                {
                    GetAllProperties(theProperty.GetValue(oRecord, null));
                }
                else
                {
                    // use theProperty.GetValue(oRecord, null).ToString();
                }
            }
        }
        catch (Exception theException)
        {
            // Do something with the exception
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...