如何搜索T的嵌套属性以设置基类属性

时间:2016-01-11 12:44:19

标签: c# generics reflection

我有一个XML序列化程序,当返回的XML不是有效的XML时会中断。所以为了解决这个问题,我想在返回的对象中显示错误,而不仅仅是null或break。

我的一个类派生自一个包含名为message的字符串错误属性的类,我希望设置此属性,以便可以看到错误消息。

类结构可以是两个或三个类。使用泛型反射,当我在Class1或ClassA中解析时,我希望访问ClassC的字符串属性message

是否可以访问ClassC的Message属性?目前,当我发送一个不直接派生自ClassC的对象时,它会抛出一个异常,因为它找不到属性(ClassA || 1中不存在),但并不是每个类都是ClassA -> ClassB : ClassC ,有些可能是Class1 -> Class2 -> Class3 : ClassC

问题代码: - 我只能看到解析到函数中的对象的属性,我需要能够遍历所有属性,如果它们还没有被初始化,直到找到名为message的字符串属性,因此我可以设置它并返回包含有用错误信息的对象。

var obj = (T)Activator.CreateInstance(typeof(T));
Type type = obj.GetType();
PropertyInfo prop = type.GetProperty("message");
prop.SetValue(obj, Convert.ChangeType(dirtyXml,prop.PropertyType), null);
return (T)obj;

所需 - 可以对ClassC中的邮件属性进行设置。目前我需要初始化其他属性(即类),所以ClassB或Class2和Class3,在我可以获取message属性之前。但是我不知道将哪个对象传递给函数。

两级课程结构:

Class ClassA 
{
    public ClassB classB { get; set; }
}

Class ClassB : ClassC 
{
    // other properties 
}

Class ClassC 
{
    public String message { get; set; }
{

1 个答案:

答案 0 :(得分:1)

我认为你真的不想找到一个具有message属性的随机类型对象 - 你特别希望找到一个派生自ClassC的对象。所以你用这样的东西做得更好,它会查看属性的层次结构,直到它找到从ClassC派生的东西:

using System;

public class Program
{
    class ClassA
    {
        public ClassB classB { get; set; }
    }

    class ClassB : ClassC
    {
    }

    class ClassC
    {
        public string message { get; set; }
    }

    static T FindClass<T>(object obj) where T : class
    {
        var classType = obj.GetType();
        var targetType = typeof(T);

        if (IsDerivedFrom(classType, targetType))
        {
            return (T)obj;
        }

        foreach (var prop in classType.GetProperties())
        {
            if ( prop.PropertyType.IsClass)
            {
                var childObj = prop.GetValue(obj);

                var target = FindClass<T>(childObj);
                if (target != null)
                {
                    return target;
                }
            }
        }

        return null;
    }

    static bool IsDerivedFrom(Type class1, Type class2)
    {
        return class2.IsAssignableFrom(class1);
    }

    public static void Main()
    {
        var classA = new ClassA { classB = new ClassB() };
        classA.classB.message = "Hello";

        var classC = FindClass<ClassC>(classA);

        if (classC != null)
        {
            Console.WriteLine(classC.message);
        }
    }
}

(请查看http://ruby-doc.org/stdlib-2.1.0/libdoc/debug/rdoc/DEBUGGER__.html以了解相关信息)。