2008-08-04 97 views
33

我正在寻找一些方法来有效地隐藏继承成员。我有一个从普通基类继承的类库。一些更新的后代类继承了依赖性属性,这些属性已经变得残缺不全,并且在使用智能感知或在视觉设计器中使用类时可能会有点混淆。隐藏继承成员

这些类都是编写为WPF或Silverlight 2.0编译的控件。我知道ICustomTypeDescriptorICustomPropertyProvider,但我很确定那些不能在Silverlight中使用。

它不像可用性问题那样是一个功能问题。我该怎么办?

更新

一些我真的想隐藏来自不属于我自己的,因为特定的工具我设计了祖先的属性,我不能做构件,隐藏new运营商。 (我知道,这是荒谬的)

回答

32

重写他们像迈克尔:建议above并防止人们从使用重载方法,将它们标记为过时:

[Obsolete("These are not supported in this class.", true)] 
public override void dontcallmeanymore() 
{ 
} 

如果第二个参数设置为true,如果有人试图调用该方法,并且第一个参数中的字符串是消息,则会生成编译器错误。如果parm2为false,则只会生成编译器警告。

+0

你能不能封住它,同样的效果呢? – 2017-01-19 16:51:57

+0

@詹姆斯没有obselete真正的防止成员_access_,密封防止成员_inheritance_。所以一个密封的类不能被派生出来,并且一个密封的方法允许其他类成员被覆盖,但是阻止该成员被覆盖。密封不会阻止调用该类或成员,而如果尝试调用它,则使用真正的obselete会抛出编译器错误。 – 2017-05-25 15:31:26

16

虽然你不能阻止那些继承成员,据我所知的使用情况,你应该能够使用EditorBrowsableAttribute从智能感知隐藏起来:

Using System.ComponentModel; 

[EditorBrowsable(EditorBrowsableState.Never)] 
private string MyHiddenString = "Muahahahahahahahaha"; 

编辑:刚才看到这在文档注释中,这使得它对于此目的有点没用:

有一个突出的说明,指出该属性“不禁止在同一个程序集中的类的成员”。这是事实,但不完整。实际上,该属性不会在同一个解决方案中压缩类的成员。

8

我认为你最好最简单的方法是考虑构成而不是继承。或者,您可以创建一个包含您想要的成员的接口,让您的派生类实现该接口,并根据接口进行编程。

13

你可以做的一件事是包含对象而不是从其他类扩展。这会给你提供最大的灵活性,但是如果你绝对需要这个类型的对象,它不是理想的解决方案(不过你可以从getter中暴露对象)。

这样:

public class MyClass : BaseClass 
{ 
    // Your stuff here 
} 

变为:

public class MyClass 
{ 
    private BaseClass baseClass; 

    public void ExposeThisMethod() 
    { 
     baseClass.ExposeThisMethod(); 
    } 
} 

或者:(?SP)

public class MyClass 
{ 
    private BaseClass baseClass; 

    public BaseClass BaseClass 
    { 
     get 
     { 
      return baseClass; 
     } 
    } 
} 
3

我知道这有几个答案,现在已经很老了,但最简单的方法是将其声明为new private

考虑一个我目前正在使用的示例,其中有一个API可用于第三方DLL中的每个方法。我必须采取他们的方法,但我想使用.Net属性,而不是“getThisValue”和“setThisValue”方法。因此,我构建了第二个类,继承第一个类,使用get和set方法创建一个属性,然后将原始get和set方法重写为private。任何想要在它们上面构建不同的东西的人都可以使用它们,但是如果他们只是想使用我正在构建的引擎,那么他们就可以使用属性而不是方法。

使用双类方法摆脱了无法使用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或以不同方式使用API​​的人,并且APIUsageClass适用于想要更简单的用户。

最终,我会做的是使APIClass内部,并只暴露我的继承类。

1

我测试了所有建议的解决方案,并没有真正隐藏新成员。

但这一个作用:

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
public new string MyHiddenProperty 
{ 
    get { return _myHiddenProperty; } 
} 

但在代码behide它仍然是可访问的,所以加以及过时的属性

[Obsolete("This property is not supported in this class", true)] 
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
public new string MyHiddenProperty 
{ 
    get { return _myHiddenProperty; } 
} 
3

要完全隐藏和标记不使用,包括智能感知它我相信是大多数读者期望的...

[Obsolete("Not applicable in this class.")] 
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
0

您可以使用接口

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(); 
     } 
    }