понедельник, 27 декабря 2010 г.

Разработка расширяемых приложений. SOLID и MEF.

За последние несколько месяцев, уже четырежды выступал с докладами перед небольшими аудиториями (на своей текущей работе, и на своей прошлой работе). И похоже, наконец-то начинает получаться!

Последний доклад, на тему "Разработка расширяемых приложений. Принципы SOLID. Практика использования Managed Extensibility Framework (MEF)", прочитал неделю назад. Вроде как, ребятам очень понравилось, приглашали еще; а для меня - соответственно, это первый доклад, который появилось желание опубликовать в блоге.

Вкратце, доклад состоял из следующих частей:
- принципы SOLID - что это такое, для чего они нужны, наглядные примеры;
- описание и краткое сравнение IoC-контейнеров;
- практический пример использования MEF (на основе кода реального коммерческого приложения, над которым я сейчас работаю)

Сегодня получил видео, однако, видео оказалось в довольно плохом качестве, пришлось присоединять к нему слайды. Длительность видео - 43 минуты, сопровождающая презентация получилась из 37 слайдов.

Видео доступно на отдельной страничке. Буду рад увидеть здесь ваши комментарии!

вторник, 16 ноября 2010 г.

CollectionEditor: валидация уникальных элементов

PropertyGrid - очень удобная штука. Однако же, встроенные редакторы коллекций то ли недоделаны, то ли просто не предназначены по задумке для расширений. Мне потребовалось реализовать валидацию уникальных элементов коллекции в CollectionEditor, нашел вариант со StackOverflow, однако глючный и, похоже, непроверенный.

Пришлось писать свой.

суббота, 13 ноября 2010 г.

Linq-to-Regex

Думал про нестандартные использования Linq (НЕ Linq-to-<источник данных>). В процессе, исходя из логических умозаключений, набрал в гугле фразу "linq-to-regex". Раньше никогда про него не слышал, не знал, не видел, не думал, что оно такое есть...

Но Linq-to-Regex должен был существовать, по следующим причинам:
1. Регулярное выражение, особенно не банальное [A-Za-z0-9]+ - штука довольно сложная для визуального восприятия.
2. Regex'ы - это идеальное вместилище для труднопрогнозируемых ошибок из серии "очепятка". А шарп по своей идеологии категорически не должен такое разрешать.
3. Regex'ы как класс реализованы в C# и .Net отвратительно, совершенно не встроены в язык, поддерживают очень мало полезных фишек... И несмотря на то, что я обожаю перл, и обожаю перловые регексы, и нет, наверное, ни одного скрипта на перле, где бы я их не использовал - несмотря на всё это, за все те 3 года, которые я пишу на C#, я юзал шарповые Regex'ы ну может раз 5-6 (причем, чаще всего в валидаторах, и регексы чаще всего были крайне примитивными)...

четверг, 4 ноября 2010 г.

Автоматический merge файлов во время установки


Судьба столкнула с довольно интересной задачей. Вкратце, её можно сформулировать как оффлайн-синхронизация файлов в процессе установки.

Я бы предпочел такое решение сделать в виде онлайн веб-сайта, но с командиром не поспоришь. Сказал WinForms - будет тебе WinForms. И WiX - заодно!

Речь идет об утилите для переводчиков для перевода ресурсов действующего и развивающегося продукта. Переводчики должны переводить resx-файлы, и пересылать их нам, разработчикам. Поскольку продукт развивается, естественно, что мы им тоже должны посылать свежие версии файлов, с новыми ресурсами. Посылаемые нами файлы скорее всего будут в виде установщиков - так проще всего. А значит, нужно придумать мерж во время установки!

среда, 3 ноября 2010 г.

Рекурсия Linq'ом

Задача рекурсивного обхода встает очень часто. Например, в SharePoint'е, я сталкивался с этим при рекурсивном добавлении пунктов меню и при удалении пунктов меню с флагом IsExternal (про это есть отдельный пост, "Локализация меню SharePoint 2010"); любые деревообразные контролы типа TreeView также частенько этого требуют, ну да и без всяких контролов, любые вложенные объекты рано или поздно требуют рекурсии или аналогичной по смыслу операции.

