是的,我知道之前已经提出并回答过,但没有完全解决几个问题。
参考
基本上,我想从Control
派生,但不暴露某些属性。就我而言,我正在设计一个Container
,它将包含许多Element
个,以编程方式排列。我希望(并且可能要求)Element
派生自Control
,以便获取所有绘图和事件,但也能够添加{{1}对象Element
的{{1}}集合(出于显而易见的原因)。
唯一的问题是,如果Container
派生自Children
,则会显示其Element
属性,并且用户可以轻松破坏程序化展示位置。当然,我的直觉是保留Control
附带的所有好东西并隐藏/禁用Location
。
我知道以下内容:
Control
封装在Location
中,并将所有调用转发给Control
的调用
Element
仍然不会与Control
类型兼容,并且在Element
的派生形式的许多情况下无法使用。我觉得必须有一些更优雅的解决方案(貌似)反复出现的问题。提前谢谢!
修改
我认为实现这一目标的唯一方法是:
Control
但是,我有问题,我的容器类如何设置Control
的位置?在C ++中,人们会使用朋友类。我想如果我把这个控件放在自己的程序集中,我可以将setter标记为public class Element : Control
{
public new Point Location { get; private set; }
}
。
修改
对于那些希望做某事的人,我的解决方案是:不要这样做。相反,我自己制作了一个自定义对象并实现了所有的点击/拖动等功能。尝试使用Control太复杂了,同时排除了像Location这样的功能。
答案 0 :(得分:2)
您无法完全阻止确定的程序员更新 Control.Location 属性。使用的新的关键字将改变属性的可访问性,但它仅适用于的元素的和的元素的派生类的引用。如果程序员铸实例参照基类的控制那么他们可以访问原始位置属性,因此可以更新值。如果您不关心此解决方法,那么只需继续使用您在问题中显示的覆盖。
要真正阻止任何人设置除容器之外的位置,那么您将不得不以下列方式进行更多工作。到控制的任何变化位置或大小的实际上是由发出呼叫到虚拟 SetBoundsCore 方法来实现。所以,你可以覆盖在元素的类这个虚拟方法,而忽略时,如 AllowChange 的设置实例变量除了所有试图进行的改革。然后在容器中,在更新大小/位置之前设置 AllowChange ,然后再将其重置。现在,改变大小的唯一方法是使用容器,或者程序员使用鲜为人知的更新属性。
答案 1 :(得分:0)
这听起来并不像你正在尝试创建一个替换方法(因为你担心“位置”的可替换性)所以你要么为“位置”创建一对方法,这只是扼杀了它们的事实无法更新底层的(因此您要为不希望受影响的属性创建覆盖)或忽略Liskov SOLID原则,因为这不是您正在做的事情。
答案 2 :(得分:0)
最好的方法是使用内部控制对象。这是完全未经测试的,我还不确定所有接口的可访问性,但这是我开始的方式:
[ComVisibleAttribute(true)]
[ClassInterfaceAttribute(ClassInterfaceType.AutoDispatch)]
public class Element : Component, IDropTarget, ISynchronizeInvoke, IWin32Window,
IBindableComponent, IComponent, IDisposable
{
private Control _control;
}
在这里,您可以完全隐藏或公开您选择的任何属性。您的任何接口成员都可以简单地引用内部控件属性。
HTH