隐藏继承的成员
我正在寻找有效隐藏继承成员的方法。我有一个类库,这些类是从通用基类继承的。一些较新的后代类继承了依赖属性,这些依赖属性已经过时,并且在使用IntelliSense或者在可视设计器中使用这些类时可能会造成一些混乱。
这些类都是为WPF或者Silverlight 2.0编写的所有控件。我知道ICustomTypeDescriptor
和ICustomPropertyProvider
,但是我可以肯定它们不能在Silverlight中使用。
它不仅是功能性问题,还包括可用性问题。我该怎么办?
更新
我真正要隐藏的某些属性来自我自己的祖先,并且由于我正在设计特定的工具,因此无法使用" new"运算符进行成员隐藏。 (我知道,这太荒谬了)
解决方案
回答
虽然我们无法防止使用这些继承的成员,但应该可以使用EditorBrowsableAttribute将它们从IntelliSense中隐藏:
Using System.ComponentModel; [EditorBrowsable(EditorBrowsableState.Never)] private string MyHiddenString = "Muahahahahahahahaha";
编辑:刚刚在文档注释中看到了这一点,这使其在此目的上毫无用处:
There is a prominent note that states that this attribute "does not suppress members from a class in the same assembly". That is true but not complete. Actually, the attribute does not suppress members from a class in the same solution.
回答
我认为我们最好的hacking方式是考虑组合而不是继承。
或者,我们可以创建一个具有所需成员的接口,让派生类实现该接口,然后针对该接口进行编程。
回答
我们可以做的一件潜在的事情是包含对象,而不是从另一个类进行扩展。在公开要公开的内容方面,这将为我们提供最大的灵活性,但是如果我们绝对需要该类型的对象,则不是理想的解决方案(但是我们可以从吸气剂中公开该对象)。
因此:
public class MyClass : BaseClass { // Your stuff here }
成为:
public class MyClass { private BaseClass baseClass; public void ExposeThisMethod() { baseClass.ExposeThisMethod(); } }
或者:
public class MyClass { private BaseClass baseClass; public BaseClass BaseClass { get { return baseClass; } } }
回答
像上面的迈克尔建议一样覆盖它们,并且为了防止人们使用覆盖的(sp?)方法,请将其标记为过时的:
[Obsolete("These are not supported in this class.", true)] public override void dontcallmeanymore() { }
如果将第二个参数设置为true,则如果有人尝试调用该方法并且第一个参数中的字符串是消息,则将生成编译器错误。如果parm2为false,则仅生成编译器警告。
回答
我知道有很多答案,而且现在已经很老了,但是最简单的方法就是将它们声明为"新私有"。
考虑我当前正在处理的一个示例,其中有一个API使第三方DLL中的每个方法都可用。我必须采用他们的方法,但是我想使用.Net属性,而不是" getThisValue"和" setThisValue"方法。因此,我建立了第二个类,继承了第一个类,创建了一个使用get和set方法的属性,然后将原始的get和set方法重写为私有的。想要在其上构建其他功能的任何人仍然可以使用它们,但是如果他们只想使用我正在构建的引擎,那么他们将能够使用属性而不是方法。
使用double class方法摆脱了无法使用new
声明来隐藏成员的任何限制。如果成员被标记为虚拟成员,则无法使用override
。
public class APIClass { private static const string DllName = "external.dll"; [DllImport(DllName)] public extern unsafe uint external_setSomething(int x, uint y); [DllImport(DllName)] public extern unsafe uint external_getSomething(int x, uint* y); public enum valueEnum { On = 0x01000000; Off = 0x00000000; OnWithOptions = 0x01010000; OffWithOptions = 0x00010000; } } public class APIUsageClass : APIClass { public int Identifier; private APIClass m_internalInstance = new APIClass(); public valueEnum Something { get { unsafe { valueEnum y; fixed (valueEnum* yPtr = &y) { m_internalInstance.external_getSomething(Identifier, yPtr); } return y; } } set { m_internalInstance.external_setSomething(Identifier, value); } } new private uint external_setSomething(int x, float y) { return 0; } new private unsafe uint external_getSomething(int x, float* y) { return 0; } }
现在,valueEnum可用于两个类,但是在APIUsageClass类中仅可见该属性。对于想要扩展原始API或者以其他方式使用它的人,仍然可以使用APIClass类,而对于想要更简单的东西的人,可以使用APIUsageClass。
最终,我要做的是将APIClass内部化,并且只公开继承的类。