简体   繁体   English

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

[英]How to search through nested properties of T to set base class property

I have an XML serialiser that breaks when the XML returned isn't valid XML. 我有一个XML序列化程序,当返回的XML无效XML时中断。 So to combat this I wanted to display the error in the object returned rather than just null or break. 因此,为了解决这个问题,我想在返回的对象中显示错误,而不仅仅是null或break。

One of my classes is derived from a class that contains a string error property called message , it is this property I wish to set so that the error message can be seen. 我的一个类派生自一个类,该类包含一个称为message的字符串错误属性,我希望设置该属性以便可以看到错误消息。

Class structure could be two or three classes down. 班级结构可以减少两到三个班级。 Using generic reflection, I wish to access the string property, message , of ClassC when I parse in either Class1 or ClassA. 使用通用反射,当我在Class1或ClassA中进行解析时,我希望访问ClassC的字符串属性message

Is it possible to access the Message property of ClassC? 是否可以访问ClassC的Message属性? Currently when I send in an object that doesn't directly derive from ClassC it throws an exception because it cannot find the property (which doesn't exist in ClassA||1), however as not every class will be ClassA -> ClassB : ClassC , some could be Class1 -> Class2 -> Class3 : ClassC 当前,当我发送一个不是直接从ClassC派生的对象时,它会引发异常,因为找不到属性(在ClassA || 1中不存在),但是由于并非每个类都是ClassA -> ClassB : ClassC ,有些可能是Class1 -> Class2 -> Class3 : ClassC

Problem code: - I can only see the properties of the object parsed into the function, I need to be able to iterate through all of the properties, initialise if they are not already until I find the string property called message so I can set it and return an object containing useful error information. 问题代码: -我只能看到解析为函数的对象的属性,我需要能够遍历所有属性,如果还没有初始化,请进行初始化,直到找到名为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;

Desired - for the message property within ClassC to be accessible to be set against. 所需 -可以设置ClassC中的message属性。 At present I need to initialise the other properties (that are classes), so ClassB or Class2 and Class3, before I can get to the message property. 目前,在获取message属性之前,需要初始化其他属性(即类),即ClassB或Class2和Class3。 However I don't know which object will be passed into the function. 但是我不知道哪个对象将被传递到函数中。

Two tier class structure: 两层类结构:

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

Class ClassB : ClassC 
{
    // other properties 
}

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

I think you don't really want to find a randomly-typed object with a message property - you specifically want to find an object derived from ClassC . 我认为您并不是真的想找到一个具有message属性的随机类型的对象-您特别想找到一个从ClassC派生的对象。 So you'd be better with something like this, which looks down the hierarchy of properties until it finds something derived from ClassC : 因此,使用类似这样的方法会更好,该方法会向下查看属性的层次结构,直到找到从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);
        }
    }
}

(Take a look at this fiddle to see it in action). (看看这个小提琴 ,看看它的作用)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM