[英]Hiding inherited members
我正在寻找某种方法来有效地隐藏继承的成员。 我有一个从公共基类继承的类库。 一些较新的后代类继承了依赖属性,这些属性已经变得残留并且在使用IntelliSense或在可视化设计器中使用这些类时可能会有些混乱。
这些类都是为 WPF 或 Silverlight 2.0 编写的所有控件。 我知道ICustomTypeDescriptor
和ICustomPropertyProvider
,但我很确定它们不能在 Silverlight 中使用。
与其说是可用性问题,不如说是功能问题。 我该怎么办?
更新
我真正想隐藏的一些属性来自不是我自己的祖先,并且由于我正在设计的特定工具,我无法使用new
操作符进行成员隐藏。 (我知道,这很可笑)
像上面迈克尔建议的那样覆盖它们并防止人们使用覆盖的(sp?)方法,将它们标记为过时:
[Obsolete("These are not supported in this class.", true)]
public override void dontcallmeanymore()
{
}
如果第二个参数设置为 true,如果有人尝试调用该方法并且第一个参数中的字符串是消息,则会生成编译器错误。 如果 parm2 为 false,则只会生成编译器警告。
虽然据我所知,您无法阻止使用这些继承的成员,但您应该能够使用EditorBrowsableAttribute将它们从 IntelliSense 中隐藏起来:
Using System.ComponentModel;
[EditorBrowsable(EditorBrowsableState.Never)]
private string MyHiddenString = "Muahahahahahahahaha";
编辑:刚刚在文档评论中看到了这一点,这使得它对此毫无用处:
有一个突出的注释指出该属性“不会抑制来自同一程序集中的类的成员”。 这是真的,但并不完整。 实际上,该属性不会抑制同一解决方案中类的成员。
您可以做的一件事是包含对象而不是从另一个类扩展。 这将在公开您想要公开的内容方面为您提供最大的灵活性,但如果您绝对需要该类型的对象,这不是理想的解决方案(但是您可以从 getter 公开对象)。
因此:
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;
}
}
}
我认为你最好的最简单的方法是考虑组合而不是继承。
或者,您可以创建一个具有所需成员的接口,让您的派生类实现该接口,然后针对该接口进行编程。
完全隐藏和标记不使用,包括智能感知,我相信这是大多数读者所期望的......
[Obsolete("Not applicable in this class.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
我知道对此有几个答案,现在已经很老了,但最简单的方法就是将它们声明为new private
。
考虑我目前正在研究的一个示例,其中我有一个 API,它使 3rd 方 DLL 中的每个方法都可用。 我必须采用他们的方法,但我想使用 .Net 属性,而不是“getThisValue”和“setThisValue”方法。 因此,我构建了第二个类,继承了第一个类,创建了一个使用 get 和 set 方法的属性,然后将原始 get 和 set 方法覆盖为私有方法。 任何想要在其上构建不同内容的人仍然可以使用它们,但是如果他们只想使用我正在构建的引擎,那么他们将能够使用属性而不是方法。
使用双类方法摆脱了无法使用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 类中可见。 APIClass 类仍然适用于想要扩展原始 API 或以不同方式使用它的人,而 APIUsageClass 则适用于那些想要更简单的人。
最终,我要做的是将 APIClass 设置为内部,并且只公开我继承的类。
我测试了所有建议的解决方案,它们并没有真正隐藏新成员。
但这个确实:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new string MyHiddenProperty
{
get { return _myHiddenProperty; }
}
但是在代码隐藏中它仍然可以访问,因此也添加过时属性
[Obsolete("This property is not supported in this class", true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new string MyHiddenProperty
{
get { return _myHiddenProperty; }
}
虽然上面明确指出在 C# 中不可能更改继承的方法和属性的访问修饰符,但我通过使用隐式转换的一种“假继承”克服了这个问题。
例子:
public class A
{
int var1;
int var2;
public A(int var1, int var2)
{
this.var1 = var1;
this.var2 = var2;
}
public void Method1(int i)
{
var1 = i;
}
public int Method2()
{
return var1+var2;
}
}
现在假设您希望class B
从class A
继承,但想要更改某些可访问性甚至完全更改 Method1
public class B
{
private A parent;
public B(int var1, int var2)
{
parent = new A(var1, var2);
}
int var1
{
get {return this.parent.var1;}
}
int var2
{
get {return this.parent.var2;}
set {this.parent.var2 = value;}
}
public Method1(int i)
{
this.parent.Method1(i*i);
}
private Method2()
{
this.parent.Method2();
}
public static implicit operator A(B b)
{
return b.parent;
}
}
通过在最后包含隐式转换,它允许我们在需要时将B
对象视为A
s。 定义从A->B
的隐式转换也很有用。
这种方法的最大缺陷是您需要重新编写您打算“继承”的每个方法/属性。 这种方法可能有更多的缺陷,但我喜欢将它用作一种“假继承”。
笔记:
虽然这允许更改public
属性的可访问性,但并不能解决将protected
属性设为公共的问题。
你可以使用一个接口
public static void Main()
{
NoRemoveList<string> testList = ListFactory<string>.NewList();
testList.Add(" this is ok ");
// not ok
//testList.RemoveAt(0);
}
public interface NoRemoveList<T>
{
T this[int index] { get; }
int Count { get; }
void Add(T item);
}
public class ListFactory<T>
{
private class HiddenList: List<T>, NoRemoveList<T>
{
// no access outside
}
public static NoRemoveList<T> NewList()
{
return new HiddenList();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.