2012-11-08 53 views
1

我有一個簡單的程序:訪問在基類和子類私有字段使用反射

using System; 
using System.Reflection; 

namespace PlayWithReflection 
{ 
class MyDisposable:IDisposable 
{ 
    private string _name; 

    public MyDisposable(string name) 
    { 
     this._name = name; 
    } 

    public string Name 
    { 
     get { return _name; } 
    } 

    public void Dispose() 
    { 
     Console.WriteLine(_name + " is disposed"); 
    } 
} 

class MyBaseClass : IDisposable 
{ 
    protected MyDisposable _baseProtectedDisposableA = new MyDisposable("_baseProtectedDisposableA"); 
    private MyDisposable _baseDisposableB = new MyDisposable("_baseDisposableB"); 

    public MyDisposable BaseProtectedDisposableA 
    { 
     get { return _baseProtectedDisposableA; } 
    } 

    public MyDisposable BaseDisposableB 
    { 
     get { return _baseDisposableB; } 
    } 

    public void Dispose() 
    { 
     var fieldInfos = this.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); 

     foreach (var fieldInfo in fieldInfos) 
     { 
      var value = fieldInfo.GetValue(this); 
      if (value is IDisposable) 
      { 
       ((IDisposable)value).Dispose(); 
       fieldInfo.SetValue(this, null); 
      } 
     } 
    } 
} 


class MyClass : MyBaseClass 
{ 
    private MyDisposable _disposableC = new MyDisposable("_disposableC"); 
    private MyDisposable _disposableD = new MyDisposable("_disposableD"); 

    public MyDisposable DisposableC 
    { 
     get { return _disposableC; } 
    } 

    public MyDisposable DisposableD 
    { 
     get { return _disposableD; } 
    } 
} 



class Program 
{ 
    static void Main(string[] args) 
    { 
     using(MyBaseClass instance = new MyClass()) 
     { 
      Console.WriteLine(instance.BaseProtectedDisposableA.Name + " is telling his name..."); 
      Console.WriteLine("--------------------------------------------------------"); 
     } 

     Console.ReadKey(); 
    } 
} 
} 

並印刷是這樣的:

_baseProtectedDisposableA is telling his name... 
------------------------------------------------------- 
_disposableC is disposed 
_disposableD is disposed 
_baseProtectedDisposableA is disposed 

的問題是如何使它打印此之一:

_baseProtectedDisposableA is telling his name... 
------------------------------------------------------- 
_disposableC is disposed 
_disposableD is disposed 
_baseProtectedDisposableA is disposed 
_baseDisposableB is disposed 

或者,換句話說,哪裏是我的私人領域_baseDisposableB,以及如何使它成爲DIS提出?

謝謝。

回答

0

這是不可能得到使用GetType().GetFields(...)的基本類型的私有字段。您必須從基本類型本身獲取字段。

:這兩種方法替換您Dispose方法:

public void Dispose() 
{ 
    var type = GetType(); 
    while (type != null) 
    { 
     DisposeFields(type); 
     type = type.BaseType; 
    } 
} 

private void DisposeFields(Type type) 
{ 
    var fieldInfos = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic); 

    foreach (var fieldInfo in fieldInfos) 
    { 
     var value = fieldInfo.GetValue(this) as IDisposable; 
     if (value == null) continue; 

     value.Dispose(); 
     fieldInfo.SetValue(this, null); 
    } 
} 

這將通過繼承層次和Dispose基本類型的字段(如果他們是一次性的)。

結果:

_baseProtectedDisposableA is telling his name... 
-------------------------------------------------------- 
_disposableC is disposed 
_disposableD is disposed 
_baseProtectedDisposableA is disposed 
_baseDisposableB is disposed 
1

哪裏是我的私人領域_baseDisposableB

閱讀來自BindingFlags枚舉文檔:

FlattenHierarchy指定公共和保護的靜態成員最多的層次應返回。不會返回繼承類中的私有靜態成員。靜態成員包括字段,方法,事件和屬性。嵌套類型不返回。

因此,不返回基類的私有成員。這是有道理的,因爲私人成員不是假設可以從派生類訪問。

如何使其處置?

既然訪問私有成員有點破解,我不會試圖從派生類中處置它。我反而明確Dispose它在基類直接:

public void Dispose() 
{ 
    var fieldInfos = this.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); 

    foreach (var fieldInfo in fieldInfos) 
    { 
     var value = fieldInfo.GetValue(this); 
     if (value is IDisposable) 
     { 
      ((IDisposable)value).Dispose(); 
      fieldInfo.SetValue(this, null); 
     } 
    } 
    _baseDisposableB.Dispose(); 
} 

雖然我假定你有一些原因想使用反射,而不是明確反正處置會員...