2008-08-04 2 views
33

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

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

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

Update

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

ответ

32

переназначить их как Майкл Предлагает above и предотвратить людей от использования преодолено методов , отметьте их как устаревшие:

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

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

+0

Можете ли вы запечатать его, также, с тем же эффектом? – 2017-01-19 16:51:57

+0

@JamesM no obselete with true предотвращает член _access_, запечатанный предотвращает член _inheritance_. Таким образом, закрытый класс не может быть получен, и закрытый метод позволяет переопределить другие члены класса, но не позволяет этому члену переопределяться. Запечатанное не препятствует вызову этого класса или члена, в то время как obselete с true вызывает ошибку компилятора, если вы попытаетесь вызвать его. – 2017-05-25 15:31:26

16

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

Using System.ComponentModel; 

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

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

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

8

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

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

13

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

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

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

Я знаю, что на это было несколько ответов, и сейчас это довольно старый, но самый простой способ сделать это - просто объявить их как 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

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

Но это один ДЕЛАЕТ:

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

Но в коде-behide она по-прежнему доступны, так что добавить, а устаревшую Атрибут

[Obsolete("This property is not supported in this class", true)] 
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
public new string MyHiddenProperty 
{ 
    get { return _myHiddenProperty; } 
} 
3

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

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

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

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(); 
     } 
    } 
Смежные вопросы