Intereting Posts
Анализ через POST Двоичная сериализация и десериализация без создания файлов (через строки) C # to VB – Как преобразовать этот анонимный метод / выражение lambda? Как скрыть столбец devexpress XtraGrid Несколько файлов AppSettings, возможно ли это? Как создать обработчик событий для DataGridViewComboBoxColumn в представлении сетки данных в Winform Интерпретация базы 64 в C # из изображения, основанного на JSON / PHP (base64_encode) Является ли PLinq более быстрым, чем System.Threading.Tasks.Parallel.ForEach Как создать глобальную переменную в C #? Как разделить строку на массив строк? C #: Как назначить многие переменные целочисленным (i) для цикла? Как создать MSI для моего веб-приложения? Напишите хорошо разработанный asynchronous / неasynchronous API Приложение Windows Store Приложение для подписки на покупку в приложении Зачем использовать флаги + битмаски, а не последовательность логических элементов?

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

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

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

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

Обновить

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Рассмотрим пример, над которым я сейчас работаю, где у меня есть API, который предоставляет доступ к каждому методу в сторонней DLL. Я должен использовать их методы, но я хочу использовать свойство .Net вместо метода getThisValue и setThisValue. Итак, я создаю второй class, наследую первый, создаю свойство, которое использует методы get и set, а затем переопределяет исходные методы get и set как частные. Они все еще доступны для всех, кто хочет создать что-то другое на них, но если они просто хотят использовать движок, который я создаю, тогда они смогут использовать свойства вместо методов.

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

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

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

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

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

Но это одно:

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

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

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