2012-12-12 51 views
3

我有一個Case對象,它自身包含許多對象(請參見下文),該對象又包含對象。C#遍歷對象層次結構以執行方法

這些對象可以從BaseDto類繼承,該類實現ValidateObject方法,該方法在當前對象上執行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(); 
+2

爲什麼不ValidateObject的每個類的實現也爲所有對象包含的孩子的運行ValidateObject? – juharr

回答

-2

這將是清潔讓每個類層次結構中的覆蓋ValidateObject()驗證其子對象:

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

等,然後客戶端只需調用根對象上ValidateObject()

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的字段,以遞歸方式驗證它們和它們內部的所有字段。

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); 
    } 
}