Показаны сообщения с ярлыком C#. Показать все сообщения
Показаны сообщения с ярлыком C#. Показать все сообщения

четверг, 3 сентября 2009 г.

Fluent Builder

Fluent Interface и Builder - идеальное сочетание для декларативного создания объектов.
На самом деле примеры такого выгодного симбиоза давно у нас под носом, например: StringBuilder.

Я использовал такой симбиоз для декларативного создания SIP аккаунтов и звонков.

Решение состоит из внутренних Builder-классов, которые предоставляют декларативный интерфейс для создания объектов и скрывают детали типа суффиксов транспорта, схемы и пр., о которых не надо задумываться.








Оба этих класса опираются на вспомогательный Builder – SIPUriBuilder. Этот класс настолько интуитивен, что я удивлен, что я не написал его первым делом.



Результат на лицо:


Было:

string remote = "sip:";

remote += txbURI.Text == "00"

? "127.0.0.1"

: (txbURI.Text + "@" + SIPUserAgent.SIPUserAgent.Instance.AccountManager.DefaultAccount.RegistrarUri.Split(new[]{':'})[1]);

remote += SIPUserAgent.SIPUserAgent.Instance.SIPTransport is TCPTransport

? ":5061;transport=TCP"

: "";

SIPUserAgent.SIPUserAgent.Instance.CallManager.MakeCall(remote);


Стало:

Call c = Call.ConstructCall().SetAccount(acc).SetExtension(txbURI.Text).SetDomain(txbURID.Text).Call();


Было:

var acc = new Account(false);

using (acc.CreateInitializationSession())

{

acc.Credential = new NamePasswordCredential

{

Password = txbPass.Text,

Realm = txbRegistrar.Text,

UserName = txbLogin.Text

};

acc.AccountId = "sip:" + txbLogin.Text + "@" + txbRegistrar.Text;

acc.RegistrarUri = "sip:" + txbRegistrar.Text;

if (ua.SIPTransport is TCPTransport)

{

acc.AccountId += "5061;transport=TCP";

acc.RegistrarUri += "5061;transport=TCP";

}

}

ua.AccountManager.RegisterAccount(acc, true);


Стало:

var acc = Account.ConstructAccount().SetLogin(txbLogin.Text).SetPassword(txbPass.Text)
.SetRegistrarDomain(txbRegistrar.Text).Register();


Комментарии я думаю излишни. Просто сравните число строк.

Удачи!

вторник, 3 июня 2008 г.

Handy Monitor wrapper.

Вам никогда не требовалось узнать, стоят ли за текущим потоком в очереди другие потоки на блокировке? Если да, то вы наверняка уже полазили по классу Monitor в поисках свойства, которое бы называлось как-нибудь вроде LockCount или Busy. И тогда-то вы уж точно знаете, что это "конфиденциальная информация"! =)

Ниже я привожу простой и удобный класс-обертку над Monitor, который предоставляет такую информацию совершенно бесплатно. И что самое прекрасное, блокировка также осуществляется с поддержкой языка (я имею ввиду синтаксические конструкции, которые позволяют писать элегантный код). Но есть небольшая разница, если блокировка Monitor осуществляется конструкцией lock(object) {}, то в данной реализации она осуществляется конструкцией using(object){}. Ниже код класса и пример.





Вот пример использования:



Удачи!

P.S. Реализацию я подглядел в недрах какой-то из системных сборок.

пятница, 11 апреля 2008 г.

ConfigurationElement serializing unrecognized attributes

Этот пост будет коротким и будет посвящен простенькой проблеме: сохранение в конфигурационном элементе неопознанных атрибутов.

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

С такой ситуацией я столкнулся разрабатывая инфраструктуру для моего нового проекта. Проблема была решена быстро - достаточно было лишь взглянуть с помощью Reflector на код системы провайдеров ASP.Net, точнее на код класса ProviderSettings. У этого класса есть свойство Parameters типа NameValueCollection, которое магическим образом сериализуется в набор строковых атрибутов элемента. А делается это следующим очень просто (далее код мой). Заполняется коллекция в методе OnDeserializeUnrecognizedAttribute конфигурационного элемента, а сохраняется при помощи создания для каждого вхождения коллекции параметров ConfigurationProperty:


плюс в этом конфигурационном элементе необходимо будет перегрузить свойство Properties.

Делается это не только для того, чтобы добавить свои элементы, но и для оптимизации, т.к. код базового класса составляет коллекцию при помощи Reflection, что довольно медленно в больших классах.
Очень много информации по пространству имен System.Configuration вы можете почерпнуть в следующих статьях:
Удачи!

четверг, 27 марта 2008 г.

Safe event pattern

Рылся в кодах Prism и натолкнулся на вот такой код:

public event EventHandler Updated = delegate { };

я так никогда раньше не писал, но данный паттерн позволяет совершенно не заботится о безопасности вызова и можно смело писать так:

Updated(null, new AccountPositionEventArgs());

вместо:

EventHandler handler = Updated;
if (handler != null)
handler(null, new AccountPositionEventArgs());

так что на заметку.


Удачи!