Извлечение из контроля, но скрытие свойств - PullRequest
3 голосов
/ 06 июля 2011

Да, я знаю, что об этом уже спрашивали и отвечали, но ничего полностью не решает несколько проблем.

Ссылки

По сути, я хотел бы получить из Control, но без предоставления определенных свойств.В моем случае я проектирую Container, который будет содержать много Element с, организованных программным способом.Мне бы хотелось (и может потребовать ), чтобы Element был получен из Control, чтобы получить все рисунки и события, но также иметь возможность добавлять Element объекты в Container 'Children collection (по понятным причинам).

Единственная проблема в том, что если Element наследуется от Control, тогда его свойство Location открыто, и пользователь может легко уничтожитьпрограммное размещение.Естественно, мой инстинкт состоит в том, чтобы сохранить все вкусности, которые идут вместе с Control, и скрыть / отключить Location.

. Мне известно следующее:

  • Этонарушает принцип замещения SOLID Liskov (проектирование по контракту)
  • Это было задано ранее
  • Я мог бы инкапсулировать Control в моем Element и переадресовывать все вызовы на Control
    • Это было бы нелепым трудом, но без реальной выгоды.
    • Инкапсулирующий Element все еще не совместим по типу с Control и не может использоваться вво многих случаях, когда производная форма Control будет.

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

Редактировать

Единственный способ, которым я вижу, чтобы сделать это:

public class Element : Control
{
    public new Point Location { get; private set; }
}

Но тогда у меня проблемаКак мой контейнерный класс устанавливает местоположение Element s?В C ++ можно использовать класс друга.Я полагаю, если бы я сохранил этот элемент управления в его собственной сборке, я мог бы пометить сеттер как internal.

Редактировать

Для тех, кто хочет что-то сделать, мойРешение было: не делать этого.Вместо этого я сделал собственный объект и сам реализовал все нажатия / перетаскивания и т. Д.Было слишком сложно попробовать использовать элемент управления, исключая такие функции, как Location.

Ответы [ 3 ]

2 голосов
/ 06 июля 2011

Вы не можете полностью предотвратить обновление свойства Control.Location определенным программистом. Использование ключевого слова new изменит доступность свойства, но оно применяется только к ссылкам на производные классы Element и Element . Если программист преобразует ссылку на экземпляр в базовый класс Control , он может получить доступ к исходному свойству Location и, следовательно, может обновить значение. Если вас не волнует этот обходной путь, тогда просто продолжайте и используйте переопределение, которое вы показали в вопросе.

Чтобы по-настоящему запретить кому-либо устанавливать местоположение, кроме вашего контейнера, вам придется проделать немного больше работы следующим образом. Любое изменение в элементах управления Location или Size фактически реализуется путем вызова виртуального метода SetBoundsCore . Таким образом, вы можете переопределить этот виртуальный метод в своем классе Element и игнорировать все предпринятые изменения, кроме случаев, когда установлена ​​переменная экземпляра, такая как AllowChange . Затем в вашем контейнере вы устанавливаете это AllowChange непосредственно перед обновлением размера / местоположения, а затем сбрасываете его обратно впоследствии. Теперь единственный способ изменить размер - использовать ваш контейнер или, если программист использует малоизвестное свойство update.

0 голосов
/ 06 июля 2011

Лучший способ добиться этого - использовать объект внутреннего контроля. Это полностью не проверено, и я еще не уверен в доступности всех интерфейсов, но я бы начал так:

[ComVisibleAttribute(true)]
[ClassInterfaceAttribute(ClassInterfaceType.AutoDispatch)]
public class Element : Component, IDropTarget, ISynchronizeInvoke, IWin32Window, 
IBindableComponent, IComponent, IDisposable
{
    private Control _control;
}

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

НТН

0 голосов
/ 06 июля 2011

Не похоже, что вы пытаетесь создать метод замены (поскольку вы беспокоитесь о заменяемости «Location»), поэтому либо вы создаете пару методов для «Location», которые просто заглушают тот факт, что ониневозможно обновить базовый (поэтому вы создаете переопределение для свойств, на которые вы не хотите влиять) или игнорируете принципы Liskov SOLID, потому что это не то, что вы делаете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...