0

在 My Base 类类型A中,我有另一种类型的集合B。在执行类的一些私有操作时,B我需要从类的某些成员中获取价值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.Addor添加它们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);

首先,您需要创建一个自定义集合类,它将拦截AddRemove方法:

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 回答
0

如果您在子类中只有一两个方法需要对父对象的引用,那么您可以将对父对象的引用传递给该方法。

但如果它更普遍(即子类中的大多数方法需要访问其父对象的属性),那么您可以简单地在子类上维护对父对象的引用。

我们有一个类似的问题,这就是我们解决它的方法。

于 2013-11-13T11:15:44.103 回答