0

My Base class typeAには、別の type のコレクションがありBます。class のいくつかのプライベート操作を実行しているときに、 classBのいくつかのメンバーから値を取得する必要がありますA

これを達成するためのベストプラクティスは何ですか?

私の問題のステートメントは次のようになります。

public class VisualService : IVisualService
{

   private readonly IList<AbstractVisualServer> myVisualServers = 
         new List<AbstractVisualServer>();

   // .... Other Members.. Goes below
   ...
}


public abstract class AbstractVisualServer
{

    // Need to use some of the members from VisualService inside the 
    // VisualServer class (Abs Base is AbstractVisualServer)
    // Hence, needs to hold the instance of VisualService.

    private IVisualService VisualService;
}

これに対する最善のアプローチを親切に提案してください。そして、この種のアプローチに関連する潜在的な問題は何でしょうか。ありがとう..

4

2 に答える 2

0

この問題は、クラスの階層があり、子ノードが親ノードにアクセスできる必要がある場合によく発生します。

より多くの情報がなければ、何が最適かを判断するのは困難ですが、いくつかのオプションがあります。

  1. つまり、親ノードへの参照を保持するフィールドを作成し、これらの参照を手動で追跡します。
  2. 親ノードへの参照を保持するフィールドを用意し、これが自動的に実行されるようにクラスを配置します (このアプローチには欠点がありますが、以下で説明します)。
  3. 各子ノードの親へのマッピングを保持し、手動で更新する別のクラスを用意します (子クラスに追加のフィールドを持たないようにしたい場合)。
  4. 親コレクションから子ノードを追加または削除し、これらの参照を更新するために使用する必要がある別のクラスを用意します。myVisualServers.Addこれには、またはを使用して直接追加するのではなく、すべての挿入と削除をこのクラスで行う必要がありますmyVisualServers.Remove
  5. これらのメソッドの呼び出し元に親クラスへの参照を渡すようにします (@tamijud が提案したように)。これは、正しい親を取得すること、または呼び出し元がこの情報をまったく知っていることを保証するものではありません。
  6. 最後にmyVisualServers、クラスのインスタンス化後にコレクションが不変であると想定されている場合VisualService、コンストラクター内でコレクション全体を渡し、そこにすべての参照を配線できるため、物事が単純化される可能性があります。

この割り当てを自動化したい場合はAbstractVisualServer、アイテムの挿入と削除でこれを実行する独自の「スマート」コレクションを作成できます。ただし、このアプローチの問題は、この特定の実装に縛られており、他のインターフェイスに依存してこれを行うことができないことです (別の実装がIVisualService同じことを保証するものはありません)。

その場合、これがあなたが達成したいことだと思います:

Parent parent = new Parent() { Name = "Parent" };
Child child = new Child() { Name = "Child" };

// starting conditions
Debug.Assert(parent.Children.Count == 0);
Debug.Assert(child.Parent == null);

// adding a child should set its parent
parent.Children.Add(child);
Debug.Assert(child.Parent == parent);

// removing a child should clear its parent
parent.Children.Remove(child);
Debug.Assert(child.Parent == null);

// setting a parent should add that child to the collection
child.Parent = parent;
Debug.Assert(parent.Children.Contains(child));

// clearing a parent should remove that child from the collection
child.Parent = null;
Debug.Assert(parent.Children.Count == 0);

Addまず、インターセプトとRemoveメソッドを実行するカスタム コレクション クラスを作成する必要があります。

public class Parent
{
    public string Name { get; set; }

    // Note that this is a custom private collection class
    private readonly ChildCollection _children;
    public ICollection<Child> Children
    {
        get { return _children; }
    }

    private class ChildCollection : 
        System.Collections.ObjectModel.Collection<Child>
    {
        private readonly Parent _parent;
        public ChildCollection(Parent parent)
        {
            _parent = parent;
        }

        protected override void InsertItem(int index, Child item)
        {
            // remove from previous parent
            if (item.Parent != null)
                item.Parent.Children.Remove(item);

            base.InsertItem(index, item);

            // assign the new parent
            item.Parent = _parent;
        }

        protected override void RemoveItem(int index)
        {
            // this item no longer has a parent
            var item = this[index];

            base.RemoveItem(index);

            item.Parent = null;
        }

        protected override void SetItem(int index, Child item)
        {
            // remove from previous parent
            if (item.Parent != null)
                item.Parent.Children.Remove(item);

            base.SetItem(index, item);

            // assign the new parent
            item.Parent = _parent;
        }

        protected override void ClearItems()
        {
            foreach (var i in this)
                i.Parent = null;

            base.ClearItems();
        }
    }

    public Parent()
    {
        _children = new ChildCollection(this);
    }
}

また、Childクラスは「親を認識する」必要があります。

public class Child
{
    public string Name { get; set; }

    private Parent _parent;
    public Parent Parent
    {
        get
        {
            return _parent;
        }
        set 
        {
            if (_parent == value)
                return;

            if (_parent != null && _parent.Children.Contains(this))
                _parent.Children.Remove(this);

            _parent = value;

            if (_parent != null && !_parent.Children.Contains(this))
                _parent.Children.Add(this);
        }
    }
}
于 2013-11-13T12:09:31.193 に答える