понедельник, 8 июля 2013 г.

Как проверить, что мы в дизайнере (DesignMode) в Windows Form

Задача

Разрабатывая элементы управления в дизайнере Windows Form, нам часто необходимо проверить в каком режиме открыли наш элемент. Ведь в реальном режиме у нас может быть сложная логика чтения информации из БД, подключения в web-службам, взаимодействия с какими-то сторонними компонентами и т. д.. На момент редактирования визуального представления, вся эта логика должна быть отключена. А, для этого, нам необходим какой-то признак, по которому мы сможем отличить дизайнер от реального запуска программы:
if( !DesignMode )
{
    //...
}

Решения

Для начала посмотрим на то, что нам предлагают разработчики от Микрософт. В классе Component имеется свойство DesignMode. "Эврика! Это именно то, что нужно", подумал я. А, прочитав описание, я уж было совсем расслабился и начал писать свой код. Однако, первое же использование моего контроля в дизайнере, ввело меня в недоумение и растерянность - DesignMode был false. Всегда! Покурив форумы, я понял, что это свойство становится true после какого-то там обряда инициализации. Далее шли рассуждения о том, в какой момент времени это свойство показывает правильное значение, а в какой неправильное.. В общем-то рассуждения весьма бредовые, потому что код "иногда работающий правильно" - это как часы которые стоят - показывают правильное время ровно 2 раза в сутки, но толку от этого никакого. Кроме того, как я уже говорил, свойство находится в классе Component, а значит, до него невозможно добраться из вспомогательных классов, не имеющих ссылку на Component, что приводит к ограничениям в рефакторинге. А это значит, что свойство не просто бесполезно, но и вредно.
Продолжая курить форумы, я случайно наткнулся на класс LicenseManager. С его помощью проверку можно осуществить следующим образом:
if( LicenseManager.UsageMode != LicenseUsageMode.Designtime )
{
    //...
}
Однако, тут есть один маленький неприятный нюанс - этот класс писали те же "руки", что и предыдущий, а значит, работает все так же "глючно" и, в самый неожиданный момент, свойство UsageMode может выдать Runtime, не смотря на то, что мы находимся в дизайнере.
Еще одно интересное решение - это проверить название процесса:
if( Process.GetCurrentProcess().ProcessName != "devenv" )
{
    //...
}
Ограничения такого решения видны сразу - оно будет работать только из-под одной среды разработки - Microsoft Visual Studio. Однако, ничего не мешает расширить проверку, если ваша команда использует другие средства. По крайней мере, тут все прозрачно и предсказуемо.
Так как же сделать проверку правильно? Ок. Есть еще один вариант, который мне кажется самым правильным - завести где-то в общей библиотеке статическую переменную DesignMode, которая по умолчанию будет равна true. А, при запуске программы, сбрасывать ее на false. Это решение стабильно, прозрачно и надежно. Но! Это ужасное решение. Дело в том, что библиотека, содержащая такое решение, накладывает ограничения на свое использование -  подключая такую библиотеку к проекту, нам придется вспомнить о нужных строчках и вписать их, а при исключении библиотеки из проекта, строчку придется удалять. Конечно, ничего криминального в этом нет. Однако, стоит нам предположить, что подход со статистическими флажками приемлем, как мы начнем использовать его повсеместно и наши библиотеки приобретут совершенно непредсказуемое поведение - ведь очень скоро уже никто и не вспомнит какие флажки надо прописать, где, когда и сколько их вообще и какие для чего.

Выводы

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

1 комментарий:

  1. Casino Sites That Take Advantage Of Mobile Version
    It allows you to play 온라인 슬롯 사이트 casino games for a seamless 카 심바 way. You don't have to pay anything. And it is also free 아시아 게이밍 to play and without 검증사이트목록 downloading any software. 바카라커뮤니티 So

    ОтветитьУдалить