在c#中一般使用反射读取分层类的属性

本文关键字:分层 读取 属性 反射 | 更新日期: 2023-09-27 18:17:43

我有一组通过xsd.exe基于*生成的类。xsd文件。每一组类为每一组*生成。XSD文件几乎是相同的,除了每个类中有一些不同的属性。例如,在集合1和集合2中,Shape类可能有不同的属性。

我想使用一个方法一次读取一个集合中所有类的指定属性(UPDATE)的值(UPDATE)。可以有很多等级。方法(例如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() {
            ...
           }

我想知道一种替代方法来实现与下面方法类似的功能

 //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{}
       ...
    }

在c#中一般使用反射读取分层类的属性

这就是我们实现这个功能的方式(这是为了获取动态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
        }
    }