Раньше как-то не задумывался, что это можно реализовать на Linq'е. А ведь оказывается, простейший Extension Method эту проблему решает. Например, потребовалось подписать на событие MouseDown все вложенные контролы некой формы, код в таком случае будет выглядеть примерно так:
foreach(Control c in this.Controls.WithDescendants(c => c.Controls))
{
    c.MouseDown += new EventHandler<MouseEventArgs>(Controls_MouseDown);
}

понедельник, 25 октября 2010 г.

Производительность LuaInterface

LuaInterface - это лучший, насколько мне известно, LUA wrapper для .Net-а на сегодняшний день. Конечно, нет предела совершенству, но оперировать враппером действительно очень просто, да и возможности завораживают. Кто не читал, очень рекомендую ознакомиться с документацией, доступной на сайте проекта LuaInterface.

Однако, с точки зрения производительности, всё далеко не так радужно. В этом посте я приведу замеры производительности и использования памяти для библиотеки LuaInterface.

четверг, 21 октября 2010 г.

SharePoint 2010 Ribbon: как удалять и заменять OOTB кнопки на риббоне

Всё-таки, Ribbon в шарепойнте - штука полезная. К примеру, Content Editor Web Part именно благодаря Ribbon'у выглядит подобно Word'у, и оттого так нравится многим (в том числе и мне). И естественно, что частенько требуется кастомизировать этот самый Ribbon.


Чаще всего задача заключается в добавлении какой-нибудь кнопки для собственного списка. Это делается довольно просто, и описано в MSDN. А вот недавно мы столкнулись с необходимостью удаления трех кнопок из риббона библиотеки документов - "Создать", "Отправить" и "Создать папку". Вместо них планировалось добавить одну собственную кнопку, которая должна была перенаправлять пользователей на страницу, где на основе вводимых данных документ для библиотеки генерировался бы программно.

Однако, стандартный в таких случаях HideCustomAction элемент, несмотря на несколько часов попыток, не помог удалить искомые кнопки из Ribbon'а. В этом посте я расскажу, как нам удалось обойти эту проблему и добиться желаемого.

вторник, 19 октября 2010 г.

Microsoft Magic: Локализация стандартного списка Links

Видимо, серия Microsoft Magic скоро станет самой большой серией постов в этом блоге :)

Итак, задача очень распространенная. Есть в шарике стандартный список Links. Если мы хотим создать инстанс этого списка для собственных целей, это делается очень просто, создаем айтем ListInstance, и заполняем его примерно следующим XML-ем:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <ListInstance Id=""
                Title="$Resources:core,linksList"
                OnQuickLaunch="FALSE"
                TemplateType="103"
                FeatureId="00bfea71-2062-426c-90bf-714c59600103"
                Url="PersonalLinks"
                Description="">
    <Data>
      <Rows>
        <Row>
          <Field Name="ID">1</Field>
          <Field Name='URL'>http://google.ru, Поиск Google</Field>
        </Row>
        <Row>
          <Field Name="ID">2</Field>
          <Field Name='URL'>http://omlin.blogspot.com, Блог Омлина :)</Field>
        </Row>
      </Rows>
    </Data>
  </ListInstance>
</Elements>

Ну и дальше, всё это добавляется в фичу и успешно деплоится.
И вот, мне потребовалось контент этого списка локализовать. Ну например, чтобы у америкосов был google.com, а у китайцев - baidu.com. Создаем ресурсный файл, ну и выносим ссылки. Все вроде просто. Но вот тут всплыл вдруг такой эксепшен:
Недопустимый URL-адрес: $Resources: TestResources. >> в Microsoft.SharePoint.Administration.SPElementDefinitionCollection.ProvisionListInstances(SPFeaturePropertyCollection props, SPSite site, SPWeb web, Boolean fForce)

Нерабочий вариант:

<Row>
    <Field Name="ID">1</Field>
    <Field Name='URL'>$Resources: TestResources, Links_ItemUrl1</Field>
</Row>

Совершенно случайно, обнаружился рабочий вариант. Сравниваем:

<Row>
    <Field Name="ID">1</Field>
    <Field Name='URL'>$Resources:TestResources, Links_ItemUrl1</Field>
</Row>

No comments :)

P.S. Актуально для полей типа URL в любых списках.

Бесплатный профайлер для .Net

