Сведения о вопросе

Solllo

16:03, 1st July, 2020

Теги

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

Просмотров: 487   Ответов: 8

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

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

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

Обновление

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



  Сведения об ответе

P_S_S

18:03, 1st July, 2020

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

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

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


  Сведения об ответе

lats

18:03, 1st July, 2020

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

Using System.ComponentModel;

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

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

Есть заметное примечание, которое гласит, что этот атрибут "does not suppress members from a class in the same assembly". Это верно, но не полностью. На самом деле атрибут не подавляет членов из класса в одном и том же решении.


  Сведения об ответе

darknet

18:03, 1st July, 2020

Одна потенциальная вещь, которую вы можете сделать, это содержать объект, а не расширяться из другого класса. Это даст вам наибольшую гибкость с точки зрения раскрытия того, что вы хотите показать, но если вам абсолютно необходимо, чтобы объект был такого типа, это не идеальное решение (однако вы можете представить объект из 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;
        }
    }
}


  Сведения об ответе

KOMP

18:03, 1st July, 2020

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

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


  Сведения об ответе

prince

18:03, 1st July, 2020

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

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


  Сведения об ответе

SSESION

18:03, 1st July, 2020

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

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


  Сведения об ответе

SSESION

18:03, 1st July, 2020

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

Но этот DOES:

[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; }
}


  Сведения об ответе

lesha

18:03, 1st July, 2020

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

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


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться