我有一个简单的程序:
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在哪里,以及如何处理它?</ p>
谢谢。
答案 0 :(得分:1)
我的私人字段_baseDisposableB
在哪里
阅读BindingFlags枚举上的文档:
FlattenHierarchy 指定应返回层次结构中的公共和受保护静态成员。不返回继承类中的私有静态成员。静态成员包括字段,方法,事件和属性。不返回嵌套类型。
因此不返回基类的私有成员。这是有道理的,因为私有成员不能假设可以从派生类访问。
如何处理它?</ p>
由于访问私有成员无论如何都是一个黑客攻击,我不会尝试从派生类中处理它。我会直接在基类中明确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();
}
虽然我认为你有理由想要使用反射而不是明确地处理成员......
答案 1 :(得分: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