Скрытие унаследованных членов - PullRequest
36 голосов
/ 04 августа 2008

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

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

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

Обновление

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

Ответы [ 8 ]

33 голосов
/ 05 августа 2008

Переопределите их, как Майкл предлагает выше , и чтобы люди не могли использовать переопределенные (sp?) Методы, пометьте их как устаревшие:

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

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

16 голосов
/ 04 августа 2008

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

Using System.ComponentModel;

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

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

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

13 голосов
/ 04 августа 2008

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

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

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;
        }
    }
}
8 голосов
/ 04 августа 2008

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

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

3 голосов
/ 24 июня 2013

Чтобы полностью скрыть и пометить, что не использовать, в том числе intellisense, что, как я полагаю, большинство читателей ожидают ...

[Obsolete("Not applicable in this class.")] 
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
3 голосов
/ 08 декабря 2010

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

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

1 голос
/ 23 мая 2012

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

Но этот ДЕЛАЕТ:

[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 голосов
/ 13 ноября 2017

Вы можете использовать интерфейс

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