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はどこにあり、どのように破棄するのですか?

ありがとうございました。

4

2 に答える 2

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

とにかくメンバーを明示的に配置するのではなく、リフレクションを使用したい理由があると思いますが...

于 2012-11-08T14:16:12.223 に答える
0

を使用して基本タイプのプライベートフィールドを取得することはできませんGetType().GetFields(...)。基本タイプ自体からフィールドを取得する必要があります。

Dispose:メソッドを次の2つのメソッドに置き換えます。

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
于 2012-11-08T14:19:01.903 に答える