<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">

<channel>
	<title>butaji</title>
	
	<link>http://butaji.wordpress.com</link>
	<description>the story of my tech.life</description>
	<lastBuildDate>Mon, 16 Nov 2009 06:58:18 +0000</lastBuildDate>
	<generator>http://wordpress.com/</generator>
	<language>ru</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<cloud domain="butaji.wordpress.com" port="80" path="/?rsscloud=notify" registerProcedure="" protocol="http-post" />
<image>
		<url>http://www.gravatar.com/blavatar/6856b88d19cbdf2f36d9068eac0fec8a?s=96&amp;d=http://s.wordpress.com/i/buttonw-com.png</url>
		<title>butaji</title>
		<link>http://butaji.wordpress.com</link>
	</image>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/Butaji" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
		<title>Как подружить ASP.NET Controls и DI-контейнер</title>
		<link>http://butaji.wordpress.com/2009/11/16/%d0%ba%d0%b0%d0%ba-%d0%bf%d0%be%d0%b4%d1%80%d1%83%d0%b6%d0%b8%d1%82%d1%8c-asp-net-controls-%d0%b8-di-%d0%ba%d0%be%d0%bd%d1%82%d0%b5%d0%b9%d0%bd%d0%b5%d1%80/</link>
		<comments>http://butaji.wordpress.com/2009/11/16/%d0%ba%d0%b0%d0%ba-%d0%bf%d0%be%d0%b4%d1%80%d1%83%d0%b6%d0%b8%d1%82%d1%8c-asp-net-controls-%d0%b8-di-%d0%ba%d0%be%d0%bd%d1%82%d0%b5%d0%b9%d0%bd%d0%b5%d1%80/#comments</comments>
		<pubDate>Mon, 16 Nov 2009 06:58:18 +0000</pubDate>
		<dc:creator>butaji</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[IoC]]></category>
		<category><![CDATA[Sapphire]]></category>
		<category><![CDATA[sharepoint]]></category>
		<category><![CDATA[AOP]]></category>
		<category><![CDATA[dependency injection]]></category>
		<category><![CDATA[Microsoft Unity]]></category>
		<category><![CDATA[Unity]]></category>
		<category><![CDATA[Unity Interception]]></category>

		<guid isPermaLink="false">http://butaji.wordpress.com/2009/11/16/%d0%ba%d0%b0%d0%ba-%d0%bf%d0%be%d0%b4%d1%80%d1%83%d0%b6%d0%b8%d1%82%d1%8c-asp-net-controls-%d0%b8-di-%d0%ba%d0%be%d0%bd%d1%82%d0%b5%d0%b9%d0%bd%d0%b5%d1%80/</guid>
		<description><![CDATA[Интро
В последнее время решил немного освежить свои знания в ASP.NET, в связи с чем углубился в процессы генерации кода контролов по разметке (*.ascx, *.aspx) и обнаружил что можно делать очень интересные решения, о которых&#160; о хочу поведать. Итак сегодня мы узнаем, как подружить наш Dependency Injection контейнер с генерируемым контролами кодом.
Поехали
 
В качестве DI-контейнера будет [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=butaji.wordpress.com&blog=4404897&post=623&subd=butaji&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><h4>Интро</h4>
<p>В последнее время решил немного освежить свои знания в ASP.NET, в связи с чем углубился в процессы генерации кода контролов по разметке (*.ascx, *.aspx) и обнаружил что можно делать очень интересные решения, о которых&#160; о хочу поведать. Итак сегодня мы узнаем, как подружить наш Dependency Injection контейнер с генерируемым контролами кодом.</p>
<h4>Поехали</h4>
<p><a href="http://butaji.files.wordpress.com/2009/11/dependencyinjection_solution1.gif"><img style="display:inline;margin-left:0;margin-right:0;border-width:0;" title="DependencyInjection_Solution[1]" border="0" alt="DependencyInjection_Solution[1]" align="right" src="http://butaji.files.wordpress.com/2009/11/dependencyinjection_solution1_thumb.gif?w=244&#038;h=136" width="244" height="136" /></a> </p>
<p>В качестве DI-контейнера будет выступать <a href="http://www.codeplex.com/unity/">Microsoft Unity</a>, но это не принципиально, всё что будет касаться DI не зависит от используемого контейнера.</p>
<p>Проблема состоит в следующем – есть некоторый ASP.NET Control, в который мы хотим внедрит зависимости, а так же воспользоваться услугами Service Locator’а для управления интересующими нас зависимостями.</p>
<p>В Microsoft Unity есть некоторые средства для того, чтобы сделать это не прилагая особенных усилий: мы можем произвести инъекцию в свойство элемента управления, нас интересующее примерно следующим образом:</p>
<ol>
<li>Отметить атрибутом Dependency необходимое свойство
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:78bff771-7f66-4569-8222-dc362ddd8152" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<font color="#AA22FF"><b>public</b></font>&#160;<font color="#AA22FF"><b>class</b></font>&#160;<font color="#0000FF">MyControl</font>&#160;:&#160;UserControl<br />
<font color="#AA22FF"><b>{</b></font><br />
<font color="#BB4444">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[Dependency]</font><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>public</b></font>&#160;MyPresenter&#160;Presenter<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>{</b></font><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>get</b></font>&#160;<font color="#AA22FF"><b>{</b></font>&#160;<font color="#AA22FF"><b>return</b></font>&#160;_presenter;&#160;<font color="#AA22FF"><b>}</b></font><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>set</b></font><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>{</b></font><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;_presenter&#160;=&#160;<font color="#AA22FF"><b>value</b></font>;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;_presenter.View&#160;=&#160;<font color="#AA22FF"><b>this</b></font>;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>}</b></font><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>}</b></font><br />
<font color="#AA22FF"><b>}</b></font>
</div>
</div>
</li>
<li>
<p>Проинициализировать элемент управления можно следующим образом</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:6c6f0d5b-933b-41e2-bc16-d864c19e9be0" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<font color="#AA22FF"><b>protected</b></font>&#160;<font color="#AA22FF"><b>override</b></font>&#160;<font color="#AA22FF"><b>void</b></font>&#160;<font color="#00A000">OnInit</font>(EventArgs&#160;e)<br />
<font color="#AA22FF"><b>{</b></font><br />
&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>base</b></font>.OnInit(e);<br />
&#160;&#160;&#160;&#160;_сontainer.BuildUp(GetType(),&#160;<font color="#AA22FF"><b>this</b></font>);<br />
<font color="#AA22FF"><b>}</b></font>&#160;
</div>
</div>
</li>
<li>
<p>Позаботиться о местоположении контейнера в вашем приложении, я предлагаю использовать для этого <a href="http://github.com/butaji/Sapphire/blob/master/trunk/Sapphire.Application/Application.cs">HttpApplication</a>, унаследовавшись от которого и произведя небольшие модификации файла <a href="http://github.com/butaji/Sapphire/blob/master/trunk/Sapphire.Application/global.asax">global.asax</a> мы получаем необходимое нам хранилище для контейнера, обращаться с ним необходимо примерно следующим образом</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:cc7df713-8f54-4130-83ef-7972154d3b36" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
((Sapphire.Application)HttpContext.Current.ApplicationInstance).Container
</div>
</div>
</li>
</ol>
<p>Решение вполне пригодное, однако пуристические воззрения не дают оставить решение на данной стадии, и думаю, что просто необходимо заменить инъекцию свойства на инъекцию в конструктор, тем более подобный подход – это далеко не то, что мы можем выжать из Unity.</p>
<p>Т.е. наш интерес состоит в том, чтобы класс MyUserControl выглядел примерно так (думаю сборщику страницы это не совсем понравится)</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:ccd9ee48-feee-49f0-b31d-ca9b07854fcc" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<font color="#AA22FF"><b>public</b></font>&#160;<font color="#AA22FF"><b>class</b></font>&#160;<font color="#0000FF">MyControl</font>&#160;:&#160;UserControl<br />
<font color="#AA22FF"><b>{</b></font><br />
&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>public</b></font>&#160;<font color="#00A000">MyControl</font>(MyPresenter&#160;presenter)<br />
&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>{</b></font><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;_presenter&#160;=&#160;presenter;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;_presenter.View&#160;=&#160;<font color="#AA22FF"><b>this</b></font>;<br />
&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>}</b></font><br />
<font color="#AA22FF"><b>}</b></font>
</div>
</div>
<p>Предлагаю этим и заняться. Начнём с того, что у элементов управления, описанных в разметке страницы, при генерации страницы указываются их конструкторы без параметров, интересно, как можно управлять данным процессом, первоначально, покопавшись в web.config я предполагал сделать это через: </p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:3a7af6de-6c18-4e7e-b637-38d1e616e95a" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<font color="#008000"><b>&lt;buildProviders&gt;</b></font><br />
&#160;&#160;&#160;&#160;<font color="#008000"><b>&lt;add</b></font>&#160;<font color="#BB4444">extension=</font><font color="#BB4444">&laquo;.aspx&raquo;</font>&#160;<font color="#BB4444">type=</font><font color="#BB4444">&laquo;System.Web.Compilation.PageBuildProvider&raquo;</font><font color="#008000"><b>/&gt;</b></font><br />
&#160;&#160;&#160;&#160;<font color="#008000"><b>&lt;add</b></font>&#160;<font color="#BB4444">extension=</font><font color="#BB4444">&laquo;.ascx&raquo;</font>&#160;<font color="#BB4444">type=</font><font color="#BB4444">&laquo;System.Web.Compilation.UserControlBuildProvider&raquo;</font><font color="#008000"><b>/&gt;</b></font><br />
&#160;&#160;&#160;&#160;&#8230;<br />
<font color="#008000"><b>&lt;/buildProviders&gt;</b></font>
</div>
</div>
<p>Однако реализация своего PageBuildProvider’а – довольно серьезное занятие, думаю отложить это для серьезной на то необходимости. Однако благодаря BuildProvider’ам можно генерить к примеру слой доступа к данным, для этого надо:</p>
<p>Написать и зарегестрировать обработчик для какого-нибудь своего расширения, к примеру *.dal и сделать что-нибудь наподобее <a href="http://www.codeproject.com/KB/aspnet/DALComp.aspx">http://www.codeproject.com/KB/aspnet/DALComp.aspx</a></p>
<p>кстати подобная логика реализована в SubSonic <a href="http://dotnetslackers.com/articles/aspnet/IntroductionToSubSonic.aspx">http://dotnetslackers.com/articles/aspnet/IntroductionToSubSonic.aspx</a></p>
<p>так же интересная реализация наследования страницы от generic типов <a title="http://stackoverflow.com/questions/1480373/generic-inhertied-viewpage-and-new-property" href="http://stackoverflow.com/questions/1480373/generic-inhertied-viewpage-and-new-property">http://stackoverflow.com/questions/1480373/generic-inhertied-viewpage-and-new-property</a></p>
<p>ещё можно, к примеру генерировать исключения, объекты передачи данных и многое другое, ограничением является лишь ваша фантазия.</p>
<p>Вообщем, данный вариант нам не подходит, необходимо сделать что-нибудь проще, и есть отличное решение, с помощью атрибута ControlBuilder мы можем указать свою логику сборки элемента управления из разметки, это будет выглядеть примерно так</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:67858728-23e4-49d7-8872-1090741c3a32" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<font color="#BB4444">[ControlBuilder(typeof(MyControlBuilder))]</font><br />
<font color="#AA22FF"><b>public</b></font>&#160;<font color="#AA22FF"><b>class</b></font>&#160;<font color="#0000FF">UserControl</font>&#160;:&#160;System.Web.UI.UserControl<br />
<font color="#AA22FF"><b>{</b></font><br />
<font color="#AA22FF"><b>}</b></font>
</div>
</div>
<p>Теперь разберемся с реализацией&#160; MyControlBuilder, этот тип должен наследовать от ControlBuilder и с помощью перегрузки ProcessGeneratedCode мы с вами сможем указать сборщику на необходимость использования нашего кода вместо вызова конструктора без атрибутов элемента управления:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:201bf84e-336c-4c96-8c41-ba2375b0820a" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>public</b></font>&#160;<font color="#AA22FF"><b>override</b></font>&#160;<font color="#AA22FF"><b>void</b></font>&#160;<font color="#00A000">ProcessGeneratedCode</font>(CodeCompileUnit&#160;codeCompileUnit,<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;CodeTypeDeclaration&#160;baseType,<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;CodeTypeDeclaration&#160;derivedType,<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;CodeMemberMethod&#160;buildMethod,<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;CodeMemberMethod&#160;dataBindingMethod)<br />
&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>{</b></font><br />
&#160;&#160;&#160;&#160;&#160;&#160;codeCompileUnit.Namespaces[<font color="#666666">0</font>].Imports.Add(<font color="#AA22FF"><b>new</b></font>&#160;CodeNamespaceImport(<font color="#BB4444">&laquo;Sapphire.Web.UI&raquo;</font>));<br />
&#160;&#160;&#160;&#160;&#160;&#160;ReplaceConstructorWithContainerResolveMethod(buildMethod);<br />
&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>base</b></font>.ProcessGeneratedCode(codeCompileUnit,&#160;baseType,&#160;derivedType,&#160;buildMethod,&#160;dataBindingMethod);<br />
&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>}</b></font>
</div>
</div>
<p>самое интересно скрывает метод ReplaceConstructorWithContainerResolveMethod </p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:742b123c-c0b8-48de-9e0f-0e0914be7bc5" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>private</b></font>&#160;<font color="#AA22FF"><b>void</b></font>&#160;<font color="#00A000">ReplaceConstructorWithContainerResolveMethod</font>(CodeMemberMethod&#160;buildMethod)<br />
&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>{</b></font><br />
&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>foreach</b></font>&#160;(CodeStatement&#160;statement&#160;<font color="#AA22FF"><b>in</b></font>&#160;buildMethod.Statements)<br />
&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>{</b></font><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;var&#160;assign&#160;=&#160;statement&#160;<font color="#AA22FF"><b>as</b></font>&#160;CodeAssignStatement;</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>if</b></font>&#160;(<font color="#AA22FF"><b>null</b></font>&#160;!=&#160;assign)<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>{</b></font><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;var&#160;constructor&#160;=&#160;assign.Right&#160;<font color="#AA22FF"><b>as</b></font>&#160;CodeObjectCreateExpression;</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>if</b></font>&#160;(<font color="#AA22FF"><b>null</b></font>&#160;!=&#160;constructor)<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>{</b></font><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;assign.Right&#160;=<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>new</b></font>&#160;<font color="#00A000">CodeSnippetExpression</font>(<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<font color="#00BB00"><b>string</b></font>.Format(<font color="#BB4444">&laquo;SapphireControlBuilder.Build&lt;{0}&gt;()&raquo;</font>,<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;ControlType.FullName));<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>break</b></font>;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>}</b></font><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>}</b></font><br />
&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>}</b></font><br />
&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>}</b></font>
</div>
</div>
<p>следуя по коду можно обратить внимание, что он заменяет вызов конструктора на вызов генерик-метода Build, в котором мы и обратимся к нашему контейнеру с просьбой вызвать наш элемент управления и проинициализировать его конструктор необходимыми зависимостями.</p>
<p>Однако это ещё не решении задания, т.к. есть метод динамической загрузки элемента управления Page.LoadControl(), для него придётся написать свой вариант</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:12b0b2e2-a28f-4b65-a35f-6e09cc01a770" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
&#160;&#160;<font color="#AA22FF"><b>public</b></font>&#160;<font color="#AA22FF"><b>static</b></font>&#160;<font color="#AA22FF"><b>class</b></font>&#160;<font color="#0000FF">PageExtensions</font><br />
&#160;&#160;<font color="#AA22FF"><b>{</b></font><br />
&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>public</b></font>&#160;<font color="#AA22FF"><b>static</b></font>&#160;UserControl&#160;<font color="#00A000">LoadAndBuildUpControl</font>(<font color="#AA22FF"><b>this</b></font>&#160;Page&#160;page,&#160;<font color="#00BB00"><b>string</b></font>&#160;virtualPath)<br />
&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>{</b></font><br />
&#160;&#160;&#160;&#160;&#160;&#160;var&#160;control&#160;=&#160;page.LoadControl(virtualPath);<br />
&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>return</b></font>&#160;SapphireControlBuilder.Build&lt;UserControl&gt;(control.GetType());<br />
&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>}</b></font><br />
&#160;&#160;<font color="#AA22FF"><b>}</b></font>
</div>
</div>
<p>Вот мы и справились с поставленной задачей, однако это ещё не всё. А почему теперь не воспользоваться всеми преимуществами Unity, и не внедрить в наш элемент управления <a href="http://habrahabr.ru/blogs/net/50845/">AOP времени исполнения</a> с помощью <a href="http://msdn.microsoft.com/en-us/library/dd140045.aspx">Unity Interception</a>.</p>
<p>К примеру мы можем сделать следующее </p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:8f3bc656-82a3-4044-971c-c7bfdc000756" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<font color="#AA22FF"><b>public</b></font>&#160;<font color="#AA22FF"><b>class</b></font>&#160;<font color="#0000FF">MyControl</font>&#160;:&#160;UserControl<br />
<font color="#AA22FF"><b>{</b></font><br />
<font color="#BB4444">&#160;&#160;&#160;&#160;[HandleException]</font><br />
&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>public</b></font>&#160;<font color="#AA22FF"><b>override</b></font>&#160;<font color="#AA22FF"><b>void</b></font>&#160;<font color="#00A000">DataBind</font>()<br />
&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>{</b></font><br />
&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>base</b></font>.DataBind();<br />
&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>}</b></font><br />
<font color="#AA22FF"><b>}</b></font>
</div>
</div>
<p>Это будет означать, что обработка исключений должна добавляться на лету, к тому ж предоставляя нам возможность её изменения во время исполнения, для начала пусть её реализация будет примерно следующая</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:b531ecfa-a7e4-4e58-832b-d666bfdd8aba" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<font color="#BB4444">&#160;&#160;[AttributeUsage(AttributeTargets.Method&#160;|&#160;AttributeTargets.Property,&#160;AllowMultiple&#160;=&#160;false,&#160;Inherited&#160;=&#160;true)]</font><br />
&#160;&#160;<font color="#AA22FF"><b>public</b></font>&#160;<font color="#AA22FF"><b>class</b></font>&#160;<font color="#0000FF">HandleExceptionAttribute</font>&#160;:&#160;HandlerAttribute<br />
&#160;&#160;<font color="#AA22FF"><b>{</b></font><br />
&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>public</b></font>&#160;<font color="#AA22FF"><b>override</b></font>&#160;ICallHandler&#160;<font color="#00A000">CreateHandler</font>(IUnityContainer&#160;container)<br />
&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>{</b></font><br />
&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>return</b></font>&#160;<font color="#AA22FF"><b>new</b></font>&#160;<font color="#00A000">ExceptionHandler</font>();<br />
&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>}</b></font><br />
&#160;&#160;<font color="#AA22FF"><b>}</b></font></p>
<p>&#160;&#160;<font color="#AA22FF"><b>public</b></font>&#160;<font color="#AA22FF"><b>class</b></font>&#160;<font color="#0000FF">ExceptionHandler</font>&#160;:&#160;ICallHandler<br />
&#160;&#160;<font color="#AA22FF"><b>{</b></font><br />
&#160;&#160;&#160;&#160;<font color="#008800"><i>///&#160;&lt;exception&#160;cref=&raquo;SapphireUserFriendlyException&raquo;&gt;&lt;c&gt;SapphireUserFriendlyException&lt;/c&gt;.&lt;/exception&gt;<br />
</i></font>&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>public</b></font>&#160;IMethodReturn&#160;<font color="#00A000">Invoke</font>(IMethodInvocation&#160;input,&#160;GetNextHandlerDelegate&#160;getNext)<br />
&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>{</b></font><br />
&#160;&#160;&#160;&#160;&#160;&#160;var&#160;result&#160;=&#160;getNext()(input,&#160;getNext);<br />
&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>if</b></font>&#160;(result.Exception&#160;==&#160;<font color="#AA22FF"><b>null</b></font>)<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>return</b></font>&#160;result;<br />
&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>throw</b></font>&#160;<font color="#AA22FF"><b>new</b></font>&#160;<font color="#00A000">SapphireUserFriendlyException</font>();<br />
&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>}</b></font></p>
<p>&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>public</b></font>&#160;<font color="#00BB00"><b>int</b></font>&#160;Order&#160;<font color="#AA22FF"><b>{</b></font>&#160;<font color="#AA22FF"><b>get</b></font>;&#160;<font color="#AA22FF"><b>set</b></font>;&#160;<font color="#AA22FF"><b>}</b></font><br />
&#160;&#160;<font color="#AA22FF"><b>}</b></font>
</div>
</div>
<p>Ну и конечно же надо сконфигурировать контейнер для создания наших прокси-обработчиков</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:611e9f53-0255-4366-a483-321e39472de5" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>public</b></font>&#160;<font color="#AA22FF"><b>static</b></font>&#160;T&#160;Build&lt;T&gt;()<br />
&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>{</b></font><br />
&#160;&#160;&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>return</b></font>&#160;(T)((Application)HttpContext.Current.ApplicationInstance)<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;.Container<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;.&#160;AddNewExtension&lt;Interception&gt;()<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;.Configure&lt;Interception&gt;()<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;.SetInterceptorFor&lt;T&gt;(<font color="#AA22FF"><b>new</b></font>&#160;VirtualMethodInterceptor())<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;.Container<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;.Resolve&lt;T&gt;();<br />
&#160;&#160;&#160;&#160;<font color="#AA22FF"><b>}</b></font>
</div>
</div>
<h4>Ресурсы</h4>
<p><a href="http://www.slideshare.net/butaji/sapphire-2256588">Sapphire.Application</a> – для чего всё это реализовывалось <a href="http://github.com/butaji/Sapphire/tree/master/trunk/Sapphire.Application/">http://github.com/butaji/Sapphire/tree/master/trunk/Sapphire.Application/</a></p>
<p>Дэвид предлагает реализации связывания с данными следующего поколения “Databinding 3.0” на основе аналогичного подхода <a href="http://weblogs.asp.net/davidfowler/archive/2009/11/13/databinding-3-0.aspx">http://weblogs.asp.net/davidfowler/archive/2009/11/13/databinding-3-0.aspx</a></p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/butaji.wordpress.com/623/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/butaji.wordpress.com/623/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/butaji.wordpress.com/623/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/butaji.wordpress.com/623/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/butaji.wordpress.com/623/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/butaji.wordpress.com/623/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/butaji.wordpress.com/623/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/butaji.wordpress.com/623/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/butaji.wordpress.com/623/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/butaji.wordpress.com/623/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=butaji.wordpress.com&blog=4404897&post=623&subd=butaji&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://butaji.wordpress.com/2009/11/16/%d0%ba%d0%b0%d0%ba-%d0%bf%d0%be%d0%b4%d1%80%d1%83%d0%b6%d0%b8%d1%82%d1%8c-asp-net-controls-%d0%b8-di-%d0%ba%d0%be%d0%bd%d1%82%d0%b5%d0%b9%d0%bd%d0%b5%d1%80/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/fbea2e42e5c3b8c1918d0dc79a2203ce?s=96&amp;d=identicon&amp;r=G" medium="image">
			<media:title type="html">butaji</media:title>
		</media:content>

		<media:content url="http://butaji.files.wordpress.com/2009/11/dependencyinjection_solution1_thumb.gif" medium="image">
			<media:title type="html">DependencyInjection_Solution[1]</media:title>
		</media:content>
	</item>
		<item>
		<title>Скринкаст о Test-Driven SharePoint Development</title>
		<link>http://butaji.wordpress.com/2009/10/27/%d1%81%d0%ba%d1%80%d0%b8%d0%bd%d0%ba%d0%b0%d1%81%d1%82-%d0%be-test-driven-sharepoint-development/</link>
		<comments>http://butaji.wordpress.com/2009/10/27/%d1%81%d0%ba%d1%80%d0%b8%d0%bd%d0%ba%d0%b0%d1%81%d1%82-%d0%be-test-driven-sharepoint-development/#comments</comments>
		<pubDate>Tue, 27 Oct 2009 19:22:25 +0000</pubDate>
		<dc:creator>butaji</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[DLR]]></category>
		<category><![CDATA[IronPython]]></category>
		<category><![CDATA[MbUnit]]></category>
		<category><![CDATA[Sapphire]]></category>
		<category><![CDATA[sharepoint]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[TypeMock]]></category>

		<guid isPermaLink="false">http://butaji.wordpress.com/?p=612</guid>
		<description><![CDATA[Записал скринкаст о том, как разрабатывал Sapphire REPL WebPart.


	
	
	
	


       <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=butaji.wordpress.com&blog=4404897&post=612&subd=butaji&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Записал скринкаст о том, как разрабатывал <a href="http://github.com/butaji/Sapphire/tree/master/trunk/Sapphire.Environment/">Sapphire REPL WebPart</a>.</p>
<p><span style='text-align:center; display: block;'>
<object type="application/x-shockwave-flash" width="400" height="300" data="http://www.vimeo.com/moogaloop.swf?clip_id=7283762&amp;server=www.vimeo.com&amp;fullscreen=1&amp;show_title=1&amp;show_byline=0&amp;show_portrait=0&amp;color=01AAEA">
	<param name="quality" value="best" />
	<param name="allowfullscreen" value="true" />
	<param name="scale" value="showAll" />
	<param name="movie" value="http://www.vimeo.com/moogaloop.swf?clip_id=7283762&amp;server=www.vimeo.com&amp;fullscreen=1&amp;show_title=1&amp;show_byline=0&amp;show_portrait=0&amp;color=01AAEA" />
</object>
</span></p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/butaji.wordpress.com/612/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/butaji.wordpress.com/612/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/butaji.wordpress.com/612/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/butaji.wordpress.com/612/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/butaji.wordpress.com/612/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/butaji.wordpress.com/612/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/butaji.wordpress.com/612/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/butaji.wordpress.com/612/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/butaji.wordpress.com/612/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/butaji.wordpress.com/612/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=butaji.wordpress.com&blog=4404897&post=612&subd=butaji&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://butaji.wordpress.com/2009/10/27/%d1%81%d0%ba%d1%80%d0%b8%d0%bd%d0%ba%d0%b0%d1%81%d1%82-%d0%be-test-driven-sharepoint-development/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/fbea2e42e5c3b8c1918d0dc79a2203ce?s=96&amp;d=identicon&amp;r=G" medium="image">
			<media:title type="html">butaji</media:title>
		</media:content>
	</item>
		<item>
		<title>REPL WebPart для SharePoint</title>
		<link>http://butaji.wordpress.com/2009/10/24/repl-webpart-%d0%b4%d0%bb%d1%8f-sharepoint/</link>
		<comments>http://butaji.wordpress.com/2009/10/24/repl-webpart-%d0%b4%d0%bb%d1%8f-sharepoint/#comments</comments>
		<pubDate>Sat, 24 Oct 2009 10:58:54 +0000</pubDate>
		<dc:creator>butaji</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[DLR]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[sharepoint]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[IronPython]]></category>
		<category><![CDATA[Isolator]]></category>
		<category><![CDATA[TypeMock]]></category>

		<guid isPermaLink="false">http://butaji.wordpress.com/2009/10/24/repl-webpart-%d0%b4%d0%bb%d1%8f-sharepoint/</guid>
		<description><![CDATA[Intro
Сегодня я расскажу о прототипе первого компонента под ярлычком Sapphire. Это REPL WebPart. Эта веб-часть предназначенная для производства оперативных изменений на серверной стороне SharePoint, так же для удаленного исполнения скриптов и тестирования некоторых кусков кода.
PreBody
Производство данной веб-части было инициированно в довольно таки частых потребностях исполнения серверного кода с достаточной оперативностью, в недоступности средств разработки под [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=butaji.wordpress.com&blog=4404897&post=610&subd=butaji&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><h4>Intro</h4>
<p><a href="http://github.com/butaji/Sapphire"><img style="display:inline;margin-left:0;margin-right:0;border-width:0;" title="logo" border="0" alt="logo" align="right" src="http://butaji.files.wordpress.com/2009/10/logo.png?w=240&#038;h=80" width="240" height="80" /></a>Сегодня я расскажу о прототипе первого компонента под ярлычком Sapphire. Это REPL WebPart. Эта веб-часть предназначенная для производства оперативных изменений на серверной стороне SharePoint, так же для удаленного исполнения скриптов и тестирования некоторых кусков кода.</p>
<h4>PreBody</h4>
<p>Производство данной веб-части было инициированно в довольно таки частых потребностях исполнения серверного кода с достаточной оперативностью, в недоступности средств разработки под рукой.</p>
<p>Здесь есть небольшая презетнация, в которой я постарался отобразить принципы работы Repl WebPart: </p>
<div style="text-align:left;width:425px;" id="__ss_2334866"><a style="display:block;font:14px helvetica,arial,sans-serif;text-decoration:underline;margin:12px 0 3px;" title="Sapphire Environment Repl WebPart" href="http://www.slideshare.net/butaji/sapphire-environment-repl-webpart">Sapphire Environment Repl WebPart</a>
<div style="font-family:tahoma,arial;height:26px;font-size:11px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">documents</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/butaji">Vitaly Baum</a>.</div>
</p></div>
</p>
<p>В добавок к слайдам расскажу о том, что веб-часть представляет собой классический хостинг Dynamic Languages Runtime языков, пока из которых доступен только Python.</p>
<p>Body</p>
<p>Далее хотелось поговорить о том, как же всё это у меня получилось, итак проект включает в себе несколько основных модулей:</p>
<ul>
<li>Веб-часть и контролы представления </li>
<li>Хостинг языков </li>
</ul>
<p>Далее о них поподробнее</p>
<h4>Language Hosting</h4>
<p>В связи с тем, что языков, которые я захочу реализовать в данном проекте является неограниченное множество, то конечно же мне необходима абстрактная фабрика для их создания, которая будет скрывать иерархию всех доступных языков и инкапсулировать их под интерфейсом:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:142788ba-d336-4fe1-89ad-79152a177eda" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
&#160;&#160;<font color="#0000ff">public</font>&#160;<font color="#0000ff">interface</font>&#160;ILanguagesFactory<br />
&#160;&#160;<font color="#0000ff">{</font><br />
&#160;&#160;&#160;&#160;ILanguage&#160;Create(<font color="#2b91af">string</font>&#160;name);<br />
&#160;&#160;<font color="#0000ff">}</font></p>
<p>&#160;&#160;<font color="#0000ff">public</font>&#160;<font color="#0000ff">interface</font>&#160;ILanguage<br />
&#160;&#160;<font color="#0000ff">{</font><br />
&#160;&#160;&#160;&#160;<font color="#2b91af">string</font>&#160;Name&#160;<font color="#0000ff">{</font>&#160;<font color="#0000ff">get</font>;&#160;<font color="#0000ff">}</font></p>
<p>&#160;&#160;&#160;&#160;<font color="#2b91af">object</font>&#160;Execute(<font color="#2b91af">string</font>&#160;input);</p>
<p>&#160;&#160;&#160;&#160;<font color="#0000ff">void</font>&#160;SetVar(<font color="#2b91af">string</font>&#160;name,&#160;<font color="#2b91af">object</font>&#160;<font color="#0000ff">value</font>);<br />
&#160;&#160;&#160;&#160;<br />
&#160;&#160;&#160;&#160;<font color="#2b91af">object</font>&#160;GetVar(<font color="#2b91af">string</font>&#160;name);<br />
&#160;&#160;<font color="#0000ff">}</font>
</div>
</div>
<p>Отлично, далее к нашему проекту присоединяются сборки, необходимые для имплементации скриптовых языков:</p>
<ul>
<li><a href="http://github.com/butaji/Sapphire/blob/master/external/IronPython.dll">IronPython.dll</a> </li>
<li><a href="http://github.com/butaji/Sapphire/blob/master/external/Microsoft.Dynamic.dll">Microsoft.Dynamic.dll</a> </li>
<li><a href="http://github.com/butaji/Sapphire/blob/master/external/Microsoft.Scripting.Core.dll">Microsoft.Scripting.Core.dll</a> </li>
<li><a href="http://github.com/butaji/Sapphire/blob/master/external/Microsoft.Scripting.ExtensionAttribute.dll">Microsoft.Scripting.ExtensionAttribute.dll</a> </li>
<li><a href="http://github.com/butaji/Sapphire/blob/master/external/Microsoft.Scripting.dll">Microsoft.Scripting.dll</a> </li>
</ul>
<p>Всё готово для того, чтобы реализовать Python, как среду для исполнения кода, отлично, приступим:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:4a23c01d-7e2e-4f64-aa6e-6aaa2296e94e" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
&#160;&#160;<font color="#0000ff">public</font>&#160;<font color="#0000ff">class</font>&#160;<font color="#2b91af">PythonLanguage</font>&#160;:&#160;ILanguage<br />
&#160;&#160;<font color="#0000ff">{</font><br />
&#160;&#160;&#160;&#160;<font color="#0000ff">private</font>&#160;<font color="#0000ff">readonly</font>&#160;ScriptScope&#160;_scope;<br />
&#160;&#160;&#160;&#160;<br />
&#160;&#160;&#160;&#160;<font color="#0000ff">public</font>&#160;<font color="#2b91af">string</font>&#160;Name<br />
&#160;&#160;&#160;&#160;<font color="#0000ff">{</font><br />
&#160;&#160;&#160;&#160;&#160;&#160;<font color="#0000ff">get</font>&#160;<font color="#0000ff">{</font>&#160;<font color="#0000ff">return</font>&#160;<font color="#a31515">&laquo;Python&raquo;</font>;&#160;<font color="#0000ff">}</font><br />
&#160;&#160;&#160;&#160;<font color="#0000ff">}</font></p>
<p>&#160;&#160;&#160;&#160;<font color="#0000ff">public</font>&#160;PythonLanguage()<br />
&#160;&#160;&#160;&#160;<font color="#0000ff">{</font><br />
&#160;&#160;&#160;&#160;&#160;&#160;_scope&#160;=&#160;Python.CreateEngine().CreateScope();<br />
&#160;&#160;&#160;&#160;<font color="#0000ff">}</font></p>
<p>&#160;&#160;&#160;&#160;<font color="#0000ff">public</font>&#160;<font color="#2b91af">object</font>&#160;Execute(<font color="#2b91af">string</font>&#160;input)<br />
&#160;&#160;&#160;&#160;<font color="#0000ff">{</font><br />
&#160;&#160;&#160;&#160;&#160;&#160;ScriptSource&#160;source&#160;=&#160;_scope.Engine.CreateScriptSourceFromString(input);<br />
&#160;&#160;&#160;&#160;&#160;&#160;<font color="#0000ff">return</font>&#160;source.Execute(_scope);<br />
&#160;&#160;&#160;&#160;<font color="#0000ff">}</font><br />
&#160;&#160;<font color="#0000ff">}</font>
</div>
</div>
<p>Далее немного усложним задачу, в связи с тем, что нам будет необходимо реализовать контекст для работы с SharePoint, выглядеть это должно примерно так:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:ca75d6c0-193b-4d2a-9881-d6788a7227d1" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
&#160;&#160;&#160;&#160;[Test]<br />
&#160;&#160;&#160;&#160;<font color="#0000ff">private</font>&#160;<font color="#0000ff">void</font>&#160;python_should_assume_sharepoint_variables()<br />
&#160;&#160;&#160;&#160;<font color="#0000ff">{</font><br />
&#160;&#160;&#160;&#160;&#160;&#160;SPWeb&#160;fakeWeb&#160;=&#160;Isolate.Fake.Instance&lt;SPWeb&gt;();<br />
&#160;&#160;&#160;&#160;&#160;&#160;Isolate.WhenCalled(()&#160;=&gt;&#160;fakeWeb.Title).WillReturn(<font color="#a31515">&laquo;I&#8217;m&#160;fake&#160;web&raquo;</font>);<br />
&#160;&#160;&#160;&#160;&#160;&#160;var&#160;python&#160;=&#160;_factory.Create(<font color="#a31515">&laquo;Python&raquo;</font>);<br />
&#160;&#160;&#160;&#160;&#160;&#160;python.SetVar(<font color="#a31515">&laquo;__x__&raquo;</font>,&#160;<font color="#a31515">&laquo;123&#8243;</font>);<br />
&#160;&#160;&#160;&#160;&#160;&#160;python.SetVar(<font color="#a31515">&laquo;__web__&raquo;</font>,&#160;fakeWeb);<br />
&#160;&#160;&#160;&#160;&#160;&#160;python.Execute(<font color="#a31515">&laquo;__x__&#160;=&#160;__web__.Title&raquo;</font>);<br />
&#160;&#160;&#160;&#160;&#160;&#160;var&#160;x&#160;=&#160;(<font color="#2b91af">string</font>)python.GetVar(<font color="#a31515">&laquo;__x__&raquo;</font>);<br />
&#160;&#160;&#160;&#160;&#160;&#160;Assert.AreEqual(x,&#160;<font color="#a31515">&laquo;I&#8217;m&#160;fake&#160;web&raquo;</font>);<br />
&#160;&#160;&#160;&#160;<font color="#0000ff">}</font>
</div>
</div>
<p>Для работы с объектами SharePoint в из IronPython, нам необходимо добавить несколько библиотек:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:563fdb62-23a0-4be1-afdb-dc13d4251e92" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
&#160;&#160;&#160;&#160;&#160;&#160;_scope.Engine.Runtime.LoadAssembly(<font color="#0000ff">typeof</font>(<font color="#2b91af">string</font>).Assembly);<br />
&#160;&#160;&#160;&#160;&#160;&#160;_scope.Engine.Runtime.LoadAssembly(<font color="#0000ff">typeof</font>(Uri).Assembly);<br />
&#160;&#160;&#160;&#160;&#160;&#160;_scope.Engine.Runtime.LoadAssembly(<font color="#0000ff">typeof</font>(SPList).Assembly);&#160;
</div>
</div>
<p>Это будет основой нашей работы с динамическими языками</p>
<h4>WebPart + WebControls</h4>
<p>Создадим проект с помощью SPVisualDev, добавим в него feature, внутри которой создадим веб-часть Repl WebPart, всё остальные действия стандартные, однако есть небольшой нюанс, нам нужен будет объект, с помощью которого можно будет выводить строковые значения после исполнения. Я решил создать для этих целей объект с классическим названием Console, его реализация предельна проста:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:945a4360-d234-4d37-8726-b513863ee74b" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
&#160;&#160;<font color="#0000ff">public</font>&#160;<font color="#0000ff">class</font>&#160;<font color="#2b91af">Console</font><br />
&#160;&#160;<font color="#0000ff">{</font><br />
&#160;&#160;&#160;&#160;<font color="#0000ff">private</font>&#160;<font color="#0000ff">readonly</font>&#160;StringBuilder&#160;_messageBuilder&#160;=&#160;<font color="#0000ff">new</font>&#160;StringBuilder();</p>
<p>&#160;&#160;&#160;&#160;<font color="#0000ff">public</font>&#160;<font color="#0000ff">void</font>&#160;Write(<font color="#2b91af">object</font>&#160;message)<br />
&#160;&#160;&#160;&#160;<font color="#0000ff">{</font><br />
&#160;&#160;&#160;&#160;&#160;&#160;_messageBuilder.Append(message);<br />
&#160;&#160;&#160;&#160;<font color="#0000ff">}</font></p>
<p>&#160;&#160;&#160;&#160;<font color="#0000ff">public</font>&#160;<font color="#0000ff">void</font>&#160;WriteLine(<font color="#2b91af">object</font>&#160;message)<br />
&#160;&#160;&#160;&#160;<font color="#0000ff">{</font><br />
&#160;&#160;&#160;&#160;&#160;&#160;_messageBuilder.AppendLine(message.ToString());<br />
&#160;&#160;&#160;&#160;<font color="#0000ff">}</font></p>
<p>&#160;&#160;&#160;&#160;<font color="#0000ff">public</font>&#160;<font color="#2b91af">string</font>&#160;Message<br />
&#160;&#160;&#160;&#160;<font color="#0000ff">{</font><br />
&#160;&#160;&#160;&#160;&#160;&#160;<font color="#0000ff">get</font><br />
&#160;&#160;&#160;&#160;&#160;&#160;<font color="#0000ff">{</font><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<font color="#0000ff">return</font>&#160;_messageBuilder.ToString();<br />
&#160;&#160;&#160;&#160;&#160;&#160;<font color="#0000ff">}</font><br />
&#160;&#160;&#160;&#160;<font color="#0000ff">}</font><br />
&#160;&#160;<font color="#0000ff">}</font>
</div>
</div>
<p>Мы будем передавать его в среду исполнения языков, а после исполнения кода опрашивать его свойство Message и выводить его содержимое в нашу веб-часть.</p>
<h4>EndBody</h4>
<p>Все исходники проекта доступны на github: <a href="http://github.com/butaji/Sapphire">http://github.com/butaji/Sapphire</a></p>
<p>Так же предварительную версию Sapphire.Environment (решение поставляется в WSP) можно слить на CodePlex: <a href="http://sapphire.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=34895">http://sapphire.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=34895</a></p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/butaji.wordpress.com/610/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/butaji.wordpress.com/610/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/butaji.wordpress.com/610/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/butaji.wordpress.com/610/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/butaji.wordpress.com/610/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/butaji.wordpress.com/610/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/butaji.wordpress.com/610/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/butaji.wordpress.com/610/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/butaji.wordpress.com/610/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/butaji.wordpress.com/610/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=butaji.wordpress.com&blog=4404897&post=610&subd=butaji&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://butaji.wordpress.com/2009/10/24/repl-webpart-%d0%b4%d0%bb%d1%8f-sharepoint/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/fbea2e42e5c3b8c1918d0dc79a2203ce?s=96&amp;d=identicon&amp;r=G" medium="image">
			<media:title type="html">butaji</media:title>
		</media:content>

		<media:content url="http://butaji.files.wordpress.com/2009/10/logo.png" medium="image">
			<media:title type="html">logo</media:title>
		</media:content>
	</item>
		<item>
		<title>Кратко о Patterns &amp; Practices: SharePoint Guidance</title>
		<link>http://butaji.wordpress.com/2009/10/19/%d0%ba%d1%80%d0%b0%d1%82%d0%ba%d0%be-%d0%be-patterns-practices-sharepoint-guidance/</link>
		<comments>http://butaji.wordpress.com/2009/10/19/%d0%ba%d1%80%d0%b0%d1%82%d0%ba%d0%be-%d0%be-patterns-practices-sharepoint-guidance/#comments</comments>
		<pubDate>Mon, 19 Oct 2009 07:56:08 +0000</pubDate>
		<dc:creator>butaji</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[Sapphire]]></category>
		<category><![CDATA[patterns & practices]]></category>
		<category><![CDATA[sharepoint]]></category>

		<guid isPermaLink="false">http://butaji.wordpress.com/2009/10/19/%d0%ba%d1%80%d0%b0%d1%82%d0%ba%d0%be-%d0%be-patterns-practices-sharepoint-guidance/</guid>
		<description><![CDATA[Интро

В данной статье я хочу произвести обзор руководства под названием “SharePoint Guidance” от подразделения Microsoft patterns &#38; practices. Данное руководство предназначено разработчикам/архитекторам SharePoint, в нём описаны основные принципы построения систем на данной платформе. Над руководством трудились выдающиеся представители разработки под SharePoint, а так же он упорно держится в списке самых активных проектов на CodePlex. Далее [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=butaji.wordpress.com&blog=4404897&post=608&subd=butaji&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><h4>Интро</h4>
<p><a href="http://msdn.microsoft.com/en-us/practices/default.aspx"><img style="display:inline;margin-left:0;margin-right:0;border-width:0;" title="clip_image001" border="0" alt="clip_image001" align="right" src="http://butaji.files.wordpress.com/2009/10/clip_image001.png?w=240&#038;h=65" width="240" height="65" /></a></p>
<p>В данной статье я хочу произвести обзор руководства под названием “SharePoint Guidance” от подразделения <a href="http://msdn.microsoft.com/en-us/practices/default.aspx">Microsoft patterns &amp; practices</a>. Данное руководство предназначено разработчикам/архитекторам SharePoint, в нём описаны основные принципы построения систем на данной платформе. Над руководством трудились выдающиеся представители разработки под SharePoint, а так же он упорно держится в списке самых активных проектов на <a href="codeplex.com">CodePlex</a>. Далее чуть подробнее.</p>
<h4>Описание руководства</h4>
<p>Руководство фактически состоит из нескольких аспектов:</p>
<ol>
<li>SharePoint Guidance Library – библиотека наиболее используемых и полезных функций, таких как управление конфигурацией, абстрагирование слоя данных, логирование событий и сервисная инфраструктура </li>
<li>Документация, в которой подробно описаны все принципы построения приведенных примеров, а так же руководства по основным вопросам, возникающим в разработке на SharePoint. </li>
<li>Contoso Partner Portal Reference Implementation – показательное приложение на MOSS некоей компании <a href="http://contoso.com/">Contoso</a>, являющее собой экстранет-портал, в приложении используются практики наиболее приближенные к промышленным решениям. </li>
<li>Contoso Training Management Reference Implementation – простое приложение HR-отдела, демонстрирующее базовые принципы построения решений на WSS. </li>
<li>QuickStarts – два небольших примера самых простых приложений на SharePoint, а так же доступа к данным </li>
</ol>
<p>Помимо исходных кодов и юнит-тестов к ним, примерами так же являются установочные скрипты, билд-скрипты, что фактически является артифактами верно налаженного процесса производства ПО, что очень показательно и полезно с практической точки зрения.</p>
<h4><a href="http://spg.codeplex.com/"><img style="display:inline;margin-left:0;margin-right:0;border-width:0;" title="image" border="0" alt="image" src="http://butaji.files.wordpress.com/2009/10/image.png?w=464&#038;h=288" width="464" height="288" /></a> </h4>
<h4>Обзор руководства</h4>
<p>1ая версия вышла в прошлом году (Dec2008), в настоящее время доступна 2ая версия данного руководства (Aug2009), о ней и будет идти речь.</p>
<ul>
<li><a href="http://msdn.microsoft.com/en-us/library/ee413876.aspx">Introduction</a> – небольшое введение, а так же рекомендации к инструментам разработки: <a href="http://www.microsoft.com/downloads/details.aspx?displaylang=en&amp;FamilyID=fb9d4b85-da2a-432e-91fb-d505199c49f6">VSeWSS</a>, <a href="http://www.u2u.be/res/Tools/CamlQueryBuilder.aspx">U2U CAML Query Builder</a>, <a href="http://www.codeplex.com/camldotnet">CAML.NET</a>, <a href="http://www.typemock.com/unit-testing-Microsoft-SharePoint.html">Typemock Isolator</a> </li>
<li><a href="http://msdn.microsoft.com/en-us/library/ee413905.aspx">Developing SharePoint Applications</a> – основные сценарии разработки под платформу, а так же её ключевые возможности </li>
<li><a href="http://msdn.microsoft.com/en-us/library/ee413955.aspx">Design and Development Guidelines</a> – отображены ключевые моменты архитектуры SharePoint, а так же описаны подходы решения тех или иных задач разработки под платформу; описаны рекомендации к управлению жизненным циклом проектов </li>
<li><a href="http://msdn.microsoft.com/en-us/library/ee413902.aspx">Application and Design Patterns</a> – одна из наиболее интересных глав, в ней описаны как классические паттерны построения корпоративных приложений ложатся на решения под SharePoint </li>
<li><a href="http://msdn.microsoft.com/en-us/library/ee413821.aspx">The SharePoint Guidance Library</a> – описание библиотеки со всеми ключевыми возможностями и компонентами для разработки </li>
<li><a href="http://msdn.microsoft.com/en-us/library/ee413751.aspx">Integrating Line-of-Business Systems</a> – описание интеграции с существующими корпоративными системами </li>
<li><a href="http://msdn.microsoft.com/en-us/library/ee413856.aspx">Considerations for Content-Driven Applications</a> – здесь можно узнать о том, как правильно строить приложения, для хранения контента </li>
<li><a href="http://msdn.microsoft.com/en-us/library/ee413732.aspx">Considerations for Enterprise-Scale Applications</a> – рекомендации по созданию приложений масштаба предприятия </li>
<li><a href="http://msdn.microsoft.com/en-us/library/ee413906.aspx">Considerations for Extranet Development</a> – рекомендации по разработке и планированию экстранет-порталов </li>
<li><a href="http://msdn.microsoft.com/en-us/library/ee413839.aspx">Partner Portal Reference Implementation</a> – описание построения приложения-примера для MOSS </li>
<li><a href="http://msdn.microsoft.com/en-us/library/ee413982.aspx">Training Management Reference Implementation</a>– описание построения приложения-примера для WSS </li>
<li><a href="http://msdn.microsoft.com/en-us/library/ee413799.aspx">QuickStarts</a> – описание приложения для легкого старта работы с SharePoint </li>
</ul>
<h4>Критика</h4>
<p><a href="http://github.com/butaji/Sapphire"><img style="display:inline;margin-left:0;margin-right:0;border-width:0;" title="logo" border="0" alt="logo" align="right" src="http://butaji.files.wordpress.com/2009/10/logo.png?w=240&#038;h=80" width="240" height="80" /></a> Данное руководство содержит в себе большое количество практичной полезной информации, однако в некоторых технических решениях моя точка зрения расходится с его создателями, в связи с чем мною был начат проект <a href="http://github.com/butaji/Sapphire">Sapphire: SharePoint Application Framework</a>, который будет так же являться каркасом для построения решений на SharePoint, а так же включать примеры решений и необходимые в повседневной разработке компоненты.</p>
<h4>Ресурсы по SharePoint Guidance</h4>
<p>Скачать полную версию за август 2009 года можно здесь: </p>
<ul>
<li><a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=91f3c22c-8be7-4721-9449-84f699337d55&amp;displaylang=en">http://www.microsoft.com/downloads/details.aspx?FamilyId=91f3c22c-8be7-4721-9449-84f699337d55&amp;displaylang=en</a> </li>
</ul>
<p>SharePoint Guidance так же представлен на CodePlex: <a href="http://www.codeplex.com/spg/">http://www.codeplex.com/spg/</a> здесь можно задать интересующие вопросы и скачать все последние изменения.</p>
<p>Так же некоторые главы из SharePoint Guidance представлены в видеоряде на channel 9:</p>
<h3><a href="http://channel9.msdn.com/posts/akMSFT/Setting-up-the-Contoso-RI-p--p-Developing-SharePoint-Applications-guidance/"></a></h3>
<ul>
<li><a href="http://channel9.msdn.com/posts/akMSFT/Setting-up-the-Contoso-RI-p--p-Developing-SharePoint-Applications-guidance/">Setting up the Contoso RI &#8211; p &amp; p Developing SharePoint Applications guidance</a> </li>
<li><a href="http://channel9.msdn.com/posts/akMSFT/Walkthrough-of-the-Contoso-Reference-Implementation-p--p-Developing-SharePoint-Applications-guidance/">Walkthrough of the Contoso Reference Implementation- p &amp; p Developing SharePoint Applications guidance</a> </li>
<li><a href="http://channel9.msdn.com/posts/akMSFT/How-to-use-the-configuration-component-p--p-Developing-SharePoint-Applications-guidance/">How to use the configuration component? &#8211; p &amp; p Developing SharePoint Applications guidance</a> </li>
<li><a href="http://channel9.msdn.com/posts/akMSFT/How-to-use-the-logging-components-p--p-Developing-SharePoint-Applications-guidance/">How to use the logging components? &#8211; p &amp; p Developing SharePoint Applications guidance</a> </li>
<li><a href="http://channel9.msdn.com/posts/akMSFT/How-to-use-the-SharePoint-Service-Locator-p--p-Developing-SharePoint-Applications-guidance/">How to use the SharePoint Service Locator? &#8211; p &amp; p Developing SharePoint Applications guidance</a> </li>
</ul>
<h4>Ресурсы по SharePoint</h4>
<p>TechNet располагает огромным количеством статей и книг по SharePoint, конечно в них не так много внимания уделено именно разработке, однако для формирования вижна платформы весьма полезно: <a href="http://technet.microsoft.com/en-us/library/cc262788.aspx">http://technet.microsoft.com/en-us/library/cc262788.aspx</a></p>
<p><a href="http://msdn.microsoft.com/en-us/sharepoint/aa905690.aspx">SharePoint Developer Center</a> здесь можно найти практически всё, что нужно для разработки на SharePoint</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/butaji.wordpress.com/608/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/butaji.wordpress.com/608/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/butaji.wordpress.com/608/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/butaji.wordpress.com/608/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/butaji.wordpress.com/608/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/butaji.wordpress.com/608/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/butaji.wordpress.com/608/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/butaji.wordpress.com/608/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/butaji.wordpress.com/608/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/butaji.wordpress.com/608/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=butaji.wordpress.com&blog=4404897&post=608&subd=butaji&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://butaji.wordpress.com/2009/10/19/%d0%ba%d1%80%d0%b0%d1%82%d0%ba%d0%be-%d0%be-patterns-practices-sharepoint-guidance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/fbea2e42e5c3b8c1918d0dc79a2203ce?s=96&amp;d=identicon&amp;r=G" medium="image">
			<media:title type="html">butaji</media:title>
		</media:content>

		<media:content url="http://butaji.files.wordpress.com/2009/10/clip_image001.png" medium="image">
			<media:title type="html">clip_image001</media:title>
		</media:content>

		<media:content url="http://butaji.files.wordpress.com/2009/10/image.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>

		<media:content url="http://butaji.files.wordpress.com/2009/10/logo.png" medium="image">
			<media:title type="html">logo</media:title>
		</media:content>
	</item>
		<item>
		<title>Habrahabr, Live Writer и Code Highlighting</title>
		<link>http://butaji.wordpress.com/2009/10/17/habrahabr-live-writer-%d0%b8-code-highlighting/</link>
		<comments>http://butaji.wordpress.com/2009/10/17/habrahabr-live-writer-%d0%b8-code-highlighting/#comments</comments>
		<pubDate>Sat, 17 Oct 2009 15:07:04 +0000</pubDate>
		<dc:creator>butaji</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[Blog]]></category>
		<category><![CDATA[Live]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[IronPython]]></category>
		<category><![CDATA[Live Writer]]></category>
		<category><![CDATA[Pygments]]></category>

		<guid isPermaLink="false">http://butaji.wordpress.com/2009/10/17/habrahabr-live-writer-%d0%b8-code-highlighting/</guid>
		<description><![CDATA[Интро
Уже практически полгода я пользуюсь Windows Live Writer в качестве инструмента для написания веб-ориентированных статей. Это отличный инструмент, работающий с большим количеством blogengine’ов, и даже с SharePoint. Но разговор не об этом, в связи с тем, что я разработчик, мне частенько приходится вставлять листинг кода в написанные статьи, на это я и хочу обратить ваше [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=butaji.wordpress.com&blog=4404897&post=604&subd=butaji&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><h2>Интро</h2>
<p>Уже практически полгода я пользуюсь <a href="http://download.live.com/writer">Windows Live Writer</a> в качестве инструмента для написания веб-ориентированных статей. Это отличный инструмент, работающий с большим количеством blogengine’ов, и даже с SharePoint. Но разговор не об этом, в связи с тем, что я разработчик, мне частенько приходится вставлять листинг кода в написанные статьи, на это я и хочу обратить ваше внимание.</p>
<h2>Пигменты</h2>
<p>Многие представители Python-сообщества наверняка знакомы с дивным проектом под названием Pygments:</p>
<p><a href="http://pygments.org/"><img style="border-bottom:0;border-left:0;border-top:0;border-right:0;" border="0" src="http://devhawk.net/content/binary/WindowsLiveWriter/CallingIronPythonfromCWithouttheDynamicT_E49B/pygments_logo_55f6722f-70ee-4d75-8781-b5d547dd3f72.png" /></a></p>
<p>Ну так вот, товарищ Harry Pierson (@<a href="http://twitter.com/devhawk">DevHawk</a>) <a href="http://devhawk.net/2009/08/10/Building+A+Hybrid+C+IronPython+App+Without+Dynamic+Type.aspx">скомпилировал</a> этот движок под IronPython и написал обертку-плагин для Windows Live Writer (качать <a href="http://cid-0d9bc809858885a4.skydrive.live.com/browse.aspx/DevHawk%20Content/Pygments%20for%20WL%20Writer">здесь</a> не торопиться). Отлично, однако то, что получается в результате его обработки не выделяется цветом на habrahabr, это связанно с некоторыми особенностями ресурса, однако поправимо.</p>
<p>Данными работами я и предлагаю заняться, для этого нам понадобятся:</p>
<ul>
<li>Исходники проекта (<a href="http://github.com/devhawk/pygments.wlwriter">на GitHub’е</a>)</li>
<li>5 мин времени</li>
</ul>
<p>После того, как мы скачали исходники, стоит разыскать скрипт под именем pygments_package\devhawk_formatter.py и немного его подкоректировать:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:a856292f-28a5-467a-86f2-45500efedf10" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<font color="#408080"><i>#&#160;a&#160;style&#160;item&#160;is&#160;a&#160;tuple&#160;in&#160;the&#160;following&#160;form:</i></font><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<font color="#408080"><i>#&#160;colors&#160;are&#160;readily&#160;specified&#160;in&#160;hex:&#160;&#8217;RRGGBB&#8217;</i></font><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<font color="#008000"><b>if</b></font>&#160;style[<font color="#BA2121">'color'</font>]:<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;start&#160;<font color="#666666">+=</font>&#160;<font color="#BA2121">&#8216;&lt;span&#160;style=&raquo;color:#</font><font color="#BB6688"><b>%s</b></font><font color="#BA2121">&laquo;&gt;&#8217;</font>&#160;<font color="#666666">%</font>&#160;style[<font color="#BA2121">'color'</font>]<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;end&#160;<font color="#666666">=</font>&#160;<font color="#BA2121">&#8216;&lt;/span&gt;&#8217;</font>&#160;<font color="#666666">+</font>&#160;end
</div>
</div>
<p>заменить на</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:c76e7b06-e3fa-4005-92db-12c0e1bed564" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<font color="#408080"><i>#&#160;a&#160;style&#160;item&#160;is&#160;a&#160;tuple&#160;in&#160;the&#160;following&#160;form:</i></font><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<font color="#408080"><i>#&#160;colors&#160;are&#160;readily&#160;specified&#160;in&#160;hex:&#160;&#8217;RRGGBB&#8217;</i></font><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<font color="#008000"><b>if</b></font>&#160;style[<font color="#BA2121">'color'</font>]:<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;start&#160;<font color="#666666">+=</font>&#160;<font color="#BA2121">&#8216;&lt;font&#160;color=&raquo;#</font><font color="#BB6688"><b>%s</b></font><font color="#BA2121">&laquo;&gt;&#8217;</font>&#160;<font color="#666666">%</font>&#160;style[<font color="#BA2121">'color'</font>]<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;end&#160;<font color="#666666">=</font>&#160;<font color="#BA2121">&#8216;&lt;/font&gt;&#8217;</font>&#160;<font color="#666666">+</font>&#160;end
</div>
</div>
<p>Далее пересобрать с помощью скрипта build.bat проект и запустить инсталлер – теперь то что делает данный проект в&#160; цвете отображается на хабре.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/butaji.wordpress.com/604/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/butaji.wordpress.com/604/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/butaji.wordpress.com/604/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/butaji.wordpress.com/604/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/butaji.wordpress.com/604/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/butaji.wordpress.com/604/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/butaji.wordpress.com/604/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/butaji.wordpress.com/604/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/butaji.wordpress.com/604/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/butaji.wordpress.com/604/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=butaji.wordpress.com&blog=4404897&post=604&subd=butaji&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://butaji.wordpress.com/2009/10/17/habrahabr-live-writer-%d0%b8-code-highlighting/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/fbea2e42e5c3b8c1918d0dc79a2203ce?s=96&amp;d=identicon&amp;r=G" medium="image">
			<media:title type="html">butaji</media:title>
		</media:content>

		<media:content url="http://devhawk.net/content/binary/WindowsLiveWriter/CallingIronPythonfromCWithouttheDynamicT_E49B/pygments_logo_55f6722f-70ee-4d75-8781-b5d547dd3f72.png" medium="image" />
	</item>
		<item>
		<title>Вы подготовились к приходу AutoMapper?</title>
		<link>http://butaji.wordpress.com/2009/10/08/%d0%b2%d1%8b-%d0%bf%d0%be%d0%b4%d0%b3%d0%be%d1%82%d0%be%d0%b2%d0%b8%d0%bb%d0%b8%d1%81%d1%8c-%d0%ba-%d0%bf%d1%80%d0%b8%d1%85%d0%be%d0%b4%d1%83-automapper/</link>
		<comments>http://butaji.wordpress.com/2009/10/08/%d0%b2%d1%8b-%d0%bf%d0%be%d0%b4%d0%b3%d0%be%d1%82%d0%be%d0%b2%d0%b8%d0%bb%d0%b8%d1%81%d1%8c-%d0%ba-%d0%bf%d1%80%d0%b8%d1%85%d0%be%d0%b4%d1%83-automapper/#comments</comments>
		<pubDate>Thu, 08 Oct 2009 04:58:51 +0000</pubDate>
		<dc:creator>butaji</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[DDD]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[AutoMapper]]></category>
		<category><![CDATA[DTO]]></category>
		<category><![CDATA[POCO]]></category>

		<guid isPermaLink="false">http://butaji.wordpress.com/2009/10/08/%d0%b2%d1%8b-%d0%bf%d0%be%d0%b4%d0%b3%d0%be%d1%82%d0%be%d0%b2%d0%b8%d0%bb%d0%b8%d1%81%d1%8c-%d0%ba-%d0%bf%d1%80%d0%b8%d1%85%d0%be%d0%b4%d1%83-automapper/</guid>
		<description><![CDATA[Введение
Данная статья предназначена к прочтению разработчикам и архитекторам распределенных систем на платформе .NET. В ней будет рассмотрен гибкий каркас для объектно-объектного преобразования (далее маппинга). Так же будут рассмотрены некоторые аспекты Domain-Driven Design’а.
Зачем мне нужен объектно-объектный маппинг?
Следуя основным принципам DDD, мы реализуем так называемую Rich Domain Model (эти объекты также должны соответствовать принципу POxO). Объекты реального [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=butaji.wordpress.com&blog=4404897&post=601&subd=butaji&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><h2>Введение</h2>
<p>Данная статья предназначена к прочтению разработчикам и архитекторам распределенных систем на платформе .NET. В ней будет рассмотрен гибкий каркас для объектно-объектного преобразования (далее маппинга). Так же будут рассмотрены некоторые аспекты <a href="http://habrahabr.ru/blogs/net/61524/">Domain-Driven Design</a>’а.</p>
<h2>Зачем мне нужен объектно-объектный маппинг?</h2>
<p>Следуя основным принципам <a href="http://habrahabr.ru/blogs/net/61524/">DDD</a>, мы реализуем так называемую <a href="http://martinfowler.com/bliki/AnemicDomainModel.html">Rich Domain Model</a> (эти объекты также должны соответствовать принципу <a href="http://www.google.ru/search?rlz=1C1GGLS_ruRU348RU344&amp;sourceid=chrome&amp;ie=UTF-8&amp;q=Plain+Old+X+Object">POxO</a>). Объекты реального мира, нашедшие отражение в нашем приложении частенько так же передают достаточную сложность, следовательно, достаточно корректно построенная модель крайне тяжело поддаётся перемещению между слоями приложения (не путать с легкостью вносимых изменений).</p>
<p><a href="http://farm4.static.flickr.com/3212/3120129968_f904328654_o.jpg"><img style="display:inline;margin-left:0;margin-right:0;border-width:0;" title="Data Transfer Object" src="http://farm4.static.flickr.com/3212/3120129968_f904328654_o.jpg" border="0" alt="Data Transfer Object" width="244" height="195" align="left" /></a> Тем не менее достаточно часто появляется необходимость “распределения” (я имею ввиду создание промежуточных сущностей, а не растекание модели по слоям) модели между слоями, для отображения, к примеру, атрибутов её сущностей пользователям (в <a href="http://martinfowler.com/eaaDev/uiArchs.html">шаблонах представления MVx</a>), а так же передаче по сервисам (<a href="http://martinfowler.com/eaaCatalog/dataTransferObject.html">Data Transfer Object</a>). Порой бывает даже, что модель “распределяется” для тестирования некоторых аспектов.</p>
<p>Предположим, мы в Африке, у нас банановая плантация, всё классно, выращиваем, продаём, выращиваем, продаём, но тут внезапно внутренний рынок переполняется и нам надо расширятся (к примеру вести бананы в Россию), мы пишем <a href="http://msdn.microsoft.com/en-us/netframework/aa663324.aspx">WCF сервис</a>, который будет слать наши бананы. Так как бананы в Африке имеют несколько иное значение, чем в России, то, соответственно нам понадобятся лишь некоторые атрибуты (остальные фактически не имеют значения), которые мы забубеним в наш DTO</p>
<blockquote><p>Правильнее было бы дать классу BananaWrapper название BananaDTO, для того, чтобы точно отображать его функциональное назначение, но я оставлю название таким для большего уровня абстракции, к примеру, если нам понадобится сделать автомат по продажи бананов и поместить этот объект в <a href="http://martinfowler.com/eaaDev/ModelViewPresenter.html">Presenter Model</a></p></blockquote>
<p>Хочу заметить, что порой задача преобразования объектов становится довольно-таки нетривиальной и в лучшем случаем выглядит примерно подобным образом (это решение в лоб, есть ещё более изощренные методы <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> ):</p>
<blockquote><p><code><span style="font-family:'Courier New';color:#000000;font-size:x-small;"> </span></code></p>
<p><code><span style="font-family:'Courier New';color:#000000;font-size:x-small;"></p>
<ol>
<li> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> Banana</li>
<li>{</li>
<li> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">string</span> Country { <span style="color:#0000ff;">get</span>; <span style="color:#0000ff;">set</span>; }</li>
<li> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">double</span> Price { <span style="color:#0000ff;">get</span>; <span style="color:#0000ff;">set</span>; }</li>
<li> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">int</span> Age { <span style="color:#0000ff;">get</span>; <span style="color:#0000ff;">set</span>; }</li>
<li>}</li>
<li></li>
<li> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> BananaWrapper</li>
<li>{</li>
<li> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">string</span> Country { <span style="color:#0000ff;">get</span>; <span style="color:#0000ff;">set</span>; }</li>
<li> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">double</span> Price { <span style="color:#0000ff;">get</span>; <span style="color:#0000ff;">set</span>; }</li>
<li> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">int</span> Age { <span style="color:#0000ff;">get</span>; <span style="color:#0000ff;">set</span>; }</li>
<li>}</li>
<li></li>
<li> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> BananaMapper</li>
<li>{</li>
<li> <span style="color:#0000ff;">public</span> BananaWrapper GetWrapper(Banana banana)</li>
<li> {</li>
<li> <span style="color:#0000ff;">return</span> <span style="color:#0000ff;">new</span> BananaWrapper</li>
<li> {</li>
<li> Country = banana.Country,</li>
<li> Price = banana.Price,</li>
<li> Age = banana.Age</li>
<li> };</li>
<li> }</li>
<li>}</li>
</ol>
<p></span></code><code><span style="font-family:'Courier New';color:#000000;font-size:x-small;"> </span><span style="color:#808080;font-size:xx-small;">* This source code was highlighted with <a href="http://virtser.net/blog/post/source-code-highlighter.aspx"><span style="color:#808080;font-size:xx-small;">Source Code Highlighter</span></a>.</span></code></p></blockquote>
<p>Думаю, что такой код писать, а тем более сопровождать, мало кому будет в радость, в последнее время я как раз частенько встречался с такого рода задачами, и находился в поиске решения проблемы.</p>
<h2>AutoMapper</h2>
<p>И тут на сцену выходит наш персонаж – <a href="http://code.google.com/p/automapperhome/">AutoMapper</a>, и сразу же говорит мне: &#8211; послушай, ты что такое пишешь? тебе не лень? ты не боишься допустить ошибок? хочешь я тебе помогу?!. Я конечно же соглашаюсь, и получаю в ответ следующее решение моей проблемы:</p>
<blockquote><p><code><span style="font-family:'Courier New';color:#000000;font-size:x-small;"> </span></code></p>
<p><code><span style="font-family:'Courier New';color:#000000;font-size:x-small;"></p>
<ol>
<li> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> BananaMapper</li>
<li>{</li>
<li> <span style="color:#0000ff;">public</span> BananaMapper()</li>
<li> {</li>
<li> Mapper.CreateMap&lt;Banana, BananaWrapper&gt;();</li>
<li> }</li>
<li></li>
<li> <span style="color:#0000ff;">public</span> BananaWrapper GetWrapper(Banana banana)</li>
<li> {</li>
<li> <span style="color:#0000ff;">return</span> Mapper.Map&lt;Banana, BananaWrapper&gt;(banana); ;</li>
<li> }</li>
<li>}</li>
</ol>
<p></span></code><code><span style="font-family:'Courier New';color:#000000;font-size:x-small;"> </span><span style="color:#808080;font-size:xx-small;">* This source code was highlighted with <a href="http://virtser.net/blog/post/source-code-highlighter.aspx"><span style="color:#808080;font-size:xx-small;">Source Code Highlighter</span></a>.</span></code></p></blockquote>
<p>Класс, и это действительно всё, что мне понадобится. Сложность, вышележащего примера снизилась в моих глазах до нуля.</p>
<p>Итак, что же за механизмы лежат внутри AutoMapper?</p>
<p>AutoMapper проверяет есть соответствующие поля в указанных типах, соответствие проводится как по имени свойства, так и по его типу. Даже такие нюансы, как Product.Name и ProductName будут учтены и обработаны автоматически (wow!). Плюс ко всему методы GetXXX() будут ложится на свойства XXX (да, ну и естественно для особо раздражительных все эти прелести можно отключить и переопределить всё в своих собственных таблицах соответствия (далее мапках)).</p>
<p>Кастомная конфигурация выглядит примерно следующим образом:</p>
<blockquote><p><code><span style="font-family:'Courier New';color:#000000;font-size:x-small;"> </span></code></p>
<p><code><span style="font-family:'Courier New';color:#000000;font-size:x-small;"></p>
<ol>
<li>Mapper.CreateMap&lt;CalendarEvent, CalendarEventForm&gt;()</li>
<li> .ForMember(dest =&gt; dest.EventDate, opt =&gt; opt.MapFrom(src =&gt; src.EventDate.Date))</li>
<li> .ForMember(dest =&gt; dest.EventHour, opt =&gt; opt.MapFrom(src =&gt; src.EventDate.Hour))</li>
<li> .ForMember(dest =&gt; dest.EventMinute, opt =&gt; opt.MapFrom(src =&gt; src.EventDate.Minute));</li>
</ol>
<p></span></code><code><span style="font-family:'Courier New';color:#000000;font-size:x-small;"> </span><span style="color:#808080;font-size:xx-small;">* This source code was highlighted with <a href="http://virtser.net/blog/post/source-code-highlighter.aspx"><span style="color:#808080;font-size:xx-small;">Source Code Highlighter</span></a>.</span></code></p></blockquote>
<p>Кстати, все ваши кастомные конфигурации легко поддаются проверке с помощью следующего метода:</p>
<blockquote><p><code><span style="font-family:'Courier New';color:#000000;font-size:x-small;"> </span></code></p>
<p><code><span style="font-family:'Courier New';color:#000000;font-size:x-small;"></p>
<ol>
<li>Mapper.AssertConfigurationIsValid();</li>
</ol>
<p></span></code><code><span style="font-family:'Courier New';color:#000000;font-size:x-small;"> </span><span style="color:#808080;font-size:xx-small;">* This source code was highlighted with <a href="http://virtser.net/blog/post/source-code-highlighter.aspx"><span style="color:#808080;font-size:xx-small;">Source Code Highlighter</span></a>.</span></code></p></blockquote>
<p>Так же не плохо работает с:</p>
<ul>
<li><a href="http://automapper.codeplex.com/Wiki/View.aspx?title=Lists%20and%20Arrays">коллекциями</a></li>
<li><a href="http://automapper.codeplex.com/Wiki/View.aspx?title=Nested%20Mappings">вложенными мапами</a></li>
<li><a href="http://automapper.codeplex.com/Wiki/View.aspx?title=Custom%20Type%20Converters">конверторами типов</a> (к примеру string в int)</li>
<li><a href="http://automapper.codeplex.com/Wiki/View.aspx?title=Custom%20Value%20Resolvers">нестандартной логикой инициализации</a></li>
<li><a href="http://automapper.codeplex.com/Wiki/View.aspx?title=Custom%20Value%20Formatters">форматированием</a></li>
</ul>
<h2>История</h2>
<p>Проект появился в конце’08-начале’09, около полугода находился в версии 0.31, сейчас же добрался до RC 1.0, думаю, что релиз уже совсем скоро.</p>
<h2>Overhead?</h2>
<p><a href="http://www.banana-bread.biz/pictures/banana-avatar.jpg"><img style="display:inline;margin-left:0;margin-right:0;border-width:0;" title="banana" src="http://www.banana-bread.biz/pictures/banana-avatar.jpg" border="0" alt="banana" width="52" height="53" align="left" /></a> Дебаты по поводу того, насколько быстрее будет работать AutoMapper и присвоение свойств в ручную (и прочие мульки) я игнорирую, т.к. готов пойти на любые жертвы производительности, если получу ясный, читабельный код. Ах, да, автор AutoMapper позаботился об этих вопросах и написал бенчмарки, смотреть здесь: <a href="http://code.google.com/p/automapperhome/source/browse/#svn/trunk/src/Benchmark">http://code.google.com/p/automapperhome/source/browse/#svn/trunk/src/Benchmark</a></p>
<h2>Ресурсы</h2>
<p>Скачать проект, а так же ознакомиться с исходными кодами можно здесь: <a title="http://code.google.com/p/automapperhome/" href="http://code.google.com/p/automapperhome/">http://code.google.com/p/automapperhome/</a></p>
<p>Обсуждения каркаса здесь: <a href="http://groups.google.com/group/automapper-users">http://groups.google.com/group/automapper-users</a></p>
<p>Так же примеры использования есть здесь: <a href="http://automapper.codeplex.com/">http://automapper.codeplex.com/</a></p>
<p>Кстати проект разрабатывает <a href="http://www.lostechies.com/blogs/jimmy_bogard/default.aspx">Jimmy Bogard</a>, который так же пишет <a href="http://en.wikipedia.org/wiki/Behavior_driven_development">BDD</a> фреймворк для .NET под названием <a href="http://code.google.com/p/nbehave/">NBehave</a>.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/butaji.wordpress.com/601/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/butaji.wordpress.com/601/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/butaji.wordpress.com/601/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/butaji.wordpress.com/601/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/butaji.wordpress.com/601/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/butaji.wordpress.com/601/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/butaji.wordpress.com/601/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/butaji.wordpress.com/601/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/butaji.wordpress.com/601/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/butaji.wordpress.com/601/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=butaji.wordpress.com&blog=4404897&post=601&subd=butaji&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://butaji.wordpress.com/2009/10/08/%d0%b2%d1%8b-%d0%bf%d0%be%d0%b4%d0%b3%d0%be%d1%82%d0%be%d0%b2%d0%b8%d0%bb%d0%b8%d1%81%d1%8c-%d0%ba-%d0%bf%d1%80%d0%b8%d1%85%d0%be%d0%b4%d1%83-automapper/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/fbea2e42e5c3b8c1918d0dc79a2203ce?s=96&amp;d=identicon&amp;r=G" medium="image">
			<media:title type="html">butaji</media:title>
		</media:content>

		<media:content url="http://farm4.static.flickr.com/3212/3120129968_f904328654_o.jpg" medium="image">
			<media:title type="html">Data Transfer Object</media:title>
		</media:content>

		<media:content url="http://www.banana-bread.biz/pictures/banana-avatar.jpg" medium="image">
			<media:title type="html">banana</media:title>
		</media:content>
	</item>
		<item>
		<title>DynamicObject, JSON и ближайшее будущее</title>
		<link>http://butaji.wordpress.com/2009/09/21/dynamicobject-json-%d0%b8-%d0%b1%d0%bb%d0%b8%d0%b6%d0%b0%d0%b9%d1%88%d0%b5%d0%b5-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5/</link>
		<comments>http://butaji.wordpress.com/2009/09/21/dynamicobject-json-%d0%b8-%d0%b1%d0%bb%d0%b8%d0%b6%d0%b0%d0%b9%d1%88%d0%b5%d0%b5-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5/#comments</comments>
		<pubDate>Mon, 21 Sep 2009 07:36:14 +0000</pubDate>
		<dc:creator>butaji</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[DLR]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[dynamic]]></category>
		<category><![CDATA[.NET 4.0]]></category>
		<category><![CDATA[DynamicObject]]></category>

		<guid isPermaLink="false">http://butaji.wordpress.com/2009/09/21/dynamicobject-json-%d0%b8-%d0%b1%d0%bb%d0%b8%d0%b6%d0%b0%d0%b9%d1%88%d0%b5%d0%b5-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5/</guid>
		<description><![CDATA[Введение
В данной статье хочу ознакомить вас с небольшим приложением для работы с JSON данными, демонстрирующим возможности, доступные нам в .NET 4.0. Поверхностно будут рассмотрены вопросы JSON-формата, а так же работы с динамическими типами данных.
JSON
Есть такая классная шутка, известная широким массам:
 JSON (JavaScript Object Notation) &#8211; простой формат обмена данными, удобный для чтения и написания как [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=butaji.wordpress.com&blog=4404897&post=600&subd=butaji&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><h4>Введение</h4>
<p>В данной статье хочу ознакомить вас с небольшим приложением для работы с JSON данными, демонстрирующим возможности, доступные нам в .NET 4.0. Поверхностно будут рассмотрены вопросы JSON-формата, а так же работы с динамическими типами данных.</p>
<h4>JSON</h4>
<p>Есть такая классная шутка, известная широким массам:</p>
<p><b><a href="http://farm3.static.flickr.com/2551/3763158824_e2f57810c4.jpg"><img style="display:inline;border-width:0;margin:0 10px 0 0;" title="3763158824_e2f57810c4[1]" border="0" alt="3763158824_e2f57810c4[1]" align="left" src="http://farm3.static.flickr.com/2551/3763158824_e2f57810c4.jpg" width="109" height="165" /></a> JSON</b> (JavaScript Object Notation) &#8211; простой формат обмена данными, удобный для чтения и написания как человеком, так и компьютером. Он основан на подмножестве <a href="http://javascript.crockford.com/">языка программирования JavaScript</a>, определенного в <a href="http://www.ecma-international.org/publications/files/ecma-st/ECMA-262.pdf">стандарте ECMA-262 3rd Edition &#8211; December 1999</a>. JSON &#8211; текстовый формат, полностью независимый от языка реализации, но он использует соглашения, знакомые программистам C-подобных языков, таких как C, C++, C#, Java, JavaScript, Perl, Python и многих других. Эти свойства делают JSON идеальным языком обмена данными. <a href="http://www.json.org/json-ru.html">далее…</a></p>
<h4>JSON и ваше приложение</h4>
<p>Ну так вот, обычно, получая объекты по JSON в наших приложениях мы должны подготовить инфраструктуру для их поддержки (к примеру с помощью <a href="http://msdn.microsoft.com/ru-ru/library/system.runtime.serialization.json.datacontractjsonserializer.aspx">DataContractJsonSerializer</a> и решения на типа <a href="http://beta.codeproject.com/KB/WCF/consuming-json-wcf.aspx">этого</a>). Однако это занимает значительное время у разработчика. В связи с этим у меня появилось страстное желание поставить JSON механизмы на рельсы динамических возможностей .NET 4.0 и получать от работы с ним одно удовольствие <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<h4>DynamicObject</h4>
<p><a href="http://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject_members(VS.100).aspx">DynamicObject</a> &#8211; Предоставляет нам простой класс, наследуясь от которого мы можем получить динамическое поведение объекта на этапе исполнения. Наследуясь от этого класса и переопределяя некоторые его методы реализуется вся основная логика необходимая нам для этого.</p>
<p>Если хостинг DLR и прочие прелести вас заинтересовали и вы хотите ознакомиться немного поглубже с вопросом, то можно посмотреть <a href="http://spbalt.net/">наше</a> выступление <a href="http://video.yandex.ru/users/thecoffee/view/4/">здесь</a>, а так же слайды (<a href="http://www.slideshare.net/butaji/dlr-hosting">здесь</a> и <a href="http://spbalt.net/Content/Maxim_Moiseev_DLR.pdf">здесь</a>).</p>
<h4>К разработке</h4>
<p>Для того, чтобы не испытывать неудобств при работе с JSON, я предлагаю воспользоваться (слить и зареференсить) решением от <a href="http://james.newtonking.com/">James Newton</a> под названием <a href="http://www.codeplex.com/Json">JSON.NET</a>, данный проект свободен и удовлетворяет всем основным требованиям работы с JSON в рамках .NET-стека (в том числе и LINQ). </p>
<blockquote><p>Да, к тому же нам понадобится IDE, умеющая работать с .NET 4.0b1, к примеру Visual Studio 2010 Beta 1 (кстати <a href="http://laputa.sharpdevelop.net/SharpDevelopRunningOnNET40Beta1.aspx">#develop не отстает</a>).</p>
</blockquote>
<p>Создаем наше приложение, которое будет выглядеть примерно следующим образом:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:0f032612-421c-4385-a345-a32c506e7031" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<span style="color:#a7a7a7;"><b>string</b></span>&#160;input&#160;=&#160;<span style="color:#CD5555;">@&raquo;{CPU:&#160;&#8217;Intel&#8217;,&#160;Drives:&#160;['DVD&#160;read/writer',&#160;<br />
	""500&#160;gigabyte&#160;hard&#160;drive""&#160;&#160;]}&raquo;</span>;</p>
<p>dynamic&#160;computer&#160;=&#160;<span style="color:#8B008B;"><b>new</b></span>&#160;DynamicJSON(input);
</div>
</div>
<p>И пробуем посмотреть, какие же свойства обнаружатся у нашего компьютера:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:94d2d03d-b65f-474d-90a8-0777accad1d3" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
&gt;&gt;&#160;computer.CPU<br />
<span style="color:#CD5555;">&laquo;Intel&raquo;</span></p>
<p>&gt;&gt;&#160;computer.Drives<br />
<span style="color:#658b00;">[<br />
&#160;&#160;"DVD&#160;read/writer",<br />
&#160;&#160;"500&#160;gigabyte&#160;hard&#160;drive"<br />
]</span></p>
<p>&gt;&gt;&#160;computer.Drives[<span style="color:#B452CD;">0</span>]<br />
<span style="color:#CD5555;">&laquo;DVD&#160;read/writer&raquo;</span>
</div>
</div>
<p>Пока ничего необычного, учитывая, что мы не знаем, что же из себя представляет DynamicJSON, к реализации которого мы и обратимся за впечатлениями:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:4d53bb6d-2c32-4abe-a81b-ecdf23a81085" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
&#160;&#160;<span style="color:#8B008B;"><b>using</b></span>&#160;<span style="color:#008b45;"><u>Newtonsoft.Json.Linq</u></span>;</p>
<p>&#160;&#160;<span style="color:#8B008B;"><b>public</b></span>&#160;<span style="color:#8B008B;"><b>class</b></span>&#160;<span style="color:#008b45;"><b>DynamicJSON</b></span>&#160;:&#160;DynamicObject<br />
&#160;&#160;<span style="color:#8B008B;"><b>{</b></span><br />
&#160;&#160;&#160;&#160;<span style="color:#8B008B;"><b>private</b></span>&#160;JObject&#160;_data;</p>
<p>&#160;&#160;&#160;&#160;<span style="color:#8B008B;"><b>public</b></span>&#160;<span style="color:#008b45;">DynamicJSON</span>(<span style="color:#a7a7a7;"><b>string</b></span>&#160;data)<br />
&#160;&#160;&#160;&#160;<span style="color:#8B008B;"><b>{</b></span><br />
&#160;&#160;&#160;&#160;&#160;&#160;_data&#160;=&#160;JObject.Parse(data);<br />
&#160;&#160;&#160;&#160;<span style="color:#8B008B;"><b>}</b></span></p>
<p>&#160;&#160;&#160;&#160;<span style="color:#8B008B;"><b>public</b></span>&#160;<span style="color:#8B008B;"><b>override</b></span>&#160;<span style="color:#a7a7a7;"><b>bool</b></span>&#160;<span style="color:#008b45;">TryGetMember</span>(GetMemberBinder&#160;binder,&#160;<span style="color:#8B008B;"><b>out</b></span>&#160;<span style="color:#a7a7a7;"><b>object</b></span>&#160;result)<br />
&#160;&#160;&#160;&#160;<span style="color:#8B008B;"><b>{</b></span><br />
&#160;&#160;&#160;&#160;&#160;&#160;result&#160;=&#160;_data[binder.Name];<br />
&#160;&#160;&#160;&#160;&#160;&#160;<span style="color:#8B008B;"><b>return</b></span>&#160;<span style="color:#8B008B;"><b>true</b></span>;<br />
&#160;&#160;&#160;&#160;<span style="color:#8B008B;"><b>}</b></span><br />
&#160;&#160;<span style="color:#8B008B;"><b>}</b></span>
</div>
</div>
<p>И это всё, что потребуется от нас для работы данного примера, меня подобные вещи радуют чрезмерно, в связи с чем рекомендую и вам использовать подобную практику в своих решениях.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/butaji.wordpress.com/600/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/butaji.wordpress.com/600/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/butaji.wordpress.com/600/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/butaji.wordpress.com/600/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/butaji.wordpress.com/600/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/butaji.wordpress.com/600/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/butaji.wordpress.com/600/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/butaji.wordpress.com/600/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/butaji.wordpress.com/600/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/butaji.wordpress.com/600/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=butaji.wordpress.com&blog=4404897&post=600&subd=butaji&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://butaji.wordpress.com/2009/09/21/dynamicobject-json-%d0%b8-%d0%b1%d0%bb%d0%b8%d0%b6%d0%b0%d0%b9%d1%88%d0%b5%d0%b5-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/fbea2e42e5c3b8c1918d0dc79a2203ce?s=96&amp;d=identicon&amp;r=G" medium="image">
			<media:title type="html">butaji</media:title>
		</media:content>

		<media:content url="http://farm3.static.flickr.com/2551/3763158824_e2f57810c4.jpg" medium="image">
			<media:title type="html">3763158824_e2f57810c4[1]</media:title>
		</media:content>
	</item>
		<item>
		<title>Как забыть про ярлыки на рабочем столе?</title>
		<link>http://butaji.wordpress.com/2009/09/07/%d0%ba%d0%b0%d0%ba-%d0%b7%d0%b0%d0%b1%d1%8b%d1%82%d1%8c-%d0%bf%d1%80%d0%be-%d1%8f%d1%80%d0%bb%d1%8b%d0%ba%d0%b8-%d0%bd%d0%b0-%d1%80%d0%b0%d0%b1%d0%be%d1%87%d0%b5%d0%bc-%d1%81%d1%82%d0%be%d0%bb%d0%b5/</link>
		<comments>http://butaji.wordpress.com/2009/09/07/%d0%ba%d0%b0%d0%ba-%d0%b7%d0%b0%d0%b1%d1%8b%d1%82%d1%8c-%d0%bf%d1%80%d0%be-%d1%8f%d1%80%d0%bb%d1%8b%d0%ba%d0%b8-%d0%bd%d0%b0-%d1%80%d0%b0%d0%b1%d0%be%d1%87%d0%b5%d0%bc-%d1%81%d1%82%d0%be%d0%bb%d0%b5/#comments</comments>
		<pubDate>Mon, 07 Sep 2009 06:21:00 +0000</pubDate>
		<dc:creator>butaji</dc:creator>
				<category><![CDATA[Productive]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Enso]]></category>
		<category><![CDATA[Humanized]]></category>
		<category><![CDATA[launcher]]></category>

		<guid isPermaLink="false">http://butaji.wordpress.com/2009/09/07/%d0%ba%d0%b0%d0%ba-%d0%b7%d0%b0%d0%b1%d1%8b%d1%82%d1%8c-%d0%bf%d1%80%d0%be-%d1%8f%d1%80%d0%bb%d1%8b%d0%ba%d0%b8-%d0%bd%d0%b0-%d1%80%d0%b0%d0%b1%d0%be%d1%87%d0%b5%d0%bc-%d1%81%d1%82%d0%be%d0%bb%d0%b5/</guid>
		<description><![CDATA[Введение
 Раньше у меня довольно часто возникала проблема захламления рабочего стола огромным количеством ярлыков, и я начинал теряться в них, соответственно терять время при поиске необходимых мне приложений. В дальнейшем я научился пользоваться сочетанием клавиш win+r, создавая ярлыки с короткими именами в system32. С приходом Windows Vista (7) теперь только кнопки win, однако гибкость и [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=butaji.wordpress.com&blog=4404897&post=598&subd=butaji&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><h2>Введение</h2>
<p><a href="http://butaji.files.wordpress.com/2009/09/image.png"><img style="display:inline;border-width:0;margin:10px 0 0;" title="image" src="http://butaji.files.wordpress.com/2009/09/image_thumb.png?w=240&#038;h=69" border="0" alt="image" width="240" height="69" align="right" /></a> Раньше у меня довольно часто возникала проблема захламления рабочего стола огромным количеством ярлыков, и я начинал теряться в них, соответственно терять время при поиске необходимых мне приложений. В дальнейшем я научился пользоваться сочетанием клавиш <strong>win+r</strong>, создавая ярлыки с короткими именами в system32.<strong> </strong>С приходом Windows Vista (7) теперь только кнопки <strong>win</strong>, однако гибкость и настройка данных методов весьма ограниченна. Имеется так же огромное количество <a href="http://www.autohotkey.com/download/">hotkey-менеджеров</a>, однако не с одним из них я так и не сдружился.</p>
<h2>Лаунчеры</h2>
<p>Недавно (по-моему после прочтения книги <a href="http://www.books.ru/shop/books/645323?partner=butaji">&laquo;Продуктивный программист. Как сделать сложное простым, а невозможное – возможным&raquo;</a> Нила Форда) мой интерес пал на launcher’ы. Для windows-платформы я нашёл несколько:</p>
<ul>
<li>SlickRun <a href="http://www.bayden.com/SlickRun/">http://www.bayden.com/SlickRun/</a></li>
<li>slimCODE <a href="http://www.slimcode.com/">http://www.slimcode.com/</a></li>
<li>Colibri <a href="http://colibri.leetspeak.org/">http://colibri.leetspeak.org/</a> – некоторый аналог небезызвестного <a href="http://docs.blacktree.com/quicksilver/what_is_quicksilver">Quicksilver</a> для Mac OS X</li>
<li>Launchy <a title="http://www.launchy.net/" href="http://www.launchy.net/">http://www.launchy.net/</a></li>
</ul>
<p>Ну и герой этого поста:</p>
<ul>
<li>Enso <a href="http://humanized.com/enso/">http://humanized.com/enso/</a></li>
</ul>
<h2>Немного истории</h2>
<p><img style="display:inline;margin-left:0;margin-right:0;border-width:0;" title="enso_321[1]" src="http://butaji.files.wordpress.com/2009/09/enso_3211.jpg?w=240&#038;h=185" border="0" alt="enso_321[1]" width="240" height="185" align="right" /></p>
<p>Изложу настолько, насколько я сумел разобраться в ней. Первоначально Enso был строго коммерческим проектом, разрабатываемым компанией <a href="http://humanized.com/">Humanized</a> (основанной <a href="http://en.wikipedia.org/wiki/Jef_Raskin">Джеффри Раскиным</a>, в котрой в последующем работал его сын). В дальнейшем компания начала работу над <a href="http://labs.mozilla.com/ubiquity/">Mozilla Ubiquity</a> (аналог Enso, являющийся плагином для FireFox), что позволило ей сделать Enso бесплатным.</p>
<h2>Enso</h2>
<p>Лучше 1 раз увидеть, чем 7 раз прочитать, базовые возможности представлены в следующих роликах:</p>
<p><span style="text-align:center; display: block;"><a href="http://butaji.wordpress.com/2009/09/07/%d0%ba%d0%b0%d0%ba-%d0%b7%d0%b0%d0%b1%d1%8b%d1%82%d1%8c-%d0%bf%d1%80%d0%be-%d1%8f%d1%80%d0%bb%d1%8b%d0%ba%d0%b8-%d0%bd%d0%b0-%d1%80%d0%b0%d0%b1%d0%be%d1%87%d0%b5%d0%bc-%d1%81%d1%82%d0%be%d0%bb%d0%b5/"><img src="http://img.youtube.com/vi/JXfjwZw8cj8/2.jpg" alt="" /></a></span></p>
<p><span style="text-align:center; display: block;"><a href="http://butaji.wordpress.com/2009/09/07/%d0%ba%d0%b0%d0%ba-%d0%b7%d0%b0%d0%b1%d1%8b%d1%82%d1%8c-%d0%bf%d1%80%d0%be-%d1%8f%d1%80%d0%bb%d1%8b%d0%ba%d0%b8-%d0%bd%d0%b0-%d1%80%d0%b0%d0%b1%d0%be%d1%87%d0%b5%d0%bc-%d1%81%d1%82%d0%be%d0%bb%d0%b5/"><img src="http://img.youtube.com/vi/Bs-L63X_xlI/2.jpg" alt="" /></a></span></p>
<p>На настоящий момент на сайте компании есть две версии продукта:</p>
<ul>
<li>Версия 1 <a href="http://humanized.com/enso/">http://humanized.com/enso/</a></li>
</ul>
<blockquote><p>удобна в эксплуатации, но умеет делать лишь базовые вещи.</p>
<p>настройка (как и во второй версии) происходит через embeded веб-сервер</p></blockquote>
<ul>
<li>Версия 2 <a href="http://humanized.com/enso/beta/all/">http://humanized.com/enso/beta/all/</a> (остальное на данной странице является плагинами для Enso)</li>
</ul>
<blockquote><p>в данной версии появилось огромное количество очень полезных плагинов (к примеру поиск в google, <a href="http://www.humanized.com/enso/beta/enso-map-anywhere/">генерация объектов-карт по выделенному адресу</a>) однако юзабили немного упало (с моей точки зрения) в плане того, что после ввода команды начала открываться отдельная строка для ввода параметров, на что уходило время, и приходилось нажимать лишний раз <strong>enter</strong></p></blockquote>
<p>Все отлично, за исключением того, что проект на данном сайте вроде как заброшен, что не совсем воодушевляло к использованию, однако слазив внутрь и посмотрев реализацию, обнаружилось, что всё написано на Python (межплатформенность?), а так же исходники доступны <a href="http://code.google.com/p/enso/">в свободном доступе</a>, что немного приободрило.</p>
<p>В дальнейших поисках упоминаний о Enso я наткнулся на коммунити <a title="http://www.ensowiki.com" href="http://www.ensowiki.com">http://www.ensowiki.com</a>, а так же (самое главное) хостинг нынешей версии Enso <a href="https://launchpad.net/enso">https://launchpad.net/enso</a>, итак, что же изменилось с тех времен:</p>
<ul>
<li>настройка больше не через веб-сервер</li>
<li>межплатформенность (Windows, Linux, Mac OS X, etc)</li>
<li>интерфейс первой версии</li>
<li>практически все плагины из второй версии</li>
</ul>
<h2>Используем Enso</h2>
<p>Для установки существует <a href="https://code.launchpad.net/enso/+download">инсталлер</a>, поэтому трудности вряд ли могут встретиться. Далее у меня возникла необходимость в настройке (теперь для совершения настроек существует файл enso\config.py) “основной” клавиши (Caps Lock) в режим залипания (Sticky в терминологии создателей программы), для этого я проделал следующее:</p>
<div id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:f8370c25-0cc2-4fd5-9bc2-0b845e076e94" class="wlWriterEditableSmartContent" style="display:inline;float:none;margin:0;padding:0;">
<div style="font-family:consolas,lucida console,courier,monospace;"><span style="color:#008800;"><em># Whether the Quasimode is actually modal (&laquo;sticky&raquo;).</em></span></p>
<p>IS_QUASIMODE_MODAL <span style="color:#666666;">=</span> <span style="color:#AA22FF;">True</span></div>
</div>
<h2>Расширяем Enso</h2>
<p>Классно, мой питомец (Enso) теперь стал послушным и ласковым, однако хочется научить его понимать новые команды, ну что ж, пускай это будет Enso hello world.</p>
<p>Я отправился в папку commands в корне, куда добавил файл butaji.py со следующим содержимым:</p>
<div id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:58f76dd8-e620-491e-8cec-c05a0f0a28de" class="wlWriterEditableSmartContent" style="display:inline;float:none;margin:0;padding:0;">
<div style="font-family:consolas,lucida console,courier,monospace;"><span style="color:#AA22FF;"><strong>import</strong></span> <span style="color:#0000FF;"><strong>enso.config</strong></span></p>
<p><span style="color:#AA22FF;"><strong>from</strong></span> <span style="color:#0000FF;"><strong>enso.messages</strong></span> <span style="color:#AA22FF;"><strong>import</strong></span> displayMessage</p>
<p><span style="color:#AA22FF;"><strong>def</strong></span> <span style="color:#00A000;">cmd_butaji</span>(ensoapi, cmd):</p>
<p><span style="color:#AA22FF;"><strong>if</strong></span> cmd <span style="color:#666666;">==</span> <span style="color:#BB4444;">&laquo;time&raquo;</span>:</p>
<p>ensoapi<span style="color:#666666;">.</span>display_message(<span style="color:#BB4444;">&laquo;Hello world&raquo;</span>)</p>
<p>cmd_butaji<span style="color:#666666;">.</span>valid_args <span style="color:#666666;">=</span> [<span style="color:#BB4444;">'time'</span>]</div>
</div>
<p>И у меня получилось следующее:</p>
<p><a href="http://butaji.files.wordpress.com/2009/09/image1.png"><img style="display:inline;border-width:0;" title="image" src="http://butaji.files.wordpress.com/2009/09/image_thumb1.png?w=433&#038;h=184" border="0" alt="image" width="433" height="184" /></a></p>
<p><img style="display:inline;border-width:0;" title="image" src="http://butaji.files.wordpress.com/2009/09/image2.png?w=240&#038;h=121" border="0" alt="image" width="240" height="121" /></p>
<p>Великолепно! я думаю, что мы с Enso очень сдружимся.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/butaji.wordpress.com/598/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/butaji.wordpress.com/598/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/butaji.wordpress.com/598/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/butaji.wordpress.com/598/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/butaji.wordpress.com/598/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/butaji.wordpress.com/598/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/butaji.wordpress.com/598/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/butaji.wordpress.com/598/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/butaji.wordpress.com/598/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/butaji.wordpress.com/598/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=butaji.wordpress.com&blog=4404897&post=598&subd=butaji&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://butaji.wordpress.com/2009/09/07/%d0%ba%d0%b0%d0%ba-%d0%b7%d0%b0%d0%b1%d1%8b%d1%82%d1%8c-%d0%bf%d1%80%d0%be-%d1%8f%d1%80%d0%bb%d1%8b%d0%ba%d0%b8-%d0%bd%d0%b0-%d1%80%d0%b0%d0%b1%d0%be%d1%87%d0%b5%d0%bc-%d1%81%d1%82%d0%be%d0%bb%d0%b5/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/fbea2e42e5c3b8c1918d0dc79a2203ce?s=96&amp;d=identicon&amp;r=G" medium="image">
			<media:title type="html">butaji</media:title>
		</media:content>

		<media:content url="http://butaji.files.wordpress.com/2009/09/image_thumb.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>

		<media:content url="http://butaji.files.wordpress.com/2009/09/enso_3211.jpg" medium="image">
			<media:title type="html">enso_321[1]</media:title>
		</media:content>

		<media:content url="http://img.youtube.com/vi/JXfjwZw8cj8/2.jpg" medium="image" />

		<media:content url="http://img.youtube.com/vi/Bs-L63X_xlI/2.jpg" medium="image" />

		<media:content url="http://butaji.files.wordpress.com/2009/09/image_thumb1.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>

		<media:content url="http://butaji.files.wordpress.com/2009/09/image2.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>
	</item>
		<item>
		<title>Ещё раз о SharePoint Guidance</title>
		<link>http://butaji.wordpress.com/2009/09/03/%d0%b5%d1%89%d1%91-%d1%80%d0%b0%d0%b7-%d0%be-sharepoint-guidance/</link>
		<comments>http://butaji.wordpress.com/2009/09/03/%d0%b5%d1%89%d1%91-%d1%80%d0%b0%d0%b7-%d0%be-sharepoint-guidance/#comments</comments>
		<pubDate>Thu, 03 Sep 2009 07:12:01 +0000</pubDate>
		<dc:creator>butaji</dc:creator>
				<category><![CDATA[sharepoint]]></category>
		<category><![CDATA[patterns & practices]]></category>
		<category><![CDATA[SharePoint guidance]]></category>
		<category><![CDATA[spg]]></category>

		<guid isPermaLink="false">http://butaji.wordpress.com/2009/09/03/%d0%b5%d1%89%d1%91-%d1%80%d0%b0%d0%b7-%d0%be-sharepoint-guidance/</guid>
		<description><![CDATA[Небольшая заметка, в которой я в очередной раз хотел бы обратить внимание на следующий документ: 
 

patterns &#38; practices SharePoint Guidance

исключительно рекомендую всем разработчикам SharePoint
А так же вчера на http://channel9.msdn.com/ вышло несколько роликов, о работе с эти проектом:

How to use the logging components? &#8211; p &#38; p Developing SharePoint Applications guidance
How to use the configuration [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=butaji.wordpress.com&blog=4404897&post=591&subd=butaji&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Небольшая заметка, в которой я в очередной раз хотел бы обратить внимание на следующий документ: </p>
<p><a href="http://spg.codeplex.com/"><img style="border-bottom:0;border-left:0;display:inline;border-top:0;border-right:0;" title="sharepoint_guidance[1]" border="0" alt="sharepoint_guidance[1]" src="http://butaji.files.wordpress.com/2009/09/sharepoint_guidance1.jpg?w=240&#038;h=111" width="240" height="111" /></a> </p>
<p><a href="http://spg.codeplex.com/"></a>
<p>patterns &amp; practices SharePoint Guidance</p>
</p>
<p>исключительно рекомендую всем разработчикам SharePoint</p>
<p>А так же вчера на <a title="http://channel9.msdn.com/" href="http://channel9.msdn.com/">http://channel9.msdn.com/</a> вышло несколько роликов, о работе с эти проектом:</p>
<p><a href="http://channel9.msdn.com/posts/akMSFT/How-to-use-the-logging-components-p--p-Developing-SharePoint-Applications-guidance/"></a></p>
<p><a href="http://channel9.msdn.com/posts/akMSFT/How-to-use-the-logging-components-p--p-Developing-SharePoint-Applications-guidance/">How to use the logging components? &#8211; p &amp; p Developing SharePoint Applications guidance</a></p>
<p><a href="http://channel9.msdn.com/posts/akMSFT/How-to-use-the-configuration-component-p--p-Developing-SharePoint-Applications-guidance/">How to use the configuration component? &#8211; p &amp; p Developing SharePoint Applications guidance</a></p>
<p><a href="http://channel9.msdn.com/posts/akMSFT/How-to-use-the-SharePoint-Service-Locator-p--p-Developing-SharePoint-Applications-guidance/">How to use the SharePoint Service Locator? &#8211; p &amp; p Developing SharePoint Applications guidance</a></p>
<p><a href="http://channel9.msdn.com/posts/akMSFT/Walkthrough-of-the-Contoso-Reference-Implementation-p--p-Developing-SharePoint-Applications-guidance/">Walkthrough of the Contoso Reference Implementation- p &amp; p Developing SharePoint Applications guidance</a></p>
<p>Приятного просмотра.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/butaji.wordpress.com/591/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/butaji.wordpress.com/591/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/butaji.wordpress.com/591/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/butaji.wordpress.com/591/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/butaji.wordpress.com/591/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/butaji.wordpress.com/591/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/butaji.wordpress.com/591/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/butaji.wordpress.com/591/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/butaji.wordpress.com/591/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/butaji.wordpress.com/591/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=butaji.wordpress.com&blog=4404897&post=591&subd=butaji&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://butaji.wordpress.com/2009/09/03/%d0%b5%d1%89%d1%91-%d1%80%d0%b0%d0%b7-%d0%be-sharepoint-guidance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/fbea2e42e5c3b8c1918d0dc79a2203ce?s=96&amp;d=identicon&amp;r=G" medium="image">
			<media:title type="html">butaji</media:title>
		</media:content>

		<media:content url="http://butaji.files.wordpress.com/2009/09/sharepoint_guidance1.jpg" medium="image">
			<media:title type="html">sharepoint_guidance[1]</media:title>
		</media:content>
	</item>
		<item>
		<title>Анализ рынка ноутбуков с помощью Python</title>
		<link>http://butaji.wordpress.com/2009/08/31/%d0%b0%d0%bd%d0%b0%d0%bb%d0%b8%d0%b7-%d1%80%d1%8b%d0%bd%d0%ba%d0%b0-%d0%bd%d0%be%d1%83%d1%82%d0%b1%d1%83%d0%ba%d0%be%d0%b2-%d1%81-%d0%bf%d0%be%d0%bc%d0%be%d1%89%d1%8c%d1%8e-python/</link>
		<comments>http://butaji.wordpress.com/2009/08/31/%d0%b0%d0%bd%d0%b0%d0%bb%d0%b8%d0%b7-%d1%80%d1%8b%d0%bd%d0%ba%d0%b0-%d0%bd%d0%be%d1%83%d1%82%d0%b1%d1%83%d0%ba%d0%be%d0%b2-%d1%81-%d0%bf%d0%be%d0%bc%d0%be%d1%89%d1%8c%d1%8e-python/#comments</comments>
		<pubDate>Mon, 31 Aug 2009 05:09:43 +0000</pubDate>
		<dc:creator>butaji</dc:creator>
				<category><![CDATA[DataMining]]></category>
		<category><![CDATA[Notebook]]></category>
		<category><![CDATA[Price]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Ноутбук]]></category>
		<category><![CDATA[Цены]]></category>

		<guid isPermaLink="false">http://butaji.wordpress.com/2009/08/31/%d0%b0%d0%bd%d0%b0%d0%bb%d0%b8%d0%b7-%d1%80%d1%8b%d0%bd%d0%ba%d0%b0-%d0%bd%d0%be%d1%83%d1%82%d0%b1%d1%83%d0%ba%d0%be%d0%b2-%d1%81-%d0%bf%d0%be%d0%bc%d0%be%d1%89%d1%8c%d1%8e-python/</guid>
		<description><![CDATA[Введение
В этой статье я расскажу о состоянии на сегодняшнем российском рынке ноутбуков. Всю аналитику мы будем проводить с помощью кода на python. Думаю она будет полезна как тем, кто ищет ноутбук, так и тем, кто хочет потренироваться написанию на python.
Начнём
 Для анализа нам необходим набор данных, к сожалению я не смог обнаружить веб-сервисы у российских [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=butaji.wordpress.com&blog=4404897&post=588&subd=butaji&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><h2>Введение</h2>
<p>В этой статье я расскажу о состоянии на сегодняшнем российском рынке ноутбуков. Всю аналитику мы будем проводить с помощью кода на python. Думаю она будет полезна как тем, кто ищет ноутбук, так и тем, кто хочет потренироваться написанию на python.</p>
<h2>Начнём</h2>
<p><a href="http://butaji.files.wordpress.com/2009/08/diy034251.jpg"><img style="display:inline;border-width:0;margin:0 10px 0 0;" title="diy-03-425[1]" border="0" alt="diy-03-425[1]" align="left" src="http://butaji.files.wordpress.com/2009/08/diy034251_thumb.jpg?w=244&#038;h=184" width="244" height="184" /></a> Для анализа нам необходим набор данных, к сожалению я не смог обнаружить <a href="http://developer.ebay.com/">веб-сервисы</a> у российских он-лайн магазинов ноутбуков, поэтому мне пришлось скачать прайс-лист одного из них (я не стану называть его) и вытащить из него цены и основные параметры (по-моему мнению таковыми являются: частота процессора, диагональ монитора, объем оперативной памяти, размер жесткого диска и объем памяти на видео-карточке). Далее я провёл некоторый анализ по следующим вопросам:</p>
<ol>
<li>Средняя стоимость ноутбука </li>
<li>Усредненные параметры железа на ноутбуках </li>
<li>Самая дорогая/дешевая конфигурация ноутбука </li>
<li>Какой из параметров конфигурации больше всего влияет на его цену </li>
<li>Прогнозирование цены указанной конфигурации </li>
<li>График распределения конфигураций и цен </li>
</ol>
<h2></h2>
<h2></h2>
<h2>Lets code</h2>
<p>Прайс-лист, который мне удалось заполучить я сохранил в формате CVS, для работы с ним необходимо подключить модуль cvs:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:06cacbed-5c59-4f43-bd47-0054ff72760b" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<span style="color:#AA22FF;"><b>import</b></span>&#160;<span style="color:#0000FF;"><b>csv</b></span><br />
<span style="color:#AA22FF;"><b>import</b></span>&#160;<span style="color:#0000FF;"><b>re</b></span><br />
<span style="color:#AA22FF;"><b>import</b></span>&#160;<span style="color:#0000FF;"><b>random</b></span>
</div>
</div>
<p>Так же подключим модуль для работы со случайными числами и регулярными выражениями, которые в последствии нам понадобятся.</p>
<p>Далее создадим метод для чтения и получения ноутбуков:</p>
</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:3782faa3-fd6a-437c-b0eb-12919c112024" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<span style="color:#AA22FF;"><b>def</b></span>&#160;<span style="color:#00A000;">get_notebooks</span>():<br />
&#160;&#160;&#160;&#160;reader&#160;<span style="color:#666666;">=</span>&#160;csv<span style="color:#666666;">.</span>reader(<span style="color:#AA22FF;">open</span>(<span style="color:#BB4444;">&#8216;data.csv&#8217;</span>),&#160;delimiter<span style="color:#666666;">=</span><span style="color:#BB4444;">&#8216;;&#8217;</span>,&#160;quotechar<span style="color:#666666;">=</span><span style="color:#BB4444;">&#8216;|&#8217;</span>)<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>return</b></span>&#160;<span style="color:#AA22FF;">filter</span>(<span style="color:#AA22FF;"><b>lambda</b></span>&#160;x:&#160;x&#160;<span style="color:#666666;">!=</span>&#160;<span style="color:#AA22FF;">None</span>,&#160;<span style="color:#AA22FF;">map</span>(create_notebook,&#160;reader))
</div>
</div>
<p>здесь всё просто, мы читаем на файл с данными data.csv и фильтруем по результату функции create_notebook, т.к. не все позиции в прайсе являются ноутбуками, а вот кстати и она:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:5d660e7e-55e0-4ee1-b0bf-13dedc90f294" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<span style="color:#AA22FF;"><b>def</b></span>&#160;<span style="color:#00A000;">create_notebook</span>(raw):<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>try</b></span>:<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;notebook&#160;<span style="color:#666666;">=</span>&#160;Notebook()<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;notebook<span style="color:#666666;">.</span>vendor&#160;<span style="color:#666666;">=</span>&#160;raw[<span style="color:#666666;">0</span>]<span style="color:#666666;">.</span>split(<span style="color:#BB4444;">&#8216;&#160;&#8217;</span>)[<span style="color:#666666;">0</span>]<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;notebook<span style="color:#666666;">.</span>model&#160;<span style="color:#666666;">=</span>&#160;raw[<span style="color:#666666;">0</span>]<span style="color:#666666;">.</span>split(<span style="color:#BB4444;">&#8216;&#160;&#8217;</span>)[<span style="color:#666666;">1</span>]<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;notebook<span style="color:#666666;">.</span>cpu&#160;<span style="color:#666666;">=</span>&#160;getFloat(<span style="color:#BB4444;">r&raquo;(\d+)\,(\d+)\s\Г&raquo;</span>,&#160;raw[<span style="color:#666666;">0</span>]<span style="color:#666666;">.</span>split(<span style="color:#BB4444;">&#8216;/&#8217;</span>)[<span style="color:#666666;">0</span>])<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;notebook<span style="color:#666666;">.</span>monitor&#160;<span style="color:#666666;">=</span>&#160;getFloat(<span style="color:#BB4444;">r&raquo;(\d+)\.(\d+)\&raquo;&raquo;</span>,&#160;raw[<span style="color:#666666;">0</span>]<span style="color:#666666;">.</span>split(<span style="color:#BB4444;">&#8216;/&#8217;</span>)[<span style="color:#666666;">1</span>])<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;notebook<span style="color:#666666;">.</span>ram&#160;<span style="color:#666666;">=</span>&#160;getInt(<span style="color:#BB4444;">r&raquo;(\d+)\Mb&raquo;</span>,&#160;raw[<span style="color:#666666;">0</span>]<span style="color:#666666;">.</span>split(<span style="color:#BB4444;">&#8216;/&#8217;</span>)[<span style="color:#666666;">2</span>])<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;notebook<span style="color:#666666;">.</span>hdd&#160;<span style="color:#666666;">=</span>&#160;getInt(<span style="color:#BB4444;">r&raquo;(\d+)Gb&raquo;</span>,&#160;raw[<span style="color:#666666;">0</span>]<span style="color:#666666;">.</span>split(<span style="color:#BB4444;">&#8216;/&#8217;</span>)[<span style="color:#666666;">3</span>])<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;notebook<span style="color:#666666;">.</span>video&#160;<span style="color:#666666;">=</span>&#160;getInt(<span style="color:#BB4444;">r&raquo;(\d+)Mb&raquo;</span>,&#160;raw[<span style="color:#666666;">0</span>]<span style="color:#666666;">.</span>split(<span style="color:#BB4444;">&#8216;/&#8217;</span>)[<span style="color:#666666;">4</span>])<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;notebook<span style="color:#666666;">.</span>price&#160;<span style="color:#666666;">=</span>&#160;getInt(<span style="color:#BB4444;">r&raquo;(\d+)\s\руб.&raquo;</span>,&#160;raw[<span style="color:#666666;">1</span>])<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>return</b></span>&#160;notebook<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>except</b></span>&#160;<span style="color:#D2413A;"><b>Exception</b></span>,&#160;e:<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>return</b></span>&#160;<span style="color:#AA22FF;">None</span>
</div>
</div>
<p>Как вы можете заметить, я решил не обращать внимания на вендора, модель и тип процессора (здесь конечно не всё так просто, но тем не менее), а и ещё &#8211; в данном методе присутствуют мои кастомные функции-помощники:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:c79507b7-6596-43d1-9aac-a11e7711745a" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<span style="color:#AA22FF;"><b>def</b></span>&#160;<span style="color:#00A000;">getFloat</span>(regex,&#160;raw):<br />
&#160;&#160;&#160;&#160;m&#160;<span style="color:#666666;">=</span>&#160;re<span style="color:#666666;">.</span>search(regex,&#160;raw)<span style="color:#666666;">.</span>groups()<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>return</b></span>&#160;<span style="color:#AA22FF;">float</span>(m[<span style="color:#666666;">0</span>]&#160;<span style="color:#666666;">+</span>&#160;<span style="color:#BB4444;">&#8216;.&#8217;</span>&#160;<span style="color:#666666;">+</span>&#160;m[<span style="color:#666666;">1</span>])</p>
<p><span style="color:#AA22FF;"><b>def</b></span>&#160;<span style="color:#00A000;">getInt</span>(regex,&#160;raw):<br />
&#160;&#160;&#160;&#160;m&#160;<span style="color:#666666;">=</span>&#160;re<span style="color:#666666;">.</span>search(regex,&#160;raw)<span style="color:#666666;">.</span>groups()<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>return</b></span>&#160;<span style="color:#AA22FF;">int</span>(m[<span style="color:#666666;">0</span>])
</div>
</div>
<p>Хочу заметить, что писать для питона лучше всего в стиле наборов данных, а не ООП структур, в связи с тем, что язык больше располагает к такому стилю, однако для наведения некоторого порядка в нашей доменной области (ноутбуки), я ввёл класс, как вы могли заметить выше (notebook = Notebook())</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:379c08af-4ff7-40fb-a4f7-cdfe6e0f1814" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<span style="color:#AA22FF;"><b>class</b></span>&#160;<span style="color:#0000FF;">Notebook</span>:<br />
&#160;&#160;&#160;<span style="color:#AA22FF;"><b>pass</b></span>
</div>
</div>
<p>Отлично, теперь у нас есть структура в памяти и она готова для анализа (<em>2005 различных конфигураций и их стоимость</em>), что же начнём:</p>
</p>
<p><strong>Средняя стоимость ноутбука:</strong> </p>
</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:18fcd376-b104-4aa9-bf1e-b97e360befa7" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<span style="color:#AA22FF;"><b>def</b></span>&#160;<span style="color:#00A000;">get_avg_price</span>():<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>print</b></span>&#160;<span style="color:#AA22FF;">sum</span>([n<span style="color:#666666;">.</span>price&#160;<span style="color:#AA22FF;"><b>for</b></span>&#160;n&#160;<span style="color:#AA22FF;"><b>in</b></span>&#160;get_notebooks()])<span style="color:#666666;">/</span><span style="color:#AA22FF;">len</span>(get_notebooks())
</div>
</div>
<p>Исполняем код и видим, что 1K$, как стандарт для компьютера всё ещё в силе:</p>
</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:4a6517cb-5756-4ae9-9e6d-ba929393e6c9" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
&gt;&gt;&#160;get_avg_price()<br />
<span style="color:#009999;">34574</span>
</div>
</div>
<p><strong>Усредненные параметры железа на ноутбуках </strong></p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:dbac7615-63ce-431e-956e-5ca4af3ea668" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<span style="color:#AA22FF;"><b>def</b></span>&#160;<span style="color:#00A000;">get_avg_parameters</span>():<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>print</b></span>&#160;<span style="color:#BB4444;">&laquo;cpu&#160;{0}&raquo;</span><span style="color:#666666;">.</span>format(<span style="color:#AA22FF;">sum</span>([n<span style="color:#666666;">.</span>cpu&#160;<span style="color:#AA22FF;"><b>for</b></span>&#160;n&#160;<span style="color:#AA22FF;"><b>in</b></span>&#160;get_notebooks()])<span style="color:#666666;">/</span><span style="color:#AA22FF;">len</span>(get_notebooks()))<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>print</b></span>&#160;<span style="color:#BB4444;">&laquo;monitor&#160;{0}&raquo;</span><span style="color:#666666;">.</span>format(<span style="color:#AA22FF;">sum</span>([n<span style="color:#666666;">.</span>monitor&#160;<span style="color:#AA22FF;"><b>for</b></span>&#160;n&#160;<span style="color:#AA22FF;"><b>in</b></span>&#160;get_notebooks()])<span style="color:#666666;">/</span><span style="color:#AA22FF;">len</span>(get_notebooks()))<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>print</b></span>&#160;<span style="color:#BB4444;">&laquo;ram&#160;{0}&raquo;</span><span style="color:#666666;">.</span>format(<span style="color:#AA22FF;">sum</span>([n<span style="color:#666666;">.</span>ram&#160;<span style="color:#AA22FF;"><b>for</b></span>&#160;n&#160;<span style="color:#AA22FF;"><b>in</b></span>&#160;get_notebooks()])<span style="color:#666666;">/</span><span style="color:#AA22FF;">len</span>(get_notebooks()))<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>print</b></span>&#160;<span style="color:#BB4444;">&laquo;hdd&#160;{0}&raquo;</span><span style="color:#666666;">.</span>format(<span style="color:#AA22FF;">sum</span>([n<span style="color:#666666;">.</span>hdd&#160;<span style="color:#AA22FF;"><b>for</b></span>&#160;n&#160;<span style="color:#AA22FF;"><b>in</b></span>&#160;get_notebooks()])<span style="color:#666666;">/</span><span style="color:#AA22FF;">len</span>(get_notebooks()))<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>print</b></span>&#160;<span style="color:#BB4444;">&laquo;video&#160;{0}&raquo;</span><span style="color:#666666;">.</span>format(<span style="color:#AA22FF;">sum</span>([n<span style="color:#666666;">.</span>video&#160;<span style="color:#AA22FF;"><b>for</b></span>&#160;n&#160;<span style="color:#AA22FF;"><b>in</b></span>&#160;get_notebooks()])<span style="color:#666666;">/</span><span style="color:#AA22FF;">len</span>(get_notebooks()))
</div>
</div>
</p>
<p>Та-да, и в наших руках усредненная конфигурация:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:25687bbf-6b61-4ed9-b53e-ffd9e97a44e2" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
&gt;&gt;&#160;get_avg_parameters()<br />
cpu&#160;<span style="color:#009999;">2.0460798005</span><br />
monitor&#160;<span style="color:#009999;">14.6333167082</span><br />
ram&#160;<span style="color:#009999;">2448</span><br />
hdd&#160;<span style="color:#009999;">243</span><br />
video&#160;<span style="color:#009999;">289</span>
</div>
</div>
<p><strong>Самая дорогая/дешевая конфигурация ноутбука:</strong></p>
<p>Функции идентичны, за исключением функций min/max</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:2affb902-918d-460f-8dc0-1e0c4c159367" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<span style="color:#AA22FF;"><b>def</b></span>&#160;<span style="color:#00A000;">get_max_priced_notebook</span>():<br />
&#160;&#160;&#160;&#160;maxprice&#160;<span style="color:#666666;">=</span>&#160;<span style="color:#AA22FF;">max</span>([n<span style="color:#666666;">.</span>price&#160;<span style="color:#AA22FF;"><b>for</b></span>&#160;n&#160;<span style="color:#AA22FF;"><b>in</b></span>&#160;get_notebooks()])<br />
&#160;&#160;&#160;&#160;maxconfig&#160;<span style="color:#666666;">=</span>&#160;<span style="color:#AA22FF;">filter</span>(<span style="color:#AA22FF;"><b>lambda</b></span>&#160;x:&#160;x<span style="color:#666666;">.</span>price&#160;<span style="color:#666666;">==</span>&#160;maxprice,&#160;get_notebooks())[<span style="color:#666666;">0</span>]<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>print</b></span>&#160;<span style="color:#BB4444;">&laquo;cpu&#160;{0}&raquo;</span><span style="color:#666666;">.</span>format(maxconfig<span style="color:#666666;">.</span>cpu)<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>print</b></span>&#160;<span style="color:#BB4444;">&laquo;monitor&#160;{0}&raquo;</span><span style="color:#666666;">.</span>format(maxconfig<span style="color:#666666;">.</span>monitor)<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>print</b></span>&#160;<span style="color:#BB4444;">&laquo;ram&#160;{0}&raquo;</span><span style="color:#666666;">.</span>format(maxconfig<span style="color:#666666;">.</span>ram)<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>print</b></span>&#160;<span style="color:#BB4444;">&laquo;hdd&#160;{0}&raquo;</span><span style="color:#666666;">.</span>format(maxconfig<span style="color:#666666;">.</span>hdd)<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>print</b></span>&#160;<span style="color:#BB4444;">&laquo;video&#160;{0}&raquo;</span><span style="color:#666666;">.</span>format(maxconfig<span style="color:#666666;">.</span>video)<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>print</b></span>&#160;<span style="color:#BB4444;">&laquo;price&#160;{0}&raquo;</span><span style="color:#666666;">.</span>format(maxconfig<span style="color:#666666;">.</span>price)
</div>
</div>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:7bbe3eeb-09bf-425e-bfa5-8fa6213ae5ff" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
&gt;&gt;&#160;get_max_priced_notebook()<br />
cpu&#160;<span style="color:#009999;">2.26</span><br />
monitor&#160;<span style="color:#009999;">18.4</span><br />
ram&#160;<span style="color:#009999;">4096</span><br />
hdd&#160;<span style="color:#009999;">500</span><br />
video&#160;<span style="color:#009999;">1024</span><br />
price&#160;<span style="color:#009999;">181660</span>
</div>
</div>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:8216f0f7-224f-4708-875f-d4ec51cb3cdc" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
&gt;&gt;&#160;get_min_priced_notebook()<br />
cpu&#160;<span style="color:#009999;">1.6</span><br />
monitor&#160;<span style="color:#009999;">8.9</span><br />
ram&#160;<span style="color:#009999;">512</span><br />
hdd&#160;<span style="color:#009999;">8</span><br />
video&#160;<span style="color:#009999;">128</span><br />
price&#160;<span style="color:#009999;">8090</span>
</div>
</div>
<p><strong>Какой из параметров конфигурации больше всего влияет на его цену </strong></p>
<p>Очень интересно было бы узнать, за какой из параметров конфигурации мы платим больше всего денег. Прикинув, я предположил, что скорее всего это диагональ монитора и частота процессора, ну что же, думаю, что стоит проверить это.</p>
<p>Для начала наш набор параметров конфигурации стоит немного модифицировать. В связи с тем, что единицы измерения различных параметров различны в своём порядке, нам необходимо привести их к одному знаменателю, т.е. нормализовать их. Итак, приступим:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:5208e42c-3412-4aa7-872e-3305180a4a4d" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<span style="color:#AA22FF;"><b>def</b></span>&#160;<span style="color:#00A000;">normalized_set_of_notebooks</span>():<br />
&#160;&#160;&#160;&#160;notebooks&#160;<span style="color:#666666;">=</span>&#160;get_notebooks()<br />
&#160;&#160;&#160;&#160;cpu&#160;<span style="color:#666666;">=</span>&#160;<span style="color:#AA22FF;">max</span>([n<span style="color:#666666;">.</span>cpu&#160;<span style="color:#AA22FF;"><b>for</b></span>&#160;n&#160;<span style="color:#AA22FF;"><b>in</b></span>&#160;notebooks])<br />
&#160;&#160;&#160;&#160;monitor&#160;<span style="color:#666666;">=</span>&#160;<span style="color:#AA22FF;">max</span>([n<span style="color:#666666;">.</span>monitor&#160;<span style="color:#AA22FF;"><b>for</b></span>&#160;n&#160;<span style="color:#AA22FF;"><b>in</b></span>&#160;notebooks])<br />
&#160;&#160;&#160;&#160;ram&#160;<span style="color:#666666;">=</span>&#160;<span style="color:#AA22FF;">max</span>([n<span style="color:#666666;">.</span>ram&#160;<span style="color:#AA22FF;"><b>for</b></span>&#160;n&#160;<span style="color:#AA22FF;"><b>in</b></span>&#160;notebooks])<br />
&#160;&#160;&#160;&#160;hdd&#160;<span style="color:#666666;">=</span>&#160;<span style="color:#AA22FF;">max</span>([n<span style="color:#666666;">.</span>hdd&#160;<span style="color:#AA22FF;"><b>for</b></span>&#160;n&#160;<span style="color:#AA22FF;"><b>in</b></span>&#160;notebooks])<br />
&#160;&#160;&#160;&#160;video&#160;<span style="color:#666666;">=</span>&#160;<span style="color:#AA22FF;">max</span>([n<span style="color:#666666;">.</span>video&#160;<span style="color:#AA22FF;"><b>for</b></span>&#160;n&#160;<span style="color:#AA22FF;"><b>in</b></span>&#160;notebooks])<br />
&#160;&#160;&#160;&#160;rows&#160;<span style="color:#666666;">=</span>&#160;<span style="color:#AA22FF;">map</span>(<span style="color:#AA22FF;"><b>lambda</b></span>&#160;n&#160;:&#160;[n<span style="color:#666666;">.</span>cpu<span style="color:#666666;">/</span>cpu,&#160;n<span style="color:#666666;">.</span>monitor<span style="color:#666666;">/</span>monitor,&#160;<span style="color:#AA22FF;">float</span>(n<span style="color:#666666;">.</span>ram)<span style="color:#666666;">/</span>ram,&#160;<span style="color:#AA22FF;">float</span>(n<span style="color:#666666;">.</span>hdd)<span style="color:#666666;">/</span>hdd,&#160;<span style="color:#AA22FF;">float</span>(n<span style="color:#666666;">.</span>video)<span style="color:#666666;">/</span>video,&#160;n<span style="color:#666666;">.</span>price],&#160;notebooks)<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>return</b></span>&#160;rows
</div>
</div>
<p>В данной функции я нахожу максимальные значения для каждого из параметров, после этого формирую результирующий список ноутбуков, в котором каждый из параметров представлен в виде коэффициента (его значение будет колебаться от 0 до 1), показывающего отношение его параметра к максимальному значению в наборе, к примеру память в 2048Mb даст конфигурации коэффициент в ram = 0.5 (2048/4056).</p>
<p>Вклад каждого из параметров мы будем считать в рублях, для наглядности, хранить эти веса мы будет в наборе:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:4c93a812-db6d-4bc1-8e28-75bc3fa0e1a9" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<span style="color:#008800;"><i>#cpu,&#160;monitor,&#160;ram,&#160;hdd,&#160;video</i></span><br />
koes&#160;<span style="color:#666666;">=</span>&#160;[<span style="color:#666666;">0</span>,&#160;<span style="color:#666666;">0</span>,&#160;<span style="color:#666666;">0</span>,&#160;<span style="color:#666666;">0</span>,&#160;<span style="color:#666666;">0</span>]
</div>
</div>
<p>Я предлагаю исчислять эти коэффициенты для каждой конфигурации, а после этого определить среднюю величину всех коэффициентов, что даст нам усредненные данные о весе каждого из элементов конфигурации.</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:3c412005-9ba3-404e-bfd2-93e8a1b8675e" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<span style="color:#AA22FF;"><b>def</b></span>&#160;<span style="color:#00A000;">analyze_params</span>(parameters):<br />
&#160;&#160;&#160;&#160;koeshistory&#160;<span style="color:#666666;">=</span>&#160;[]<br />
&#160;&#160;&#160;&#160;<span style="color:#008800;"><i>#наши&#160;ноутбуки</i></span><br />
&#160;&#160;&#160;&#160;notes&#160;<span style="color:#666666;">=</span>&#160;normalized_set_of_notebooks()<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>for</b></span>&#160;i&#160;<span style="color:#AA22FF;"><b>in</b></span>&#160;<span style="color:#AA22FF;">range</span>(<span style="color:#AA22FF;">len</span>(notes)):<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;koes&#160;<span style="color:#666666;">=</span>&#160;[<span style="color:#666666;">0</span>,&#160;<span style="color:#666666;">0</span>,&#160;<span style="color:#666666;">0</span>,&#160;<span style="color:#666666;">0</span>,&#160;<span style="color:#666666;">0</span>]<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<span style="color:#008800;"><i>#устанавливаем&#160;коэффициенты</i></span><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;set_koes(notes[i],&#160;koes)<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<span style="color:#008800;"><i>#сохраняем&#160;историю&#160;коэффициентов</i></span><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;koeshistory<span style="color:#666666;">.</span>extend(koes)<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<span style="color:#008800;"><i>#показываем&#160;прогресс&#160;выполнения</i></span><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>if</b></span>&#160;(i&#160;<span style="color:#666666;">%</span>&#160;<span style="color:#666666;">100</span>&#160;<span style="color:#666666;">==</span>&#160;<span style="color:#666666;">0</span>):<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>print</b></span>&#160;i<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>print</b></span>&#160;koes
</div>
</div>
<p>Как же мы будет устанавливать коэффициенты для каждого элемента конфигурации? Мой способ заключается в следующем: </p>
<ul>
<li><em>нам необходимо в случайном порядке наращивать, либо уменьшать значение одного из коэффициентов</em> </li>
<li><em>после чего анализировать, приблизились ли мы к цене за конфигурацию, при умножении вектора параметров на вектор коэффициентов (напомню, что в нашем случае это рубли)</em> </li>
<li><em>если приближение состоялось, ты мы повторяем данное действие, если же нет, то отменяем его</em> </li>
<li><em>повторять данный порядок до той степени, пока не приблизимся к нашей цене с установленной нами точностью</em> </li>
</ul>
<p>Вот реализация данного алгоритма:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:733fce97-3c51-4e18-8150-06dac8a3d02e" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<span style="color:#AA22FF;"><b>def</b></span>&#160;<span style="color:#00A000;">set_koes</span>(note,&#160;koes,&#160;error<span style="color:#666666;">=</span><span style="color:#666666;">500</span>):<br />
&#160;&#160;&#160;&#160;price&#160;<span style="color:#666666;">=</span>&#160;get_price(note,&#160;koes)<br />
&#160;&#160;&#160;&#160;lasterror&#160;<span style="color:#666666;">=</span>&#160;<span style="color:#AA22FF;">abs</span>(note[<span style="color:#666666;">5</span>]&#160;<span style="color:#666666;">-</span>&#160;price)<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>while</b></span>&#160;(lasterror&#160;<span style="color:#666666;">&gt;</span>&#160;error):<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;k&#160;<span style="color:#666666;">=</span>&#160;random<span style="color:#666666;">.</span>randint(<span style="color:#666666;">0</span>,<span style="color:#666666;">4</span>)<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<span style="color:#008800;"><i>#изменяем&#160;коэффицинт</i></span><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;inc&#160;<span style="color:#666666;">=</span>&#160;(random<span style="color:#666666;">.</span>random()<span style="color:#666666;">*</span><span style="color:#666666;">2</span>&#160;<span style="color:#666666;">-</span>&#160;<span style="color:#666666;">1</span>)&#160;<span style="color:#666666;">*</span>&#160;(error<span style="color:#666666;">*</span>(<span style="color:#666666;">1</span>&#160;<span style="color:#666666;">-</span>&#160;error<span style="color:#666666;">/</span>lasterror))<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;koes[k]&#160;<span style="color:#666666;">+=</span>&#160;inc<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<span style="color:#008800;"><i>#не&#160;даём&#160;коэффициенту&#160;стать&#160;меньше&#160;нуля</i></span><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>if</b></span>&#160;(koes[k]&#160;<span style="color:#666666;">&lt;</span>&#160;<span style="color:#666666;">0</span>):&#160;koes[k]&#160;<span style="color:#666666;">=</span>&#160;<span style="color:#666666;">0</span><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<span style="color:#008800;"><i>#получаем&#160;цену&#160;при&#160;учёте&#160;коэффициентов</i></span><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;price&#160;<span style="color:#666666;">=</span>&#160;get_price(note,&#160;koes)<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<span style="color:#008800;"><i>#получаем&#160;текущую&#160;ошибку</i></span><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;curerror&#160;<span style="color:#666666;">=</span>&#160;<span style="color:#AA22FF;">abs</span>(note[<span style="color:#666666;">5</span>]&#160;<span style="color:#666666;">-</span>&#160;price)<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<span style="color:#008800;"><i>#проверяем,&#160;приблизились&#160;ли&#160;мы&#160;к&#160;цене,&#160;казанной&#160;в&#160;прайсе</i></span><br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>if</b></span>&#160;(lasterror&#160;<span style="color:#666666;">&lt;</span>&#160;curerror):<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;koes[k]&#160;<span style="color:#666666;">-=</span>&#160;inc<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>else</b></span>:<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;lasterror&#160;<span style="color:#666666;">=</span>&#160;curerror
</div>
</div>
<p>inc – переменная отвечающая за цвеличение/уменьшение коэффициента, способ её вычисления объесняется тем, что данное значение должно быть тем больше, чем больше разница в ошибке, для быстрого и более точного приближения к желаемому результату.</p>
<p>Умножение векторов для получения цены выглядит следующим образом:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:f44012d4-b13f-4640-b570-08f5af8bc629" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<span style="color:#AA22FF;"><b>def</b></span>&#160;<span style="color:#00A000;">get_price</span>(note,&#160;koes):<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>return</b></span>&#160;<span style="color:#AA22FF;">sum</span>([note[i]<span style="color:#666666;">*</span>koes[i]&#160;<span style="color:#AA22FF;"><b>for</b></span>&#160;i&#160;<span style="color:#AA22FF;"><b>in</b></span>&#160;<span style="color:#AA22FF;">range</span>(<span style="color:#666666;">5</span>)])
</div>
</div>
<p>Пришла пора выполнить анализ:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:92322cc2-458a-4f09-91fe-e334a9915036" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
&gt;&gt;&#160;analyze_params()<br />
cpu,&#160;monitor,&#160;ram,&#160;hdd,&#160;video</p>
<p>[<span style="color:#009999;">15455.60675667684</span>,&#160;<span style="color:#009999;">20980.560483811361</span>,&#160;<span style="color:#009999;">12782.535270304281</span>,&#160;<span style="color:#009999;">17819.904629585861</span>,&#160;<span style="color:#009999;">14677.889529808042</span>]
</div>
</div>
<p>Данный набор мы получили, благодаря усреднению коэффициентов, полученных для каждой из конфигураций:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:c4cf2b5d-58dd-432e-83ab-17cfac61f7cf" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<span style="color:#AA22FF;"><b>def</b></span>&#160;<span style="color:#00A000;">get_avg_koes</span>(koeshistory):<br />
&#160;&#160;&#160;&#160;koes&#160;<span style="color:#666666;">=</span>&#160;[<span style="color:#666666;">0</span>,&#160;<span style="color:#666666;">0</span>,&#160;<span style="color:#666666;">0</span>,&#160;<span style="color:#666666;">0</span>,&#160;<span style="color:#666666;">0</span>]<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>for</b></span>&#160;row&#160;<span style="color:#AA22FF;"><b>in</b></span>&#160;koeshistory:<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>for</b></span>&#160;i&#160;<span style="color:#AA22FF;"><b>in</b></span>&#160;<span style="color:#AA22FF;">range</span>(<span style="color:#666666;">5</span>):<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;koes[i]&#160;<span style="color:#666666;">+=</span>&#160;koeshistory[i]<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>for</b></span>&#160;i&#160;<span style="color:#AA22FF;"><b>in</b></span>&#160;<span style="color:#AA22FF;">range</span>(<span style="color:#666666;">5</span>):<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;koes[i]&#160;<span style="color:#666666;">/=</span>&#160;<span style="color:#AA22FF;">len</span>(koeshistory)<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>return</b></span>&#160;koes
</div>
</div>
<p>Итак, у нас получился желаемый набор, что же мы можем сказать из этих цифр, а можем мы составить рейтинг параметров: </p>
<ol>
<li>Диагональ монитора </li>
<li>Объем жесткого диска </li>
<li>Частота процессора </li>
<li>Объем видео-карточки </li>
<li>Объем оперативной памяти </li>
</ol>
<p>Хотелось бы отметить, что это далеко не идеальный вариант, и у вас могут получится иные результаты, однако, моё предположение, о том, что частота процессора и диагональ дисплея наиболее важные параметры в конфигурации, частично подтвердились.</p>
<p><strong>Прогнозирование цены указанной конфигурации </strong></p>
<p>Классно бы было, имея такой богатый набор данных, уметь прогнозировать цену на заданную конфигурацию. Этим мы и займемся.</p>
<p>Для начала преобразуем нашу коллекцию ноутбуков в список:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:2c7be1e5-7b86-447f-b508-cec9d0462e5e" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<span style="color:#AA22FF;"><b>def</b></span>&#160;<span style="color:#00A000;">get_notebooks_list</span>():<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>return</b></span>&#160;<span style="color:#AA22FF;">map</span>(<span style="color:#AA22FF;"><b>lambda</b></span>&#160;n:&#160;[n<span style="color:#666666;">.</span>cpu,&#160;n<span style="color:#666666;">.</span>monitor,&#160;n<span style="color:#666666;">.</span>ram,&#160;n<span style="color:#666666;">.</span>hdd,&#160;n<span style="color:#666666;">.</span>video,&#160;n<span style="color:#666666;">.</span>price],&#160;get_notebooks())
</div>
</div>
<p>Далее нам понадобиться функция, способная определить расстояние между двумя векторами, хорошим вариантом я вижу функцию эвклидова расстояния:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:05774a88-aa3d-4e3f-aad5-826b75aef396" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<span style="color:#AA22FF;"><b>def</b></span>&#160;<span style="color:#00A000;">euclidean</span>(v1,&#160;v2):<br />
&#160;&#160;&#160;&#160;d&#160;<span style="color:#666666;">=</span>&#160;<span style="color:#666666;">0.0</span><br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>for</b></span>&#160;i&#160;<span style="color:#AA22FF;"><b>in</b></span>&#160;<span style="color:#AA22FF;">range</span>(<span style="color:#AA22FF;">len</span>(v1)):<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;d<span style="color:#666666;">+=</span>(v1[i]&#160;<span style="color:#666666;">-</span>&#160;v2[i])<span style="color:#666666;">**</span><span style="color:#666666;">2</span>;<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>return</b></span>&#160;math<span style="color:#666666;">.</span>sqrt(d)
</div>
</div>
<p>Корень из суммы квадратов разностей довольно таки наглядно и эффективно показывает нам насколько один вектор различен от другого. Чем же полезна для нас данная функция? Всё просто, когда мы получим вектор, с интересующими нас параметрами, мы пробежимся по всей коллекции нашего набора и найдём ближайшего соседа, а его стоимость мы уже знаем, отлично! Вот как мы это сделаем:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:0d87fb01-bf20-4e9c-866a-bd1007fdadbd" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<span style="color:#AA22FF;"><b>def</b></span>&#160;<span style="color:#00A000;">getdistances</span>(data,&#160;vec1):<br />
&#160;&#160;&#160;&#160;distancelist<span style="color:#666666;">=</span>[]<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>for</b></span>&#160;i&#160;<span style="color:#AA22FF;"><b>in</b></span>&#160;<span style="color:#AA22FF;">range</span>(<span style="color:#AA22FF;">len</span>(data)):<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;vec2&#160;<span style="color:#666666;">=</span>&#160;data[i]<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;distancelist<span style="color:#666666;">.</span>append((euclidean(vec1,vec2),i))<br />
&#160;&#160;&#160;&#160;distancelist<span style="color:#666666;">.</span>sort()<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>return</b></span>&#160;distancelist
</div>
</div>
<p>Далее, можно немного усложнить задачу, а так же точность предоставляемых данных. Для этого мы введем функцию, использующую классификацию <a href="http://www.machinelearning.ru/wiki/index.php?title=%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_k_%D0%B2%D0%B7%D0%B2%D0%B5%D1%88%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B1%D0%BB%D0%B8%D0%B6%D0%B0%D0%B9%D1%88%D0%B8%D1%85_%D1%81%D0%BE%D1%81%D0%B5%D0%B4%D0%B5%D0%B9_(%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80)">методом k взвешенных ближайших соседей</a>:</p>
<blockquote><p><img alt="K" src="http://www.machinelearning.ru/mimetex/?K" /> взвешенных ближайших соседей &#8211; это <a href="http://www.machinelearning.ru/wiki/index.php?title=%D0%9C%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B9_%D0%BA%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%82%D0%BE%D1%80">метрический алгоритм классификации</a>, основанный на оценивании сходства объектов. Классифицируемый объект относится к тому классу, которому принадлежат ближайшие к нему объекты <a href="http://www.machinelearning.ru/wiki/index.php?title=%D0%92%D1%8B%D0%B1%D0%BE%D1%80%D0%BA%D0%B0">обучающей выборки</a>.</p>
</blockquote>
<p>Ну и взять среднее значение среди некоторого количества ближайших соседей, что сведет на нет влияние цен вендора, либо специфичности конфигурации:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:e2bf4f7a-9c7b-4693-887d-4c168f125887" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<span style="color:#AA22FF;"><b>def</b></span>&#160;<span style="color:#00A000;">knnestimate</span>(data,vec1,k<span style="color:#666666;">=</span><span style="color:#666666;">3</span>):<br />
&#160;&#160;&#160;&#160;dlist&#160;<span style="color:#666666;">=</span>&#160;getdistances(data,&#160;vec1)<br />
&#160;&#160;&#160;&#160;avg&#160;<span style="color:#666666;">=</span>&#160;<span style="color:#666666;">0.0</span><br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>for</b></span>&#160;i&#160;<span style="color:#AA22FF;"><b>in</b></span>&#160;<span style="color:#AA22FF;">range</span>(k):<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;idx&#160;<span style="color:#666666;">=</span>&#160;dlist[i][<span style="color:#666666;">1</span>]<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;avg&#160;<span style="color:#666666;">+=</span>data[idx][<span style="color:#666666;">5</span>]<br />
&#160;&#160;&#160;&#160;avg&#160;<span style="color:#666666;">/=</span>&#160;k<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>return</b></span>&#160;avg
</div>
</div>
<p>*последние 3 алгоритма взяты из книги <a href="http://www.books.ru/shop/books/586615?partner=butaji">Сегерана Тоби “Программируем коллективный разум”</a></p>
<p>И что же мы получаем:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:6206cf21-acde-4b1f-8adb-419e7c7b106f" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
&gt;&gt;&#160;knnestimate(get_notebooks_list(),&#160;[<span style="color:#009999;">2.4</span>,&#160;<span style="color:#009999;">17</span>,&#160;<span style="color:#009999;">3062</span>,&#160;<span style="color:#009999;">250</span>,&#160;<span style="color:#009999;">512</span>])<br />
<span style="color:#009999;">31521.0</span></p>
<p>&gt;&gt;&#160;knnestimate(get_notebooks_list(),&#160;[<span style="color:#009999;">2.0</span>,&#160;<span style="color:#009999;">15</span>,&#160;<span style="color:#009999;">2048</span>,&#160;<span style="color:#009999;">160</span>,&#160;<span style="color:#009999;">256</span>])<br />
<span style="color:#009999;">27259.0</span><br />
&gt;&gt;&#160;knnestimate(get_notebooks_list(),&#160;[<span style="color:#009999;">2.0</span>,&#160;<span style="color:#009999;">15</span>,&#160;<span style="color:#009999;">2048</span>,&#160;<span style="color:#009999;">160</span>,&#160;<span style="color:#009999;">128</span>])<br />
<span style="color:#009999;">20848.0</span>
</div>
</div>
<p>Цены рыночные и этого вполне достаточно, хотя мы абсолютно не учитываем в этой реализации, к примеру частоту процессора и диагональ монитора (для этого нам необходимо добавить в функцию сравнения векторов их веса , которые мы вычисляли в предыдущем пункте)</p>
<p><strong>График распределения конфигураций и цен </strong></p>
<p>Хочется объять картину распределения целиком, т.е. нарисовать распределение конфигураций и цен на рынке. Ок, сделаем это.</p>
<p>Для начала надо поставить библиотеку <a href="http://matplotlib.sourceforge.net/users/installing.html">matplotlib</a>. Далее подключить её к нашему проекту:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:2e6a5184-4954-479d-8575-7f9403a572c7" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<span style="color:#AA22FF;"><b>from</b></span>&#160;<span style="color:#0000FF;"><b>pylab</b></span>&#160;<span style="color:#AA22FF;"><b>import</b></span>&#160;<span style="color:#666666;">*</span>
</div>
</div>
<p>Так же нам понадобится создать два набора данных, для оси абсцисс и ординат:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:c348a4cd-b058-4fea-8d5f-b1e4f5e3651d" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<span style="color:#AA22FF;"><b>def</b></span>&#160;<span style="color:#00A000;">power_of_notebooks_config</span>():<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>return</b></span>&#160;<span style="color:#AA22FF;">map</span>(<span style="color:#AA22FF;"><b>lambda</b></span>&#160;x:&#160;x[<span style="color:#666666;">0</span>]<span style="color:#666666;">*</span>x[<span style="color:#666666;">1</span>]<span style="color:#666666;">*</span>x[<span style="color:#666666;">2</span>]<span style="color:#666666;">*</span>x[<span style="color:#666666;">3</span>]<span style="color:#666666;">*</span>x[<span style="color:#666666;">4</span>],&#160;normalized_set_of_notebooks())<br />
<span style="color:#AA22FF;"><b>def</b></span>&#160;<span style="color:#00A000;">config_prices</span>():<br />
&#160;&#160;&#160;&#160;<span style="color:#AA22FF;"><b>return</b></span>&#160;<span style="color:#AA22FF;">map</span>(<span style="color:#AA22FF;"><b>lambda</b></span>&#160;x:&#160;x[<span style="color:#666666;">5</span>],&#160;normalized_set_of_notebooks())
</div>
</div>
<p>И функцию, в которой мы построим график распределения:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:a94c35e2-30aa-4d52-a3e6-3afdf59f8423" class="wlWriterEditableSmartContent">
<div style="font-family:consolas,lucida console,courier,monospace;">
<span style="color:#AA22FF;"><b>def</b></span>&#160;<span style="color:#00A000;">draw_market</span>():<br />
&#160;&#160;&#160;&#160;plot(config_prices(),power_of_notebooks_config(),<span style="color:#BB4444;">&#8216;bo&#8217;</span>,&#160;linewidth<span style="color:#666666;">=</span><span style="color:#666666;">1.0</span>)</p>
<p>&#160;&#160;&#160;&#160;xlabel(<span style="color:#BB4444;">&#8216;price&#160;(Rub)&#8217;</span>)<br />
&#160;&#160;&#160;&#160;ylabel(<span style="color:#BB4444;">&#8216;config_power&#8217;</span>)<br />
&#160;&#160;&#160;&#160;title(<span style="color:#BB4444;">&#8216;Russian&#160;Notebooks&#160;Market&#8217;</span>)<br />
&#160;&#160;&#160;&#160;grid(<span style="color:#AA22FF;">True</span>)<br />
&#160;&#160;&#160;&#160;show()
</div>
</div>
<p>И что же мы получаем:</p>
<p><a href="http://butaji.files.wordpress.com/2009/08/notes.png"><img style="display:inline;border-width:0;" title="notes" border="0" alt="notes" src="http://butaji.files.wordpress.com/2009/08/notes_thumb.png?w=495&#038;h=378" width="495" height="378" /></a> </p>
</p>
<h2>В завершение</h2>
<p>Итак, у нас получилось провести небольшой анализ российского рынка ноутбуков, а так же немного проиграться с python. </p>
<p>Исходный код проекта доступен по адресу:</p>
<p><a href="http://code.google.com/p/runm/source/checkout">http://code.google.com/p/runm/source/checkout</a></p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/butaji.wordpress.com/588/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/butaji.wordpress.com/588/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/butaji.wordpress.com/588/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/butaji.wordpress.com/588/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/butaji.wordpress.com/588/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/butaji.wordpress.com/588/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/butaji.wordpress.com/588/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/butaji.wordpress.com/588/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/butaji.wordpress.com/588/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/butaji.wordpress.com/588/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=butaji.wordpress.com&blog=4404897&post=588&subd=butaji&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://butaji.wordpress.com/2009/08/31/%d0%b0%d0%bd%d0%b0%d0%bb%d0%b8%d0%b7-%d1%80%d1%8b%d0%bd%d0%ba%d0%b0-%d0%bd%d0%be%d1%83%d1%82%d0%b1%d1%83%d0%ba%d0%be%d0%b2-%d1%81-%d0%bf%d0%be%d0%bc%d0%be%d1%89%d1%8c%d1%8e-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/fbea2e42e5c3b8c1918d0dc79a2203ce?s=96&amp;d=identicon&amp;r=G" medium="image">
			<media:title type="html">butaji</media:title>
		</media:content>

		<media:content url="http://butaji.files.wordpress.com/2009/08/diy034251_thumb.jpg" medium="image">
			<media:title type="html">diy-03-425[1]</media:title>
		</media:content>

		<media:content url="http://www.machinelearning.ru/mimetex/?K" medium="image">
			<media:title type="html">K</media:title>
		</media:content>

		<media:content url="http://butaji.files.wordpress.com/2009/08/notes_thumb.png" medium="image">
			<media:title type="html">notes</media:title>
		</media:content>
	</item>
	</channel>
</rss>
