C#遍历对象层次结构以执行方法

C#遍历对象层次结构以执行方法,c#,C#,我有一个Case对象,它本身包含许多对象(见下文),同样也包含对象 这些对象可以从实现ValidateObject方法的BaseDto类继承,该类在当前对象上执行DataAnnotation验证器,从而返回验证错误,并累积到ValidationResult集合中 我想将以下混乱的语法转换为可以遍历给定对象的对象层次结构的语法,对于实现ValidateObject的每个对象(及其子对象!),执行它 我现在感觉有点卡住了,所以如果有任何想法,我将不胜感激 cCase.ValidateObject()

我有一个Case对象,它本身包含许多对象(见下文),同样也包含对象

这些对象可以从实现ValidateObject方法的BaseDto类继承,该类在当前对象上执行DataAnnotation验证器,从而返回验证错误,并累积到ValidationResult集合中

我想将以下混乱的语法转换为可以遍历给定对象的对象层次结构的语法,对于实现ValidateObject的每个对象(及其子对象!),执行它

我现在感觉有点卡住了,所以如果有任何想法,我将不胜感激

cCase.ValidateObject() &
cCase.Object1.ValidateObject() &
cCase.Object2.ValidateObject() &
cCase.Object3.ValidateObject() &
cCase.Object3.ChildObject1.ValidateObject() &
cCase.Object3.ChildObject2.ValidateObject() &
cCase.Object3.ChildObject3.ValidateObject() &
cCase.Object3.ChildObject4.ValidateObject() &
cCase.Object3.ChildObject4.ChildChildObject1.ValidateObject() &
cCase.Object3.ChildObject5.ValidateObject() &
cCase.Object4.ValidateObject() &
cCase.Object4.ChildObject6.ValidateObject();

让层次结构中的每个类重写
ValidateObject()
以验证其子对象会更简洁:

public override bool ValidateObject()
{
    return base.ValidateObject() & 
        this.Object1.ValidateObject() &
        this.Object2.ValidateObject() &
        this.Object3.ValidateObject() &
        this.Object4.ValidateObject();
}

等等。然后客户端就可以对根对象调用
ValidateObject()

您需要使用反射获取所有字段,这些字段继承自
BaseDto
类:

public abstract class BaseDto
{
    public abstract bool ValidateObject();
}

// Sample class without nested fields, requiring validation.
public class Case2 : BaseDto
{
    public override bool ValidateObject()
    {
        Console.WriteLine("Validated: " + ToString());
        return false;
    }
}

// Sample nested class with nested fields, requiring validation.
public class Case1 : BaseDto
{
    private Case2 Object1 = new Case2();
    private Case2 Object2 = new Case2();
    private Stream stream = new MemoryStream();

    public override bool ValidateObject()
    {
        Console.WriteLine("Validated: " + ToString());
        return true;
    }
}

public class Case : BaseDto
{
    private Case1 Object1 = new Case1();
    private Case2 Object2 = new Case2();
    // don't touch this field
    private Stream stream = new MemoryStream();
    private Case1 Object3 = new Case1();

    public override bool ValidateObject()
    {
        Console.WriteLine("Validated: " + ToString());
        return true;
    }

    public bool ValidateAll()
    {
        if (!ValidateObject()) return false;
        return ValidateAll(this);
    }

    private bool ValidateAll(object o)
    {
        foreach (FieldInfo fieldInfo in o.GetType().GetFields(BindingFlags.Instance |
               BindingFlags.NonPublic |
               BindingFlags.Public))
        {
            BaseDto current = fieldInfo.GetValue(o) as BaseDto;

            if(current != null)
            {
                bool result = current.ValidateObject();
                if(!result)
                {
                    return false;
                }
                return ValidateAll(current);
            }
        }

        return true;
    }
}

对根对象调用
ValidateAll()
。它在内部遍历所有字段,这些字段是从
BaseDto
派生的,递归地验证它们和它们内部的所有字段。

我会使用如下扩展方法:

public interface IValidatable
{
    bool ValidateObject();
}

public static class ValidateExtensions
{
    public static bool ValidateAll(this IValidatable item)
    {
        if (!item.ValidateObject())
            return false;

        const BindingFlags flags = BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public;
        var type = item.GetType();
        var props = type.GetProperties(flags).Select(x => x.GetValue(item));
        var fields = type.GetFields(flags).Select(x => x.GetValue(item));
        return props
            .Concat(fields)
            .OfType<IValidatable>()
            .Select(x => x.ValidateAll())
            .All(x => x);
    }
}
公共接口表
{
bool ValidateObject();
}
公共静态类ValidateExtensions
{
公共静态bool ValidateAll(此IValidatable项)
{
如果(!item.ValidateObject())
返回false;
const BindingFlags flags=BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public;
var type=item.GetType();
var props=type.GetProperties(标志)。选择(x=>x.GetValue(项));
var fields=type.GetFields(标志)。选择(x=>x.GetValue(项));
返回道具
.Concat(字段)
第()类
.Select(x=>x.ValidateAll())
.全部(x=>x);
}
}

为什么不让每个类的ValidateObject实现也为它包含的所有子对象运行ValidateObject?