2011-05-07 45 views
1

我一直在努力嘗試一些反射代碼,但我很簡單。從本質上講,我有一個定義方法的接口。然後,我有一個抽象類,提供該方法的基礎實現。在不創建新實例的情況下反映嵌套實例

具體類可以包含其他類的嵌套實例,這些類也可以從相同的基類派生。它可以通過下面的示例來說明:

using System.Linq; 

public interface ISampleObject 
{ 
    bool IsValid(); 
} 

public abstract class SampleObjectBase : ISampleObject 
{ 
    public bool IsValid() 
    { 
     var returnValue = true; 

     // Self-validation sets the return value. 

     var childProperties = this.GetType().GetProperties().Where(pi => typeof(ISampleObject).IsAssignableFrom(pi.PropertyType)); 

     foreach (var childProperty in childProperties) 
     { 
      // var childInstance = ????; // Need the actual *existing* instance property, cast to ISampleObject. 
      // if (childInstance.IsValid() != true) 
      // { 
      //  returnValue = false; 
      // } 
     } 

     return returnValue; 
    } 
} 

public sealed class InnerSampleObject : SampleObjectBase 
{ 
} 

public sealed class OuterSampleObject : SampleObjectBase 
{ 
    public InnerSampleObject DerivedSampleObject { get; set; }  
} 

我的問題是,在SampleObjectBase註釋代碼,我不能得到匹配的PropertyInfo值的具體實例。如果我查看循環中的PropertyInfo對象,我發現該類型是正確的,但我找不到直接訪問實現中已存在的實例的方法。因此,執行時(例如,OuterSampleObject.IsValid()),代碼將按照預期查找InnerSampleObject的PropertyInfo。我想執行InnerSampleObject.IsValid()。

我已經嘗試(的多種變型):

var childIsValid = (bool)contractProperty.PropertyType.InvokeMember("IsValid", BindingFlags.InvokeMethod, null, null, null); 

和:

var childInstance = (ISampleContract)contractProperty; 

與第一個問題是,我不能傳遞null作爲目標InvokeMember,因爲IsValid()不是靜態的(也不可能,因爲我專注於實際的實例)。第二個只是一個蹩腳的演員,但是我想完成的要點。

上面的示例代碼僅僅是我想要實現的最簡單的例子。完整的代碼是自我驗證的DTO的一部分,遞歸地檢查整個層次結構並返回孩子有驗證問題以及它們是什麼。

任何幫助將不勝感激。

+0

看起來你'returnValue'永遠不能'真'。 – 2011-05-07 13:27:23

+0

只是一個錯字。固定,但。 ;-) – 2011-05-07 13:29:03

回答

2

如何:

var instance = childProperty.GetValue(this, null) as ISampleObject; 
if (instance != null) 
{ 
    if (!instance.IsValid()) 
    return false; 
} 
+0

哦,我的......我以爲我曾嘗試過,並得到了一個StackOverflowException。我希望我有舊版本,看看我實際上做了什麼,但是那個工作很好。 :-) – 2011-05-07 13:49:31

1

請參閱下面的代碼是否您想要的。我的變化都標有註釋開始//VH:

public interface ISampleObject 
{ 
    bool IsValid(); 
} 

public abstract class SampleObjectBase : ISampleObject 
{ 
    public virtual bool IsValid() 
    { 
     var returnValue = true; //VH: Changed value from false to true 

     // Self-validation sets the return value. 

     var childProperties = this.GetType().GetProperties().Where(pi => typeof(ISampleObject).IsAssignableFrom(pi.PropertyType)); 

     foreach (var childProperty in childProperties) 
     { 
      //VH: Here is how you get the value of the property 
      var childInstance = (ISampleObject)childProperty.GetValue(this, null); 
      if (childInstance.IsValid() != true)     
      { 
       returnValue = false; 
      } 
     } 

     return returnValue; 
    } 
} 

public sealed class InnerSampleObject : SampleObjectBase 
{ 
} 

public sealed class OuterSampleObject : SampleObjectBase 
{ 
    //VH: Added this constructor 
    public OuterSampleObject() 
    { 
     DerivedSampleObject = new InnerSampleObject(); 
    } 

    public InnerSampleObject DerivedSampleObject { get; set; } 
} 


class Program 
{ 
    static void Main(string[] args) 
    { 
     OuterSampleObject c = new OuterSampleObject(); 
     c.IsValid(); 

    } 
} 
1

只需使用

var childInstance = (ISampleObject)childProperty.GetValue(this, null); 
相關問題