Разрабатываю некий редактор мира для онлайн-игры (не по работе). Ну там, монстры, комнаты, предметы... На WinForms. Ну вот, почему-то так сложилось, что не WPF, и я думаю, правильно сложилось...

Дак вот, нужно, чтобы карта спокойно держала 200к объектов, из которых 20к комнат. Неудивительно, что потребовался профайлер. Однако, дома у меня Visual C# Express, и встроенного майкрософтовского профайлера я, посему, лишен. Между прочим, также как владельцы Visual Studio Professional, так что весьма актуально, как мне кажется.

Пришлось искать какой-то бесплатный аналог. Хотелось, чтобы профайлер выполнял свою основную функцию, без наворотов, но чтобы при этом не надо было думать или иным путем выпендриваться...

воскресенье, 10 октября 2010 г.

Видео-доклад с презентацией: FLVScrubber, Flex-Ajax Bridge и SWFObject

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

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

Итак, идеальный вариант - совмещать на одном видео и изображение докладчика, и изображение с проектора. Чтобы это проделать, используются различные методы.

среда, 29 сентября 2010 г.

Microsoft Magic: Setup-проекты

Вчера несколько часов убили, разбираясь с такого рода ошибками при добавлении новых файлов в установщик:
Error 39 Unable to find source file 'D:\Projects\<путь к файлу>\xxx.DLL' for assembly 'xxx.DLL', located in '[TARGETDIR]\<путь к файлу на целевой системе>'
Проблема крылась в появлении магическим образом дубликатов некой dll-ки, уже добавленной в проект ранее. Причем, у дубликатов был неверный SourcePath, из-за чего и ругалась студия.

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

Сегодня решил порыться в интернете на эту тему как следует, и через некоторое время обнаружил статью "Wrestling with Windows Installer", которая помогла решить проблему.

Оказывается, у Setup-проекта есть такое магическое свойство SearchPath. Вообще говоря, по умолчанию оно пустое:

 , но если нажать кнопку [...], оказывается, что по умолчанию там выставлена галочка Include standard search paths:



Если снимаешь эту галочку, то проблемы с дублирующимися dll-ками магическим образом исчезают. Вау :)

пятница, 24 сентября 2010 г.

Быстрый способ локализации Content Editor Web Part

Проблема: ContentEditorWebPart (далее CEWP) помечен как sealed, и как следствие, отнаследоваться от него мы не можем. А встроенными средствами, да, он локализацию не поддерживает. Ту, которая "на лету". По крайней мере я не нашел, как это можно сделать.

Вообще, сделать такую же вебчасть раньше не представляло совершенно никаких проблем. Например, на основе TinyMCE. Но сейчас MS реализовал классную фишку с Ribbon'ом, благодаря чему интерфейс редактора даже чем-то напоминает Word. Это выглядит очень клево, и мне нравится, и вообще это стандартная веб-часть, и здорово было бы именно её использовать.


четверг, 23 сентября 2010 г.

Рефакторинг модулей SharePoint-проектов

Есть у SharePoint несколько недоработок и тонкостей. В частности, не очень проработан рефакторинг, с чем я и столкнулся не далее как вчера. Ошибок, при этом, выдается множество самых разных, причем большинство - не слишком внятные.

Я видел вот такие ошибки:
Feature1.feature : error : The following file can not be found: "<путь к файлу>".
Error occurred in deployment step 'Activate Features': Failed to instantiate file "<имя файла>" from module "<название модуля>": Source path "Features\Feature1\<путь к файлу внутри фичи>" not found.
Error occurred in deployment step 'Activate Features': The specified name is already in use. The document or folder name was not changed. To change the name to a different value, close this dialog and edit the properties of the document or folder.
Все эти ошибки связаны с перемещением файлов между модулями (шаблон элемента SharePoint -> 2010 -> Module), переименованиями модулей и т.п.

понедельник, 20 сентября 2010 г.

On-fly локализация меню в SharePoint Foundation 2010

Как вы, наверняка, знаете, в SharePoint 2010 добавлена возможность смены локализации сайта "на лету". Однако, контент, который был внесен пользователем вручную, или создан при развертывании шаблона сайта, или создан при активации фич, не подлежит локализации "на лету". Казалось бы, довольно логично. Но что делать, если хочется?...

