隐藏继承的成员

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

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

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

更新</强>

我真正想隐藏的一些属性来自不属于我自己的祖先,并且由于我设计的特定工具,我无法使用 new 运算符执行成员隐藏。 (我知道,这很荒谬)

0
额外 编辑
意见: 2

8 答案

尽管您不能阻止使用这些继承的成员,但我应该可以使用 EditorBrowsableAttribute

Using System.ComponentModel;

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

Edit: Just saw this in the documentation comments, which makes it kinda useless for this purpose:

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

0
额外

你可以做的一件事是包含对象而不是从其他类扩展。这会给你提供最大的灵活性,但是如果你绝对需要这个类型的对象,它不是理想的解决方案(不过你可以从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;
        }
    }
}
0
额外

我认为你最不危险的方式是考虑作文而不是继承。

或者,您可以创建一个包含所需成员的接口,让派生类实现该接口,并根据接口进行编程。

0
额外

像Michael一样覆盖它们建议上面,并防止人们使用重写(sp?)方法,将它们标记为过时:

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

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

0
额外
你是否也可以用同样的效果来封印它?
额外 作者 James M,
@RobertPetz在使用过时时,会给出警告,而不是错误。巨大差距。
额外 作者 James M,
@RobertPetz你显然没有读我的,但是,对于无意义的讽刺而感到赞叹。
额外 作者 James M,
@JamesM没有obselete真正的阻止成员访问,密封防止成员继承。所以一个密封的类不能被派生出来,并且一个密封的方法允许其他类成员被覆盖,但是阻止该成员被覆盖。密封不会阻止调用该类或成员,而如果尝试调用它,则使用真正的obselete会抛出编译器错误。
额外 作者 Robert Petz,
@JamesM呃......你甚至读过你刚刚评论过的答案吗?
额外 作者 Robert Petz,
@詹姆斯我笑了,这就是为什么我回答你原来的问题,说明为什么密封没有执行相同的任务。然后你注意到 Obselete 只给出了一个警告,这是不正确的,因为 true 的第二个参数会导致编译器错误而不是警告 - 作为您直接专门评论的答案状态。如果我误解了你,我欢迎澄清。以下是 MSDN源
额外 作者 Robert Petz,

我知道这有几个答案,现在已经很老了,但最简单的方法就是将它们声明为 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内部化,并只展示我的继承类。

0
额外
如何使用这个依赖属性?
额外 作者 James M,

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

但是这个可以:

[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; }
}
0
额外

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

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

你可以使用一个接口

    public static void Main()
    {
        NoRemoveList testList = ListFactory.NewList();

        testList.Add(" this is ok ");

        // not ok
        //testList.RemoveAt(0);
    }

    public interface NoRemoveList
    {
        T this[int index] { get; }
        int Count { get; }
        void Add(T item);
    }

    public class ListFactory
    {
        private class HiddenList: List, NoRemoveList
        {
            // no access outside
        }

        public static NoRemoveList NewList()
        {
            return new HiddenList();
        }
    }
0
额外