在父对象的子对象中设置只读“父”属性

时间:2015-04-15 22:08:03

标签: properties parent-child getter-setter

我正在尝试重现某些WinForms控件(例如DataGridViewDataGridViewColumn)中的行为,其中子对象具有指向父对象的属性。此属性通常是只读的,但在调用父Add()方法之后会以某种方式更改。

在我的代码中,我有两个类DataGroupDataEntry,后者是子对象。

如果我只是实现了以下内容:

public class DataEntry
{
    public DataGroup Parent { get; set; }
}

public class DataGroup
{
    public List<DataEntry> DataEntries { get; set; }

    public DataGroup()
    {
        DataEntries = new List<DataEntry>();
    }

    public void Add(DataEntry de)
    {
        // Check stuff here
        // ...
        //
        DataEntries.Add(de);
        de.Parent = this;
    }
}

它确实有效,但有一个主要缺点:DataEntry.Parent有一个公共设置器,所以可以在任何地方修改属性,而不需要我在DataGroup.Add()

中设计的任何检查

我可以做以下事情:

public class DataEntry
{
    private DataGroup _parent;
    public DataGroup Parent
    {
        get { return _parent; }
        set
        {
            _parent = value;
            _parent.Add(this);
        }
    }
}

public class DataGroup
{
    ...

    public void Add(DataEntry de)
    {
        // Check stuff here
        // ...
        //
        _dataEntries.Add(de);

        // de.Parent = this;    Already set!
    }

    ...
}

如果我想通过设置其父属性来添加子项,则可以正常工作,但如果我调用DataEntry.Parent

则不会更新DataGroup.Add()

正如我已经说过的,WinForms控件不能直接在子节点中更改Parent属性是很正常的,但是在从父节点调用Add方法后更改属性。 我无法找出链接,父母修改子属性的方法,除非该属性是公共的或通过方法公开,这两种方法都有机会绕过我​​的检查并最终产生错误

1 个答案:

答案 0 :(得分:0)

如果您只是想从外部方隐藏方法,您可以声明方法内部

internal void SetParent(DataGroup dg)
{
    //code to set parent
}

我从来没有尝试过这个,但它也可能有效。我一直都是私下做的。

public DataGroup Parent { get; internal set; }

另一个隐藏自己的选择是使用显式接口实现。甚至将它与内部结合以将其从外部隐藏起来。当您显式实现接口时,调用该方法的唯一方法是首先将对象强制转换为接口。我觉得这样的事情会起作用

internal interface ISetParent
{
   void SetParent(DataGroup dg); 
}

public class DataEntry : ISetParent
{

    void ISetParent.SetParent(DataGroup dg)
    {
        Parent = dg;
    }

    public DataGroup Parent { get; private set;}
}

public class DataGroup
{
    public List<DataEntry> DataEntries { get; set; }

    public DataGroup()
    {
        DataEntries = new List<DataEntry>();
    }

    public void Add(DataEntry de)
    {
    // Check stuff here
    // ...
    //
      DataEntries.Add(de);
      ((ISetParent)de).SetParent(this);
    }
}