В SharePoint Server есть Variation Labels, есть Publishing Pages, а вот в Foundation ничего этого нет.

Я начал проработку локализации меню с двух неудачных попыток. Потратил огромную кучу времени (хотя как оказалось, всё можно сделать за полчаса), но с третьей попытки всё-таки мне удалось сделать всё как я хотел. А хотел я так:
  1. Пункты меню развертываются фичей. И удаляются тоже ею же, при деактивации. Фича развертывается в пределах веба.
  2. При переключении текущего языка на сайте, пункты меню сразу же локализуются. Т.е. сайт может смотреть одновременно несколько пользователей, и все будут видеть меню именно на выбранном ими языке.
Надеюсь, представленный ниже код сэкономит кому-нибудь кучу времени.

пятница, 17 сентября 2010 г.

Кэш SharePoint

Иногда SharePoint кэширует намертво. Не помогает ничего. Переразвертывание фич, iisreset'ы, перезапуски служб... Иногда даже ребут не помогает. Где-то сидит кэш и всё тут. За последние дни уже трижды с этим встречался, и каждый раз разбирательства отнимали у меня кучу времени...

SharePoint Cache Storage


Один раз даже хотел запостить вопрос на StackOverflow - но в итоге поборол проблему, перезагрузившись. И что вы думаете? Буквально через несколько часов, обнаруживаю на этом самом StackOverflow вопрос с точно такими же симптомами, как и мой несостоявшийся - практически 1 в 1. Тоже связан с локализацией, тоже производится развертывание фичами неких сложных элементов. У меня это была страница с элементом AllUserWebPart, а у Don Carnage не сложилось с заголовками списков.

Ну и я значит, тут же пишу этому парню, вот мол, так и так, перезагрузись, или вот тебе еще ссылка, должно помочь (а по ссылке, между прочим, очень хитрый способ, с остановкой OWSTimer, и последующим удалением строго определенных xml-файлов). Он видимо тоже обрадовался, даже ассептнул поначалу мой ответ, но уже через пару часов смотрю - снимает ассепт. НЕ ПОМОГЛО!!

Так и хотелось написать: SharePoint has you :)

Update: От кэша resx-файлов, похоже, гарантированно спасает удаление файлов из папки C:\Users\%username%\AppData\Local\assembly\dl3 (в Windows 7). Перед этим, как правило, требуется закрыть студию.

четверг, 16 сентября 2010 г.

Блоги на SharePoint 2010

Часть блогов на sharepoint.microsoft.com переведена на использование SharePoint 2010 (например, Steve Walker's SharePointing Blog). Ну что я могу сказать, не фонтан. В комментах - спам, хоть и написано про content approval (может, поздно включили?). Можно перейти на просмотр всего контента узла, и посмотреть даже не аппрувленные комментарии (а ведь это всё индексируется!). Сами комменты какие-то дурные, и еще такое ощущение, что регистрация пользователей там не предусмотрена... Юзабилити отвратительное. Никаких особых фишек нет, всё крайне примитивно. Ни рейтингов, ни related posts, ни ленты последних комментариев, ни колонки лучших комментаторов... Да, очень бесит, что подсветку синтаксиса ввести в свои посты ребята почему-то не удосужились (хотя можно ведь! пусть даже и сторонней утилитой, как, например, я это делаю здесь, на Blogger'е). Плюс к тому, все эти блоги почему-то периодически зависают и не выдают контент.
Меня эти факты всё больше укрепляют во мнении, что SharePoint - это всё-таки фреймворк, а не CMS. Т.е., его нужно обязательно очень серьезно настраивать и кастомизировать, прежде чем выкладывать, особенно если выкладываешь в интернет...

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

среда, 15 сентября 2010 г.

Deskwork

Про продукт, который мы разрабатываем, выпустили видеоролик. Качественно делают, блин. Я б тоже хотел так уметь! В блог бы вставлял... :)

вторник, 14 сентября 2010 г.

Внутри stackoverflow: первые впечатления

Я уже упоминал, что недавно зарегистрировался на stackoverflow. Хочу поделиться первыми впечатлениями использования этого сайта.


