<?xml version='1.0' encoding="utf-8"?>
      <rss version='2.0'>
      <channel>
      <title>Форум на Исходниках.RU</title>
      <link>https://forum.sources.ru</link>
      <description>Форум на Исходниках.RU</description>
      <generator>Форум на Исходниках.RU</generator>
  	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=268778&amp;view=findpost&amp;p=2452254</guid>
        <pubDate>Thu, 17 Dec 2009 15:42:09 +0000</pubDate>
        <title>Unity Framework</title>
        <link>https://forum.sources.ru/index.php?showtopic=268778&amp;view=findpost&amp;p=2452254</link>
        <description><![CDATA[f.7: <strong class='tag-b'>juice</strong><br>
Привет, я наверное уже не первый, но все таки хочу поблагодарить Тебя(даж зарегился для этого :rolleyes:) за эту статью:<br>
<br>
&quot;Unity Framework, как реализация подмножества AOП&quot;<br>
<br>
очень доходчивое объяснение.<br>
Большое-большое Спасибо&#33;<br>
<br>
Обязательно почитаю все Твои статьи&#33;<br>
 :good:]]></description>
        <author>f.7</author>
        <category>.NET FAQ</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=268778&amp;view=findpost&amp;p=2231735</guid>
        <pubDate>Mon, 30 Mar 2009 20:25:26 +0000</pubDate>
        <title>Unity Framework</title>
        <link>https://forum.sources.ru/index.php?showtopic=268778&amp;view=findpost&amp;p=2231735</link>
        <description><![CDATA[juice: Наверное стоит немного добавить ко всему вышенаписанному, в связи с некоторыми вопросами которые я уже получил. Мне кажется это окажется полезным для всех.<br>
<br>
Первый вопрос прозвучал примерно так: А что если я не хочу создавать точки перехвата посредством аттрибутов? Или я хочу сам сконфигурировать перехват для дебаг версии, а для релиза отключить? Использование потенциально мешает этому. Ответ заключается в том, что можно сконфигурировать политику перехвата обойдясь при этом вообще без использования аттрибутов. Ниже пример runtime настройки для TransparentProxyInterceptor (можно использовать второй пример где используется интерфейс в связке с TransparentProxyInterceptor ):<br>
<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;IUnityContainer container = new UnityContainer(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // создаем контейнер</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;container.RegisterType&#60;IPrinter, Printer&#62;() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // мапим IPrinter на Printer</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.AddNewExtension&#60;Interception&#62;() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// сообщаем контейнеру о том, что собираемся пользоваться соответствующим расширением</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Configure&#60;Interception&#62;() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// разрешаем зависимость на расширения для последующей настройки</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.SetInterceptorFor&#60;IPrinter&#62;(new TransparentProxyInterceptor()) // устанавливаем тип перехватчика для IPrinter</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.AddPolicy(&quot;printerPolicy&quot;) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // добавляем новую политику</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.AddCallHandler(typeof(NullControlHandler)) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // ассоциируем с политикой наш обработчик (политика может содержать множество обработчиков)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.AddMatchingRule(new TypeMatchingRule(typeof(IPrinter))); &nbsp; &nbsp; &nbsp; // добавляем правило согласно с которым для типов которые разрешаются через IPrinter, будет применяться соответствующая политика</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;IPrinter printer = container.Resolve&#60;IPrinter&#62;();</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;printer.Print(null);</div></ol></div></div></div></div><script>preloadCodeButtons('1');</script><br>
<br>
Можем смело удалить аттрибут с метода Print и запустить пример. :)<br>
<br>
Другим вопросом было: Можно ли применять аттрибут не к методу, а к классу? Можно. Равноценно тому, что каждый метод класса был бы помечен аттрибутом.<br>
<br>
Третий вопрос: Для всего ли можно использовать конфигурацию в DesignTime вместо RunTime? Мне кажется, что да :) Покрайней мере я планирую описать процесс конфигурирования Unity в одной из последующих статей.<br>
<br>
Четвертый вопрос: Он плавно вытекает из первого. Можно ли цеплять обработчики не только по типу? Ответ: Можно. Unity предлагает набор предопределенных правил сопоставления по: сборке, аттрибуту, имени члена, сигнатуре метода, пространству имен, типу параметра, свойству, возвращаемому значению, по аттрибуту Tag, типу (TypeMatchingRule использовался при ответе на вопрос 1). Для всех &quot;специальных&quot; ситуаций Unity предлагает создавать кастомные правила посредством реализации IMatchingRule.]]></description>
        <author>juice</author>
        <category>.NET FAQ</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=268778&amp;view=findpost&amp;p=2230945</guid>
        <pubDate>Sun, 29 Mar 2009 19:24:16 +0000</pubDate>
        <title>Unity Framework</title>
        <link>https://forum.sources.ru/index.php?showtopic=268778&amp;view=findpost&amp;p=2230945</link>
        <description><![CDATA[juice: Unity Framework – легковесный, расширяемый, dependency injection контейнер. Одной из его особенностей является поддержка подмножества АОП (Аспектно Ориентированное Программирование). Сегодня я предлагаю, Вам, ознакомиться с этими возможностями. <br>
Прежде чем переходить к технической части, мне бы хотелось рассмотреть простой пример, который продемонстрирует один из вариантов, когда АОП может оказаться полезным в наших приложениях.<br>
<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">using System;</div><div class="code_line">using System.Collections.Generic;</div><div class="code_line">using System.Linq;</div><div class="code_line">using System.Text;</div><div class="code_line">&nbsp;</div><div class="code_line">namespace StandardAproachSample</div><div class="code_line">{</div><div class="code_line">&nbsp;&nbsp; &nbsp;public class Printer</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public virtual void Print(string line)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (line == null)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;throw new ArgumentNullException(&quot;line&quot;);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(line);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(&quot;Was written {0} symbols&quot;, line.Length);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;class Program</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;static void Main(string[] args)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Printer printer = new Printer();</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;printer.Print(null);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">}</div></ol></div></div></div></div><br>
<br>
Часто ли Вы видели код подобный методу Print класса Printer? Я наблюдаю его ежедневно от метода к методу. Проверять приходящие параметры на null, является общепринятой практикой. И даже если мы не всегда делаем это в каждом методе, то на верхнем уровне, с которым взаимодействует клиент нашего кода это является обыденностью. <br>
Если бы методы всегда принимали единственный параметр ссылочного типа или наши приложения содержали бы единственный метод, принимающий такие параметры, проблем бы вероятно не возникало. Но признаюсь по секрету, что написания таких проверок для меня является настоящей тягостью. Что может быть скучнее в программирование, чем рутинное, монотонное написание однотипного кода? Более того такой код «засоряет» наши методы добавляя в бизнес логику инфраструктурный код. А часто ли вы пользуетесь логированием? Предположу, что каждый когда-нибудь да пользовался. Необходимая и полезная функциональность, относящаяся к подсистеме логирования или трассировки пересыпает собой нашу бизнес логику. В лучшем случае просто фиксируя факт вызова, а в особо «тяжелых» случаях трассируются алгоритмы, параметры методов, результаты выполнения, контексты вызовов и безопасности … Вот если бы …<br>
Немного пофантазировав, без труда можно было бы представить идеальное решение для такого кода. Вероятно, это будет, нечто похожее вот на это:<br>
<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp;public class Printer</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;[NullControl]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public void Print(string line)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(line);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(&quot;Was written {0} symbols&quot;, line.Length);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div></ol></div></div></div></div><br>
<br>
Решение: некий «волшебный» атрибут, применив который к любому методы, мы получаем автоматическую проверку параметров на null, а также генерирование соответствующего исключения ArgumentNullException говорящего нам, какой именно параметр привел к его возникновению.  <br>
Мы могли бы попытаться самостоятельно решить этот вопрос. Решение находится практически на поверхности и его реализация пролегает, через паттерн Proxy. Для начала нужно было бы реализовать динамическую генерацию proxy классов для регистрируемых типов и пользоваться локатором  для их (proxy) инстанцирования. Сгенерированный proxy объект мог бы выполнить соответствующие проверки и сгенерировать в случае надобности исключение. Проверки могли бы быть вынесены в некий аспект ассоциируемый с целевым типом посредством атрибута. Другое возможное решение это использовать классы которые получают proxy классы на основе самой инфраструктуры .NET Framework, тут можно было бы воспользоваться функциональностью предоставляемой объектами наследующими MarshalByRefObject или его потомка ContextBoundObject. Далее путь путем обращения к ним через TransparentProxy. Все эти решения по-своему хороши, как и не лишены недостатков по отдельности. Первое предполагает написание приличного объема кода, в противном случае решение окажется не универсальным, а второе накладывает заведомые ограничения и не может считаться «производительным» решением.<br>
<br>
Помечтаем еще? Вот если бы … была бы библиотека, которая совмещает оба подхода, да еще дает, что нибудь в довесок … и если бы имела открытый исходный код, да обладала документацией свойственной платным аналогам и была бы написана сотрудниками Microsoft … Фантастика?&#33; Unity нам предлагает все это за бесплатно&#33; Сверх того, как было упомянуто выше, это лишь только часть ее возможностей. Вот об этой самой части мы с Вами будем говорить подробней.<br>
<br>
Что нам понадобится? Во первых загрузить Unity: http://www.microsoft.com/downloads/details.aspx?FamilyId=2C8B79E7-AE56-4F90-822E-A1E43C49D12E&displaylang=en<br>
Во вторых разобраться с основными принципами работы.<br>
 <br>
Контейнер Unity имеет соответствующие настройки которые позволяют указать ему, что мы хотим воспользоваться его возможностями по перехвату обращений к объекту. После чего мы инстанцируем объекты посредством Unity, и вызываем их соответствующие методы. В действительности Unity возвращает прокси объект который перехватывает все обращения к действительному экземпляру класса и перенаправляет их в специальный обработчик написанный нами. В примере с классом Printer это может быть код, который проверяет параметры метода на Null и генерирует соответствующие исключение. В дополнение Unity предлагает поддержку атрибутов, которые позволят нам связать обработчик с методами, требующими соответствующую проверку. Перед демонстрацией примеров использования я должен упомянуть, что существует два типа перехватчиков (объекты создающие прокси) обращений, первый основан на том, что прокси объект выводится на основе экземпляра объекта, а второй на основе его типа. Что бы лучше понять разницу можно вспомнить как .NET Framework создает TransperantProxy. Для того, что бы инфраструктура создала прокси объект ей требуется ссылка на экземпляр. Примером прокси основанного на типе, может быть реализация NHibernate, который требует от нас объявлять свойства объектов который мы будем мапить виртуальными. Это необходимо для того, что бы библиотека могла динамически создать прокси объект путем переопределения соответствующих виртуальных свойств.<br>
<br>
Unity поддерживает оба типа перехватчиков. В нашем с вами распоряжении имеется два экземплярных перехватчика и один перехватчик на основе типов.<br>
Приступим к примерам.<br>
<br>
<strong class='tag-b'>TransparentProxyInterceptor</strong> - первый тип перехватчика<br>
<br>
Воспользуемся для примера классом Printer, приведенным выше:<br>
<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp;public class Printer</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public void Print(string line)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(line);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(&quot;Was written {0} symbols&quot;, line.Length);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div></ol></div></div></div></div><br>
<br>
В этом сценарии Unity создаст прокси, путем взаимодействия с инфраструктурой .NET Transparent/RealProxy. Его можно использовать если тип наследует MarshalByRefObject (ContextBoundObject) или же когда перехватываются только методы класса реализующие соответствующий интерфейс. Сразу рассмотрим первый случай. <br>
<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp;public class Printer : ContextBoundObject</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public void Print(string line)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(line);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(&quot;Was written {0} symbols&quot;, line.Length);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div></ol></div></div></div></div><br>
<br>
Теперь нам необходимо написать обработчик. Тут все просто нам нужен класс который реализует ICallHandler интерфейс. Ниже пример реализации такого обработчика. В нашем случае он должен проверить параметры на null и в случае необходимости сгенерировать исключение.<br>
<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;public class NullControlHandler : ICallHandler</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;for (int i = 0; i &#60; input.Arguments.Count; ++i)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (input.Arguments[i] == null)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ParameterInfo parameterInfo = input.Arguments.GetParameterInfo(i);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ArgumentNullException ex = new ArgumentNullException(parameterInfo.Name);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return input.CreateExceptionMethodReturn(ex);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return getNext()(input, getNext);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public int Order</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;get;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;set;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div></ol></div></div></div></div><br>
<br>
При обращению к методу Print прокси объект делегирует свою работу соответствующему обработчику. Из парамметров метода мы может получить всю необходимую информацию об аргументах. Т.к. обработчиков может быть много, напрмиер один проверяющий аргументы на null, а второй производящий логирование соответствующего метода, нам нужно вызывать их по цепочке, пока мы не получим результат выполнения который будет возвращен прокси и преобразован им в результат вызова метода. Если не говорить заумно, то до строки getNext()(input, getNext); мы можем писать код который должен выполниться перед непосредственным вызовом метода с аргументами (в нашем случае организовать проверки и при надобности сгенерировать исключение) или модифицировать парамметры вобщем любую необходимую работу, а после вызова метода мы вольны модифицировать результат (или просто вернуть его), выполнить нужную нам работу (к примеру записать в лог сообщение о том, что метод был успешно вызыван и.т.д.).<br>
<br>
Реализуем аттрибут. Нет ничего тривиальней:<br>
<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp;public class NullControlAttribute : HandlerAttribute</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public override ICallHandler CreateHandler(IUnityContainer container)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return new NullControlHandler();</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div></ol></div></div></div></div><br>
<br>
Переопределяем метод CreateHandler возвращая соответствующий экземпляр.<br>
<br>
Осталось применить аттрибут к методу Print:<br>
<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;[NullControl]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public void Print(string line)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(line);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(&quot;Was written {0} symbols&quot;, line.Length);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div></ol></div></div></div></div><br>
<br>
После этого все готово к тестированию:<br>
<br>
 <div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; class Program</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;static void Main(string[] args)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Создаем контейнер</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;IUnityContainer container = new UnityContainer();</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Регистрируем тип Printer, указываем Unity, хотим использовать перехватчик</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Указываем, что для получения прокси для Printer собираемся использовать TransparentProxyInterceptor </div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;container.RegisterType&#60;Printer&#62;();</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;container.AddNewExtension&#60;Interception&#62;()</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Configure&#60;Interception&#62;()</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.SetInterceptorFor&#60;Printer&#62;(new TransparentProxyInterceptor());</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Получаем прокси</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Printer printer = container.Resolve&#60;Printer&#62;();</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Наслаждаемся результатом</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;printer.Print(null);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div></ol></div></div></div></div><br>
<br>
<div class='tag-quote'><span class='tag-quote-prefix'>Цитата</span> <div class='quote '>Результат:<br>
<br>
Unhandled Exception: System.ArgumentNullException: Value cannot be null.<br>
Parameter name: line</div></div><br>
<br>
Тут можно заметить, что всю настройку мы можем выполнять в конфигурационных файлах, но конфигурирование Unity в DisignTime тема отдельной статьи.<br>
<br>
Рассмотрим второй сценарий применения TransparentProxyIntercepotor. Предположим, что у нас есть класс вида:<br>
<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp;public class Printer : IPrinter</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;[NullControl]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public void Print(string line)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(line);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(&quot;Was written {0} symbols&quot;, line.Length);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div></ol></div></div></div></div><br>
<br>
, где<br>
<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp;public interface IPrinter</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;void Print(string line);</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div></ol></div></div></div></div><br>
<br>
Немного изменив реализацию метода Main мы добъемся того, что сможем использовать TransparentProxyInterceptor для перехвата обращений к методам являющимися реализацией интерфейса IPrinter.<br>
<br>
В заключение разговора о TransparentProxyInterceptor, просто необходимо описать некоторые особености данного перехватчика. К его достоинствам относится то, что мы можем перехватывать с его помощью обращения к виртуальным, не виртуальным и интерфейсным методам, а к недостаткам можно отнести неторопливость, а также требование использовать MarshalByRefObject в качестве базового типа (в противном случае мы можем перехватывать только методы объявленные в интерфейсе).<br>
<br>
<strong class='tag-b'>InterfaceInterceptor</strong><br>
Рассмотрим еще один перехватчик предоставляемый нам Unity. Это еще один перехватчик на основе экземпляров, но существенным отличием от упомянутого TransparentProxyInterceptor является то, что он для построения прокси использует динамическую генерацию кода. Его удобно использовать в тех случаях когда мы мапим типы на интерфейсы с использованием Unity, так как мы делали в во втором примере для  TransparentProxyInterceptor. Код будет отличаться только типом перехватчика указываемого Unity,  при настройке. Для удобства я привожу полный код примера ниже:<br>
<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">using System;</div><div class="code_line">using System.Collections.Generic;</div><div class="code_line">using System.Linq;</div><div class="code_line">using System.Text;</div><div class="code_line">using System.Reflection;</div><div class="code_line">using Microsoft.Practices.Unity;</div><div class="code_line">using Microsoft.Practices.Unity.InterceptionExtension;</div><div class="code_line">&nbsp;</div><div class="code_line">namespace InterfaceInterceptorSample</div><div class="code_line">{</div><div class="code_line">&nbsp;&nbsp; &nbsp;public interface IPrinter</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;void Print(string line);</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;public class Printer : IPrinter</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;[NullControl]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public void Print(string line)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(line);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(&quot;Was written {0} symbols&quot;, line.Length);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;public class NullControlHandler : ICallHandler</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;for (int i = 0; i &#60; input.Arguments.Count; ++i)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (input.Arguments[i] == null)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ParameterInfo parameterInfo = input.Arguments.GetParameterInfo(i);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ArgumentNullException ex = new ArgumentNullException(parameterInfo.Name);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return input.CreateExceptionMethodReturn(ex);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return getNext()(input, getNext);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public int Order</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;get;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;set;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;public class NullControlAttribute : HandlerAttribute</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public override ICallHandler CreateHandler(Microsoft.Practices.Unity.IUnityContainer container)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return new NullControlHandler();</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;class Program</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;static void Main(string[] args)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;IUnityContainer container = new UnityContainer();</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;container.RegisterType&#60;IPrinter, Printer&#62;();</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;container.AddNewExtension&#60;Interception&#62;()</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Configure&#60;Interception&#62;()</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.SetInterceptorFor&#60;IPrinter&#62;(new InterfaceInterceptor());</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;IPrinter printer = container.Resolve&#60;IPrinter&#62;();</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;printer.Print(null);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">}</div></ol></div></div></div></div><br>
<br>
<div class='tag-quote'><span class='tag-quote-prefix'>Цитата</span> <div class='quote '>Результат:<br>
<br>
Unhandled Exception: System.ArgumentNullException: Value cannot be null.<br>
Parameter name: line</div></div><br>
<br>
<br>
Как я и обещал отличия в коде не существенные. Думаю даже из названия понятно, что перехватывать мы можем только интерфейсные методы.<br>
<br>
<strong class='tag-b'>VirtualMethodInterceptor</strong><br>
Третий тип перехватчика, как и для InterfaceInterceptor, используется динамическая генерация кода, тем не менее он строит прокси отталкиваясь от типа. Этот перехватчик перехватывает обращения к виртуальным методам, что накладывает на нас требования делать все методы которые мы желаем перехватить виртуальными. <br>
<br>
 <div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; public class Printer</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;[NullControl]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public virtual void Print(string line)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(line);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(&quot;Was written {0} symbols&quot;, line.Length);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div></ol></div></div></div></div><br>
<br>
Настройка перехватчика подобна первому примеру для TransparentProxyIntercepotor:<br>
<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;IUnityContainer container = new UnityContainer();</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;container.RegisterType&#60;Printer&#62;();</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;container.AddNewExtension&#60;Interception&#62;()</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Configure&#60;Interception&#62;()</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.SetInterceptorFor&#60;Printer&#62;(new VirtualMethodInterceptor());</div></ol></div></div></div></div><br>
<br>
После вызова метода Print c нулевым аргументом мы увидим уже знамое, по предыдущим примерам сообщение.<br>
<br>
В заключение прошу заметить, что использование обработчиков Unity не ограничивается только обработкой исключений. Вы можете реализовать с их помощью любой «сквозной» функционал в вашей программе. Это может быть логирование или преобразование возвращаемых методом результатов, обработка транзакций или встаивание инструментального кода.<br>
<br>
В следующий раз я обязательно напишу и о других замечательных особеностях Unity контейнера о реализации паттернов Inversion of Сontrol и DependencyInjection в ваших приложениях.<br>
<br>
До новых встреч.]]></description>
        <author>juice</author>
        <category>.NET FAQ</category>
      </item>
	
      </channel>
      </rss>
	