2

ルートオブジェクトを受け取り、ルートオブジェクトから到達できるすべてのオブジェクトへの参照を含むリストを返すメソッドを実装したいと思います。その署名は次のようになります。

static List<object> EnumerateObjectsInRange(object root);

GetProperties()を使用してPropertyInfoオブジェクトの配列を取得し、GetValue()を使用してこれらのプロパティの値を取得し、最後に値ごとにGetProperties()を再度呼び出して、オブジェクトグラフ全体にアクセスするまでこの手順を繰り返すことを考えています。しかし、これが最善のアプローチかどうかはわかりません。

助言がありますか?

編集:

到達可能性の2つの定義を考えることができます:

  1. ルートオブジェクトの所有者がアクセスできるすべてのオブジェクト(公開されているオブジェクト)。
  2. ルートオブジェクトが属するオブジェクトグラフによって参照されるすべてのパブリックオブジェクトとプライベートオブジェクト。

私の目的には、最初の定義で十分です。

4

2 に答える 2

3

プロパティではなく、間違いなくフィールドが必要です。オブジェクトは、プロパティを介してではなく、フィールドを介して他のオブジェクトを存続させます。リストには GetFields を使用して見つける内部配列が含まれているため、特別なケースのリストは必要ありません。ただし、配列を特殊なケースにする必要があります。

ところで、私はこのアルゴリズムを実装しましたが、それが機能していて便利であることがわかりました。

于 2012-05-20T21:48:03.433 に答える
0

誰かがそれを便利だと思った場合に備えて、私はusrから書いた再帰的な方法と、私の問題を解決したHenkの回答を共有しています。

static void EnumerateObjectsInRange(object root, HashSet<object> hashset)
{
    if (root == null || hashset.Contains(root))
    {
        return;
    }

    hashset.Add(root);
    FieldInfo[] fields = root.GetType().GetFields(BindingFlags.Static
                                                | BindingFlags.Instance
                                                | BindingFlags.Public
                                                | BindingFlags.NonPublic);

    foreach (FieldInfo field in fields)
    {
        object obj = field.GetValue(root);

        if (obj == null)
        {
            continue;
        }

        if (obj.GetType().IsSubclassOf(typeof(Array)))
        {
            foreach (object member in (Array)obj)
            {
                EnumerateObjectsInRange(member, hashset);
            }
        }

        EnumerateObjectsInRange(obj, hashset);
    }
}

このメソッドはまだリファクタリングが必要です(そしてHashSetがnullかどうかをチェックしていません)が、それは仕事を成し遂げます。

これを呼び出すには、ルートオブジェクトと、訪問したオブジェクトが保存される空のHashSetを指定します。

于 2012-05-21T00:07:49.663 に答える