3

それ自体に多数のオブジェクト (以下を参照) を含む Case オブジェクトがあり、これにもオブジェクトが含まれています。

これらのオブジェクトは、現在のオブジェクトで DataAnnotation バリデーターを実行する ValidateObject メソッドを実装する BaseDto クラスから継承できるため、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

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 に答える
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 に答える
-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 に答える