代码之家  ›  专栏  ›  技术社区  ›  MojoFilter

隐藏继承成员

  •  36
  • MojoFilter  · 技术社区  · 16 年前

    我正在寻找有效地隐藏继承成员的方法。我有一个从公共基类继承的类库。一些较新的后代类继承了依赖属性,这些属性已经退化,在使用时可能有点混淆。 智能感知 或者使用可视化设计器中的类。

    这些类都是为WPF或Silverlight2.0编写的控件。我知道 ICustomTypeDescriptor ICustomPropertyProvider 但是我很确定这些不能在Silverlight中使用。

    它不是一个功能性问题,而是一个可用性问题。我该怎么办?

    更新

    我真正想要隐藏的一些属性来自于我自己之外的祖先,并且由于我正在设计的一个特定工具,我不能让成员用 new 操作员。(我知道,这太荒谬了)

    8 回复  |  直到 7 年前
        1
  •  33
  •   Community CDub    8 年前

    像迈克尔建议的那样超越他们 above 为了防止人们使用被覆盖的(SP?)方法,标记为已过时:

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

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

        2
  •  16
  •   Michael Stum    15 年前

    据我所知,虽然您不能阻止使用这些继承成员,但您应该能够使用 EditorBrowsableAttribute :

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

    编辑: 只是在文档注释中看到了这一点,这使得它对于这个目的来说有点无用:

    有一个突出的说明指出,该属性“不禁止来自同一程序集中某个类的成员”。这是真的,但不完整。实际上,该属性并不禁止来自同一解决方案中的类的成员。

        3
  •  13
  •   Mike Stone    16 年前

    您可以做的一件可能的事情是包含对象,而不是从另一个类进行扩展。这将在公开您想要公开的内容方面给予您最大的灵活性,但是如果您绝对需要对象是那种类型,它不是理想的解决方案(但是您可以从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;
            }
        }
    }
    
        4
  •  8
  •   Karl Seguin    16 年前

    我认为你最好的方法是考虑组合而不是继承。

    或者,您可以创建一个具有您想要的成员的接口,让派生类实现该接口,并针对该接口编程。

        5
  •  3
  •   Nathan Wheeler    14 年前

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

    考虑一个我目前正在研究的示例,其中我有一个API,它使第三方DLL中的每个方法都可用。我必须使用它们的方法,但我想使用.NET属性,而不是“getHisValue”和“settHisValue”方法。因此,我构建了第二个类,继承第一个类,生成使用get和set方法的属性,然后将原始get和set方法重写为private。对于任何想在上面构建不同内容的人来说,它们仍然是可用的,但是如果他们只想使用我正在构建的引擎,那么他们就可以使用属性而不是方法。

    使用double类方法可以消除无法使用 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对这两个类都可用,但只有属性在ApiusGeClass类中可见。api class类对于希望扩展原始API或以其他方式使用它的人仍然可用,而apiusgeclass对于那些想要更简单的东西的人仍然可用。

    最后,我将要做的是使Apiclass内部化,并且只公开继承的类。

        6
  •  3
  •   Robert    12 年前

    完全隐藏和标记不使用,包括智能感知,我相信这是大多数读者所期待的…

    [Obsolete("Not applicable in this class.")] 
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    
        7
  •  1
  •   Uwe Keim    12 年前

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

    但这一个是:

    [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; }
    }
    
        8
  •  0
  •   acon    7 年前

    您可以使用接口

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