3

我有一个 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();
4

3 回答 3

0

我会使用这样的扩展方法:

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);
    }
}
于 2012-12-12T15:29:58.653 回答
0

您需要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以递归方式验证它们以及其中的所有字段。

于 2012-12-12T15:07:43.363 回答
-2

让层次结构中的每个类都覆盖ValidateObject()以验证其子对象会更干净:

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

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

于 2012-12-12T14:49:07.410 回答