Первым делом, отмечу, что вопросы я сам пока не задавал, только отвечал. Как правило, у меня банально не хватает терпения дождаться хорошего ответа. Работа авральная, решения нужны быстрые. Если хорошего решения не находится сразу, в течение получасового поиска в гугле - использую какой-нибудь workaround. Но не все такие, как я. И помогая людям, которые задают вопросы, я и сам многому могу научиться.


понедельник, 13 сентября 2010 г.

Вложенные тэги

Блог у меня молодой и развивающийся. Поэтому многие организационные вопросы еще не решены.

Вот сегодня, ломал голову, как же организовать тэги по SharePoint'у в блоге.


воскресенье, 12 сентября 2010 г.

Многоязычные установщики MSI

Буквально вчера зарегился на StackOverflow, и обнаружил любопытный вопрос по Microsoft Installer. В результате поиска в документации, книжках и интернете, удалось установить: оказывается, создание многоязычных msi-установщиков возможно! Причем, без всяких bootstrapper'ов.

Хитрость заключается в использовании embedded transforms и недокументированной возможности Windows Installer.

среда, 8 сентября 2010 г.

Cruise Control .Net и развертывание SharePoint-продуктов

Благодаря Cruise Control .Net (далее - CCNet) недавно удалось решить несколько важных проблем на работе, поэтому спешу поделиться!


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

Ниже речь пойдет о применении CCNet для непрерывной интеграции большого коробочного продукта под SharePoint.

воскресенье, 5 сентября 2010 г.

Экзамены по SharePoint

Готовлюсь к 70-542, MOSS 2007. Почему 2007? Потому что у меня по нему большой и хороший опыт, а буду ли работать вообще с SharePoint Server 2010 - неизвестно.

Хочу такой :)
Вообще, нас хотели отправить на сертификацию массово, еще зимой, но по ряду причин (главным образом из-за авралов) - не отправили. А в июле 2010го (почти одновременно с появлением экзаменов по 2010-му шарику), как выяснилось, обновились вопросы экзамена 70-542. И их дампов, между прочим, до сих пор нигде нет!

Вы скажете, - "Ага, злобный дампер"?

четверг, 2 сентября 2010 г.

.Net Framework Setup-проект - организация обновлений

Сегодня пришлось задержаться на работе, решая внезапно вылезшую проблему со стандартным MS-овским Setup-проектом. Сделал новую версию некоей программы, и решил проверить, как инсталлятор обновит предыдущую версию. В итоге - целый час потерял, прежде чем удалось все решить.

Как выяснилось, обновления для стандартных проектов .Net Setup Project - задача, требующая знания некоторых довольно тонких ньюансов.

вторник, 31 августа 2010 г.

Производительность SharePoint

Я столкнулся с проблемами производительности SharePoint при работе с MOSS 2007 для одного из наших крупных клиентов. Задержки при запросе страниц доходили аж до 15-30 секунд - и это на очень хороших серверах! Казалось бы, всё очевидно - медлительный BDC. Однако, сейчас, не затрагивая BDC, удалось производительность улучшить многократно (до значений 0.6-3.2 секунды) - исключительно за счет переписывания собственного кода + введения кэширования.

Ниже я постараюсь описать некоторые причины медлительности при работе с SharePoint, и изложить рекомендации о том, как решить проблемы, связанные с производительностью.

среда, 25 августа 2010 г.

Флэш-игрушки

Разбирался сегодня со старыми проектами, отрыл пару стародавних игрушек, написанных мною когда-то на флэше... Улыбнуло!

Есть желающие сыграть?

понедельник, 23 августа 2010 г.

Setup-проекты в Visual C# Express

Одно из серьезных ограничений Visual C# Express - это невозможность использования майкрософтовских Setup-проектов. Впрочем, эти проекты далеко не идеальны, и как показала практика, куда эффективнее использовать для создания вашего msi бесплатный продукт Windows Installer XML (WIX).


В этой статье я расскажу, как интегрировать WIX в Visual C# Express и научиться создавать с его помощью полномасштабные msi-инсталляторы.

среда, 18 августа 2010 г.

Лицензионный софт

Волна лицензионной одержимости докатилась до меня, и окатила полностью, смыв с диска около 10 гигабайт лишних файлов! Все-таки, полезно иногда разбираться у себя на компе. И место освобождается, и порядка становится больше. А порядок, как известно, - отец эффективности.

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