在C#中封装属性和接口

时间:2014-06-23 05:03:41

标签: c# properties interface encapsulation

我有一个班级:

public class A
{
    private IB link;
    public IB Link
    {
        get { return link; }
        set
        {
            link = value;
            b.Link = this;
        }
    }
    ...
}

和界面:

public interface IB
{
    A Link { get; set; }
}

我将这样使用它:

public class B1 : IB, Button
{
    public A Link { get; set; }
    ...
}

public class B2 : IB, TextBox
{
    public A Link { get; set; }
    ...
}

b1 = new B1();
b2 = new B2();

A a = new A();
a.Link = b1;
...
a.Link = b2;

但我必须封装IB.Link属性,它只应在A类(以及A.Link属性)中更改。这可能吗?

更新

很抱歉这个例子含糊不清。我的真实代码太大而没有完成:我有一个节点结构。每个节点都有一个指向Control的链接。因此,可以构建控件的视觉结构。我们可以从节点管理控件,但不能从控件访问节点,例如,从OnMouseClick方法。我们需要有后引用 - IMyControl.OwnerNode属性。 IMyControl是仅包含此属性的接口。因此,我们可以创建“MyControl:IMyControl,Control”类并在其中实现鼠标单击逻辑。当我们将控制分配给节点时,必须创建,直接和返回两个引用,但它发生在节点类的代码中,而不是在MyControl和IMyControl代码中。 IMyControl接口中的属性字段必须可以从NodeClass写入,并且无法访问派生类的写入。我想在这里完成。

1 个答案:

答案 0 :(得分:1)

如果我理解正确,您可以使用此草稿:

class Node
{
    public ControlWrapper Link { get; set; }
}

abstract class ControlWrapper
{
    private readonly Node _node;
    private readonly Control _control;

    public Node Node
    {
        get { return _node; }
    }

    public Control Control
    {
        get { return _control; }
    }

    public ControlWrapper(Node node, Control control)
    {
        if (node == null)
            throw new ArgumentNullException("node");

        if (control == null)
            throw new ArgumentNullException("control");

        _node = node;
        _control = control;
    }
}

class ControlWrapper<TControl> : ControlWrapper
    where TControl : System.Windows.Forms.Control
{
    public TControl Control
    {
        get { return (TControl)base.Control; }
    }

    public ControlWrapper(Node node, TControl control)
        : base (node, control)
    {
    }
}

class Program
{
    static void Main(string[] args)
    {
        Node n1 = new Node();
        n1.Link = new ControlWrapper<TextBox>(n1, new TextBox());
        Node n2 = new Node();
        n2.Link = new ControlWrapper<Button>(n2, new Button());
    }
}

抽象类ControlWrapper为您提供了到节点的反向链接(您无法在接口中封装逻辑,因此抽象类在这里),类型派生泛型类提供了用于创建控件包装器的实际实现的构造函数。

如果您希望此关系自动强制其一致性,您应该编写如下代码:

class Program
{
    static void Main(string[] args)
    {
        Node n1 = new Node();
        n1.SetControl(new TextBox());
        Node n2 = new Node();
        n2.SetControl(new Button());
    }
}

class Node
{
    private ControlWrapper _link;
    public ControlWrapper Link
    {
        get { return _link; }
    }

    public void SetControl<TControl>(TControl control)
        where TControl : System.Windows.Forms.Control
    {
        ControlWrapper prevLink = Link;
        if (prevLink != null)
            prevLink.Dispose();

        _link = new ControlWrapper<TControl>(this, control);
    }
}

// microsoft basic dispose pattern
// http://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.110).aspx#basic_pattern
abstract class ControlWrapper : IDisposable
{
    private readonly Node _node;
    private readonly Control _control;

    public Node Node
    {
        get { return _node; }
    }

    public Control Control
    {
        get { return _control; }
    }

    public ControlWrapper(Node node, Control control)
    {
        if (node == null)
            throw new ArgumentNullException("node");

        if (control == null)
            throw new ArgumentNullException("control");

        _node = node;
        _control = control;
    }

    #region IDisposable Members

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    #endregion

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (_control != null)
                _control.Dispose();
        }
    }

}

class ControlWrapper<TControl> : ControlWrapper
    where TControl : System.Windows.Forms.Control
{
    public TControl Control
    {
        get { return (TControl)base.Control; }
    }

    public ControlWrapper(Node node, TControl control)
        : base (node, control)
    {
    }
}