Скрытие наследуемых элементов

Я ищу какой-то способ эффективно скрыть унаследованные члены. У меня есть библиотека классов, которые наследуют от общих базовых классов. Некоторые из более поздних классов-потомков наследуют свойства зависимостей, которые стали рудиментарными и могут быть немного запутанными при использовании IntelliSense или при использовании классов в визуальном конструкторе.

Эти классы являются элементами управления, которые записываются для компиляции для WPF или Silverlight 2.0. Я знаю о ICustomTypeDescriptorandICustomPropertyProvider, но я уверен, что они не могут быть использованы в Silverlight.

Это не столько функциональная проблема, сколько проблема удобства использования. Что мне делать?

Обновить

Некоторые из свойств, которые я действительно хотел бы скрыть, происходят от предков, которые не являются моими собственными, и из-за конкретного инструмента, для которого я разрабатываю, я не могу сделать скрытие элемента с помощью newоператора. (Я знаю, это смешно)

8 ответов

  1. Хотя нельзя запретить использование унаследованных элементов в my knowledge, их можно скрыть от IntelliSense с помощью атрибута EditorBrowsableAttribute:

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

    Edit: просто увидел это в комментариях к документации, что делает его бесполезным для этой цели:

    Существует заметное примечание, которое гласит, что этот атрибут «не подавляет членов из класса в той же сборке». Это верно, но не полностью. На самом деле атрибут не подавляет членов из класса в том же решении.

  2. Я думаю, что вы лучше всего наименее хакский способ, чтобы рассмотреть композицию, в отличие от наследования.

    Или можно создать интерфейс, содержащий нужные элементы, реализовать этот интерфейс в производном классе и настроить программу против интерфейса.

  3. Одна потенциальная вещь, которую вы можете сделать, это содержать объект, а не расширяться от другого класса. Это даст вам наибольшую гибкость с точки зрения предоставления того, что вы хотите предоставить, но если вам абсолютно нужен объект такого типа, это не идеальное решение (однако вы могли бы предоставить объект из геттера).

    Таким образом:

    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. Переопределите их, как Майкл предлагает выше, и чтобы предотвратить использование переопределенных (sp?) методы, пометить их как устаревшие:

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

    Если второй parm имеет значение true, ошибка компилятора будет сгенерирована, если кто-то попытается вызвать этот метод и строка в первом parm является сообщением. Если значение parm2 равно false, будет создано только предупреждение компилятора.

  5. Я знаю, что было несколько ответов на это, и это довольно старый сейчас, но самый простой способ сделать это-просто объявить их как new private.

    Рассмотрим пример, над которым я сейчас работаю, где у меня есть 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. Класс APIClass по-прежнему доступен для людей, которые хотят расширить исходный API или использовать его по-другому, а APIUsageClass доступен для тех, кто хочет что-то более простое.

    В конечном счете, то, что я буду делать, это делать APIClass внутренним, и только раскрывать мой унаследованный класс.

  6. Я протестировал все предложенные решения,и они не скрывают новых участников.

    Но это делает:

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

    Но в Code-behide это все еще доступно, поэтому добавьте также устаревший атрибут

    [Obsolete("This property is not supported in this class", true)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public new string MyHiddenProperty
    { 
        get { return _myHiddenProperty; }
    }
    
  7. Чтобы полностью скрыть и отметить не использовать, в том числе intellisense, который я считаю, что большинство читателей ожидают …

    [Obsolete("Not applicable in this class.")] 
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    
  8. Вы можете использовать интерфейс

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