<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://dotnet.lv/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><title type="html">Valdis Iljuconoks</title><subtitle type="html">Microsoft® Most Valuable Professional (MVP), System architect and web/mobile technologist, Visual Studio ALM and Agile evangelist. Microsoft and EPiServer certified developer.</subtitle><id>http://dotnet.lv/blogs/vi/atom.aspx</id><link rel="alternate" type="text/html" href="http://dotnet.lv/blogs/vi/default.aspx" /><link rel="self" type="application/atom+xml" href="http://dotnet.lv/blogs/vi/atom.aspx" /><generator uri="http://communityserver.org" version="4.0.30619.63">Community Server</generator><updated>2011-10-25T23:53:51Z</updated><entry><title>Jauns gads, jaunas idejas</title><link rel="alternate" type="text/html" href="/blogs/vi/archive/2013/01/08/jauns-gads-jaunas-idejas.aspx" /><id>/blogs/vi/archive/2013/01/08/jauns-gads-jaunas-idejas.aspx</id><published>2013-01-07T22:19:00Z</published><updated>2013-01-07T22:19:00Z</updated><content type="html">&lt;div id="post_content"&gt;
&lt;p&gt;Vēl viens gads ir pagājis.&lt;/p&gt;
&lt;p&gt;Aizvadītais gads ir bijis ražens netikai man, bet arī dotnet.lv grupai kopumā. Ir lasītas neskaitāms lekcijas gan grupas ietvaros, gan arī ir notiku&amp;scaron;i intensīvi universitātes apmeklējumi visā Latvijā visa gada garumā. Atsauces un iespaidi ir biju&amp;scaron;i lieliski un to noteikti arī atkārto&amp;scaron;u &amp;scaron;ajā gadā.&lt;/p&gt;
&lt;p&gt;Aizvadītajā gadā cītīgi stradāju un dienas gaismu ieraudzīja ATM Finder aplikācija Microsoft platformām &amp;ndash; &lt;a target="_blank" href="http://bit.ly/atmfinder"&gt;Windows Phone&lt;/a&gt; un &lt;a target="_blank" href="http://bit.ly/AtmFinderW8"&gt;&lt;strong&gt;Windows 8&lt;/strong&gt;&lt;/a&gt;. Gada laikā ATM Finder aplikācija sasniegusi gandrīz 10k lejupielādes. Saņemts ir daudz atsauksmes no Jums. Paldies!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Darbi arī norit pie nākamajām interesantajām aplikācijām gan mobilajai platformai, gan ari Windows 8 darba virsmai.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Tomēr..&lt;/p&gt;
&lt;p&gt;Sekojot &lt;a target="_blank" href="http://gettingresults.com/wiki/Main_Page"&gt;&lt;strong&gt;Agile Results&lt;/strong&gt;&lt;/a&gt; ietvaram jauns gads ir jauns sākums un iespēja ko mainīt, izvirzīt jaunus mērķus un intensīvi strādāt pie tā lai tos sasniegtu.&lt;/p&gt;
&lt;p&gt;&amp;Scaron;ajā gadā ir izvirzīti augstāki mērķi un idejas.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;Scaron;is gads iesākas ar personisko ikubācijas projektu laboratoriju, kas pla&amp;scaron;āk pazīstama kā &lt;a target="_blank" href="http://www.tech-fellow.lv/"&gt;&lt;strong&gt;Tech Fellow Consulting&lt;/strong&gt;&lt;/a&gt;. Tā ir apvienība, kurā darbojas pieredzēju&amp;scaron;i problēmu domaina eksperti, nolūkā palīdzēt klientiem programmatūras izstrādes procesu sakārto&amp;scaron;anā, arhitektūras definē&amp;scaron;anā un modelē&amp;scaron;anā, kopējās tehniskās vīzijas skicē&amp;scaron;anā un citās interesantās lietās.&lt;/p&gt;
&lt;p&gt;Bet galvenokārt, tā ir apvienība, kuras pamatā ir ideja &amp;ndash; fun &amp;amp; passion &amp;ndash; par lietām, ar kurām nodarbojamies &amp;ndash; Software Development.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.tech-fellow.lv/" title="http://www.tech-fellow.lv/"&gt;http://www.tech-fellow.lv/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://twitter.com/tech_fellow" title="https://twitter.com/tech_fellow"&gt;https://twitter.com/tech_fellow&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Keep coding!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;[x]&lt;/p&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnet.lv/aggbug.aspx?PostID=694994" width="1" height="1"&gt;</content><author><name>valdis.iljuconoks</name><uri>http://dotnet.lv/members/valdis.iljuconoks/default.aspx</uri></author><category term="Other" scheme="http://dotnet.lv/blogs/vi/archive/tags/Other/default.aspx" /></entry><entry><title>‘ATM Finder’ privacy policy</title><link rel="alternate" type="text/html" href="/blogs/vi/archive/2012/10/04/atm-finder-privacy-policy.aspx" /><id>/blogs/vi/archive/2012/10/04/atm-finder-privacy-policy.aspx</id><published>2012-10-04T07:09:35Z</published><updated>2012-10-04T07:09:35Z</updated><content type="html">&lt;div id="post_content"&gt;   &lt;table cellspacing="0" cellpadding="0"&gt;       &lt;tr&gt;         &lt;td align="center"&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/150x150_5F00_22D9077A.png" rel="lightbox"&gt;&lt;img style="float:none;margin:50px auto;display:block;" border="0" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/150x150_5F00_thumb_5F00_6DCC7849.png" width="154" height="154" alt="" /&gt;&lt;/a&gt;             &lt;p align="center"&gt;&lt;/p&gt;         &lt;/td&gt;       &lt;/tr&gt;        &lt;tr&gt;         &lt;td&gt;           &lt;p&gt;&lt;font size="4"&gt;Privacy:&lt;/font&gt;&lt;/p&gt;            &lt;p&gt;&lt;font style="line-height:200%;" size="4"&gt;ATM Finder respects user privacy and therefore no user information is collected nor stored. ATM Finder uses location services to detect device location to provide information about closest ATM machine or bank office. Data collected from location service are not stored or forwarded. User always is able to turn off permissions for ATM Finder application to use location services.&lt;/font&gt;&lt;/p&gt;            &lt;p&gt;&lt;font size="4"&gt;If you would like to report any violations of this policy, please contact us at &lt;a href="mailto:valdis.iljuconoks@dotnet.lv" target="_blank"&gt;valdis.iljuconoks@dotnet.lv&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;            &lt;p&gt;&amp;#160;&lt;/p&gt;            &lt;p&gt;&amp;#160;&lt;/p&gt;            &lt;p&gt;&amp;#160;&lt;/p&gt;            &lt;p&gt;&lt;font size="4"&gt;Author:&lt;/font&gt;&lt;/p&gt;            &lt;p&gt;&lt;font size="4"&gt;Valdis Iljuconoks, Microsoft MVP&lt;/font&gt;&lt;/p&gt;            &lt;p&gt;&lt;font size="4"&gt;&lt;a href="http://www.dotnet.lv/blogs/vi/"&gt;http://www.dotnet.lv/blogs/vi/&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;            &lt;p&gt;&lt;font size="4"&gt;Copyright © Valdis Iljuconoks, 2012&lt;/font&gt;&lt;/p&gt;         &lt;/td&gt;       &lt;/tr&gt;     &lt;/table&gt; &lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnet.lv/aggbug.aspx?PostID=613623" width="1" height="1"&gt;</content><author><name>valdis.iljuconoks</name><uri>http://dotnet.lv/members/valdis.iljuconoks/default.aspx</uri></author></entry><entry><title>Delete Team Project from TFS hosted service (tfspreview.com)</title><link rel="alternate" type="text/html" href="/blogs/vi/archive/2012/10/01/delete-team-project-from-tfs-hosted-service-tfspreview-com.aspx" /><id>/blogs/vi/archive/2012/10/01/delete-team-project-from-tfs-hosted-service-tfspreview-com.aspx</id><published>2012-10-01T18:53:00Z</published><updated>2012-10-01T18:53:00Z</updated><content type="html">&lt;div id="post_content"&gt;
&lt;p&gt;While making some demos and playing around with TFS in the cloud (tfspreview.com) I noticed that it&amp;rsquo;s not actually possible to permanently delete the team project from user interface. This particular &amp;ldquo;red cross&amp;rdquo; besides team project name actually just removes project from MRU (&lt;em&gt;Most Recently Used&lt;/em&gt;) list.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a rel="lightbox" href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_61A802FB.png"&gt;&lt;img height="151" width="232" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_36636BF4.png" alt="image" border="0" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin-left:auto;display:block;padding-right:0px;border-top-width:0px;margin-right:auto;" title="image" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;What you need to to is to use &lt;strong&gt;tfsdeleteproject.exe &lt;/strong&gt;from Command Line tool.&lt;/p&gt;
&lt;p&gt;First of all you need to have permission to &lt;strong&gt;Delete team project&lt;/strong&gt;. That one you can easily set in Administration page in your TFS account. Just click on &amp;ldquo;gear&amp;rdquo; icon in the right-upper corner. You can set this permission either on team project or team project collection level, for the user or for the group to which user is member of.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a rel="lightbox" href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_0156DCC4.png"&gt;&lt;img height="490" width="773" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_613BD006.png" alt="image" border="0" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin-left:auto;display:block;padding-right:0px;border-top-width:0px;margin-right:auto;" title="image" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Open Visual Studio Command prompt. And type:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style="background-color:#f2f2f2;"&gt;
&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;tfsdeleteproject /collection:https://&lt;strong&gt;{your-subscription-name}&lt;/strong&gt;.tfspreview.com/defaultcollection &lt;strong&gt;{project-name}&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a rel="lightbox" href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_561245BC.png"&gt;&lt;img height="335" width="837" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_35F738FF.png" alt="image" border="0" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin-left:auto;display:block;padding-right:0px;border-top-width:0px;margin-right:auto;" title="image" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Sometimes you may see some error messages while deleting team project.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style="background-color:#f2f2f2;"&gt;
&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;Deleting from ProjectServer ... &lt;br /&gt;TF294000: Access denied. Windows Live ID\valdis.iljuconoks@dotnet.lv needs the A &lt;br /&gt;dminister Project Server Integration privilege to perform this action. For more &lt;br /&gt;information, contact your administrator for Team Foundation Server. &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;This could be ignored for the moment &amp;ndash; team project gets deleted regardless of errors.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a rel="lightbox" href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_15DC2C42.png"&gt;&lt;img height="559" width="837" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_75C11F84.png" alt="image" border="0" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin-left:auto;display:block;padding-right:0px;border-top-width:0px;margin-right:auto;" title="image" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Remember that you have to use VS 2012 Command Line tools instead of 2010. Because later does not have forward compatibility with tfspreview.com services.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a rel="lightbox" href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_55A612C7.png"&gt;&lt;img height="431" width="837" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_358B060A.png" alt="image" border="0" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin-left:auto;display:block;padding-right:0px;border-top-width:0px;margin-right:auto;" title="image" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Hope this helps!&lt;/p&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnet.lv/aggbug.aspx?PostID=612329" width="1" height="1"&gt;</content><author><name>valdis.iljuconoks</name><uri>http://dotnet.lv/members/valdis.iljuconoks/default.aspx</uri></author><category term="Tfs" scheme="http://dotnet.lv/blogs/vi/archive/tags/Tfs/default.aspx" /><category term="Visual Studio 2010" scheme="http://dotnet.lv/blogs/vi/archive/tags/Visual+Studio+2010/default.aspx" /><category term="Visual Studio 2012" scheme="http://dotnet.lv/blogs/vi/archive/tags/Visual+Studio+2012/default.aspx" /><category term="Team Foundation Services" scheme="http://dotnet.lv/blogs/vi/archive/tags/Team+Foundation+Services/default.aspx" /></entry><entry><title>Story behind ‘ATM Finder’ v2.0</title><link rel="alternate" type="text/html" href="/blogs/vi/archive/2012/09/24/story-behind-atm-finder-v2-0.aspx" /><id>/blogs/vi/archive/2012/09/24/story-behind-atm-finder-v2-0.aspx</id><published>2012-09-24T19:09:00Z</published><updated>2012-09-24T19:09:00Z</updated><content type="html">&lt;div id="post_content"&gt;   &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/200_5F00_723360F3.png" rel="lightbox"&gt;&lt;img title="200" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:left;padding-top:0px;padding-left:0px;margin:40px;display:inline;padding-right:0px;border-top-width:0px;" border="0" alt="200" align="left" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/200_5F00_thumb_5F00_19017734.png" width="92" height="92" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;After a while I’m pleased to announce that “ATM Finder” application has been finally pushed out and published on &lt;a href="http://www.windowsphone.com/en-us/store/app/atm-finder/e0ff546f-b723-4fea-8c38-badfe3495b05" target="_blank"&gt;Windows Phone Store&lt;/a&gt;.&lt;/p&gt;    &lt;p&gt;This has been incredible learning and exploring period to get things done and up and working. So I think this is good time to share some story behind the scene of “ATM Finder v2.0”.&lt;/p&gt;    &lt;p&gt;User interface hasn’t been changed so much. Some small enhancements and polishing.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;div align="center"&gt;     &lt;table cellspacing="0" cellpadding="5" align="center"&gt;         &lt;tr&gt;           &lt;td&gt;             &lt;p align="center"&gt;&lt;span style="font-size:medium;"&gt;&lt;strong&gt;ATM Finder 1.*&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;           &lt;/td&gt;            &lt;td&gt;             &lt;p align="center"&gt;&lt;strong&gt;&lt;span style="font-size:medium;"&gt;ATM Finder 2.0&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;           &lt;/td&gt;         &lt;/tr&gt;          &lt;tr&gt;           &lt;td&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/5.1_5F00_0DD7ECEA.png" rel="lightbox"&gt;&lt;img title="5.1" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin-left:auto;display:block;padding-right:0px;border-top-width:0px;margin-right:auto;" border="0" alt="5.1" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/5.1_5F00_thumb_5F00_06B8B072.png" width="374" height="623" /&gt;&lt;/a&gt;&lt;/td&gt;            &lt;td&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/5.2_5F00_148AF66D.png" rel="lightbox"&gt;&lt;img title="5.2" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin-left:auto;display:block;padding-right:0px;border-top-width:0px;margin-right:auto;" border="0" alt="5.2" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/5.2_5F00_thumb_5F00_0D6BB9F5.png" width="375" height="625" /&gt;&lt;/a&gt;&lt;/td&gt;         &lt;/tr&gt;       &lt;/table&gt;   &lt;/div&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;So what are the new cool features for the new version? Here goes the list:&lt;/p&gt;    &lt;p&gt;1. As more settings switches were coming, I decided to split up “Settings” page into multiple pages grouped in single pivot.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/4_5F00_6D50AD37.png" rel="lightbox"&gt;&lt;img title="4" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin-left:auto;display:block;padding-right:0px;border-top-width:0px;margin-right:auto;" border="0" alt="4" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/4_5F00_thumb_5F00_291045EB.png" width="271" height="452" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;2. Now you can turn on to show map immediately after application start. This mode is usually used when you need to navigate directly to nearest ATM and want to look where it is exactly on the map.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/1_5F00_08F5392E.png" rel="lightbox"&gt;&lt;img title="1" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin-left:auto;display:block;padding-right:0px;border-top-width:0px;margin-right:auto;" border="0" alt="1" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/1_5F00_thumb_5F00_16C77F29.png" width="277" height="462" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;3. Now you can see GPS coordinates on main screen. Some feedback received on this – this could sometimes pretty useful because there is rarely any application that is exposing GPS coordinates to the user.&lt;/p&gt;    &lt;p&gt;4. For those guys who are traveling and roaming is generating some expenses – offline (local data stored driven) mode is also still available. Local storage will be a bit out-dated. I’m considering to offer offline-download mode – which would provide a way to download data to local storage for particular area when on WiFi.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/2_5F00_5DB0A226.png" rel="lightbox"&gt;&lt;img title="2" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin-left:auto;display:block;padding-right:0px;border-top-width:0px;margin-right:auto;" border="0" alt="2" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/2_5F00_thumb_5F00_3D959569.png" width="285" height="475" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;5. Now you can select multiple “My home bank”. The feature request was pretty obvious as nowadays in modern world we are having more than one bank and credit card.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/3_5F00_6F8D35F3.png" rel="lightbox"&gt;&lt;img title="3" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin-left:auto;display:block;padding-right:0px;border-top-width:0px;margin-right:auto;" border="0" alt="3" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/3_5F00_thumb_5F00_7D5F7BEE.png" width="290" height="483" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;6. If there unfortunately some misleading data or location for the ATM is invalid then user has possibility to report this issue to the author and data will be fixed.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/6_5F00_0B31C1EA.png" rel="lightbox"&gt;&lt;img title="6" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin-left:auto;display:block;padding-right:0px;border-top-width:0px;margin-right:auto;" border="0" alt="6" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/6_5F00_thumb_5F00_6B16B52C.png" width="298" height="497" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;And of course feature still remains unchanged – you can still get directions to ATM of your choice using Bing Maps directions services.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/7_5F00_1D0E55B7.png" rel="lightbox"&gt;&lt;img title="7" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin-left:auto;display:block;padding-right:0px;border-top-width:0px;margin-right:auto;" border="0" alt="7" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/7_5F00_thumb_5F00_1FB71168.png" width="303" height="505" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;A bit longer story goes for the backend.&lt;/p&gt;    &lt;p&gt;In previous version “ATM Finder” was driven by local data storage. All the ATMs were stored in local storage, loaded up asynchronously and “some-how in parallel” (are you kidding – that’s a single core phone!, for this I’ll share more details in upcoming posts). The change is that data now in v2.0 is retrieve from &lt;a href="http://www.windowsazure.com/" target="_blank"&gt;Windows Azure&lt;/a&gt; cloud service. This change was driven by idea that uploading new ATMs or removing some obsolete ones should not trigger client application update. Now any changes made to the list of the ATMs are done on server side and immediately distributed to the clients on-demand. Data also is cached on the server side not to hit SQL server and generate additional costs. For this in more details – another post is pending.&lt;/p&gt;    &lt;p&gt;So in honor to ATM Finder application I though that it’s a good time to share some more details on each of the aspect which I faced during design and development phases in following series of blog posts:&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;ol&gt;     &lt;li&gt;Overall design and planning phase (&lt;em&gt;&lt;strong&gt;planning&lt;/strong&gt;&lt;/em&gt;). &lt;/li&gt;      &lt;li&gt;Source code and project layout and source control system (&lt;em&gt;&lt;strong&gt;planning&lt;/strong&gt;&lt;/em&gt;). &lt;/li&gt;      &lt;li&gt;Screen layout and application navigation schema (&lt;em&gt;&lt;strong&gt;planning&lt;/strong&gt;&lt;/em&gt;). &lt;/li&gt;      &lt;li&gt;Binding and Model-View-View/Model approach (&lt;em&gt;&lt;strong&gt;planning&lt;/strong&gt;&lt;/em&gt;). &lt;/li&gt;      &lt;li&gt;Reactive Extensions and asynchronous programming on that small device (&lt;em&gt;&lt;strong&gt;planning&lt;/strong&gt;&lt;/em&gt;). &lt;/li&gt;      &lt;li&gt;Location services (&lt;em&gt;&lt;strong&gt;planning&lt;/strong&gt;&lt;/em&gt;). &lt;/li&gt;      &lt;li&gt;Working with Bing Maps (&lt;em&gt;&lt;strong&gt;planning&lt;/strong&gt;&lt;/em&gt;). &lt;/li&gt;      &lt;li&gt;Application state, settings and isolated storage (&lt;em&gt;&lt;strong&gt;planning&lt;/strong&gt;&lt;/em&gt;). &lt;/li&gt;      &lt;li&gt;Consuming Windows Azure cloud services (&lt;em&gt;&lt;strong&gt;planning&lt;/strong&gt;&lt;/em&gt;). &lt;/li&gt;      &lt;li&gt;Performance and asynchronous operation model. &lt;/li&gt;      &lt;li&gt;Unit testing and UI testing (&lt;em&gt;&lt;strong&gt;planning&lt;/strong&gt;&lt;/em&gt;). &lt;/li&gt;      &lt;li&gt;Packaging, marketplace certification and publishing (&lt;em&gt;&lt;strong&gt;planning&lt;/strong&gt;&lt;/em&gt;). &lt;/li&gt;   &lt;/ol&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Also I wanted to give a big thanks to my beta testers for invaluable feedback on early versions of ATM Finder app. Thanks goes to (alphabetical order)&lt;/p&gt;    &lt;p&gt;1. Āriņš Ivars (&lt;a href="https://twitter.com/PiRXlv" target="_blank"&gt;@PiRXlv&lt;/a&gt;)&lt;/p&gt;    &lt;p&gt;2. Bicāns Jānis (&lt;a href="https://twitter.com/janisbic" target="_blank"&gt;@janisbic&lt;/a&gt;)&lt;/p&gt;    &lt;p&gt;3. Linkēvičš Gusts (&lt;a href="https://twitter.com/gstgusts" target="_blank"&gt;@gstgusts&lt;/a&gt;)&lt;/p&gt;    &lt;p&gt;4. Maciņš Aigars (&lt;a href="https://twitter.com/Owandir" target="_blank"&gt;@Owandir&lt;/a&gt;)&lt;/p&gt;    &lt;p&gt;5. Andres Sirel (&lt;a href="http://twitter.com/asirel" target="_blank"&gt;@asirel&lt;/a&gt;)&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Cheers! Hope this helps. Take a look at &lt;a href="http://bit.ly/atmfinder"&gt;http://bit.ly/atmfinder&lt;/a&gt; and waiting always for feedback how cash finding process could be improved and enhanced :)&lt;/p&gt;     &lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnet.lv/aggbug.aspx?PostID=608983" width="1" height="1"&gt;</content><author><name>valdis.iljuconoks</name><uri>http://dotnet.lv/members/valdis.iljuconoks/default.aspx</uri></author><category term="Other" scheme="http://dotnet.lv/blogs/vi/archive/tags/Other/default.aspx" /><category term="Architecture" scheme="http://dotnet.lv/blogs/vi/archive/tags/Architecture/default.aspx" /><category term="Windows Phone" scheme="http://dotnet.lv/blogs/vi/archive/tags/Windows+Phone/default.aspx" /><category term="Windows Azure" scheme="http://dotnet.lv/blogs/vi/archive/tags/Windows+Azure/default.aspx" /><category term="Azure Storage" scheme="http://dotnet.lv/blogs/vi/archive/tags/Azure+Storage/default.aspx" /><category term="English" scheme="http://dotnet.lv/blogs/vi/archive/tags/English/default.aspx" /><category term="Team Foundation Services" scheme="http://dotnet.lv/blogs/vi/archive/tags/Team+Foundation+Services/default.aspx" /></entry><entry><title>Product Backlog ātrais pievienošanas panelis</title><link rel="alternate" type="text/html" href="/blogs/vi/archive/2012/09/18/product-backlog-trais-pievieno-anas-panelis.aspx" /><id>/blogs/vi/archive/2012/09/18/product-backlog-trais-pievieno-anas-panelis.aspx</id><published>2012-09-18T12:02:40Z</published><updated>2012-09-18T12:02:40Z</updated><content type="html">&lt;div id="post_content"&gt; &lt;p&gt;Jaunais Team Foundation Server 2012 (kā arī Services – &lt;a href="http://tfspreview.com/"&gt;tfspreview.com&lt;/a&gt;) nāk kopā ar ļoti daudz svarīgām un noderīgām iespējām tieši produkta master To-do saraksta (angl. &lt;em&gt;product backlog&lt;/em&gt;) pārlūkošanai un plānošanas. Principā TFS piedāvā diezgan plašu klāstu ar lietām, kas nākušas klāt tieši šajā sfērā, bet tas ir atsevišķs stāsts.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Viena no jaukā &lt;em&gt;feature &lt;/em&gt;klāsta ir iespēja &lt;em&gt;on-fly &lt;/em&gt;pievienot jaunu &lt;em&gt;Product Backlog Item &lt;/em&gt;(PBI). Zemāk redzams ātrās pievienošanas panelis, kas dod iespēju ātri un ērti pievienot jaunu lietotāja scenāriju (&lt;em&gt;user story&lt;/em&gt;) sarakstam.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_7AEABE50.png" rel="lightbox"&gt;&lt;img title="image" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;padding-top:0px;padding-left:0px;margin:0px;display:inline;padding-right:0px;border-top-width:0px;" border="0" alt="image" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_21B8D491.png" width="947" height="306" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Sekojot labākajām Agile praksēm, pārsvarā pietiek tikai nosaukumu, kurā tiek minēti visi nepieciešamie un svarīgākie atslēgas vārdi, kas apraksta šo &lt;em&gt;user story&lt;/em&gt;.&lt;/p&gt;  &lt;p&gt;Tomēr brīžiem šķiet arī, ka aptuvenais novērtējums ir pietiekami svarīgs, lai to ievadītu uzreiz pie jauna PBI ievades.&lt;/p&gt;  &lt;p&gt;Lai nodrošinātu šādu iespēju, jāķeras pie procesa šablona mainīšanas (&lt;strong&gt;Process Template Customization&lt;/strong&gt;).&lt;/p&gt;  &lt;p&gt;Lai ķertos klāt pie šablona izmaiņām pastāv divi varianti, kā to darīt:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Lejupielādēt visu procesa šablonu. Šis gadījums noder situācijās, kad grib mainīt iebūvētā šablona uzvedību un iegūt šīs veiktās izmaiņas projektos, kas tiks veidoti TFS serverī, izmantojot šo modificēto šablonu. &lt;/li&gt;    &lt;li&gt;Lejupielādēt tikai nepieciešamo definīciju failu. Šis variants noder situācijās, kad nepieciešams mainīt jau esoša projekta uzvedību un izskatu. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Tātad ķersimies pie 2. varianta, jo projekts jau eksistē un vēlamies veikt izmaiņas esošā projektā.&lt;/p&gt;  &lt;p&gt;Vispirms nepieciešams atvērt Visual Studio Command Prompt (&lt;strong&gt;NB! &lt;/strong&gt;atceramies, ja ir instalēta arī VS 2010, tad jālaiž ir 2012 komandrinda, jo 2010 šīs jaunās iespējas nebūs un izpildot komandas atpakaļ saņemsim tikai kļūdas paziņojumus).&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_53B0751B.png" rel="lightbox"&gt;&lt;img title="image" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;padding-top:0px;padding-left:0px;margin:0px;display:inline;padding-right:0px;border-top-width:0px;" border="0" alt="image" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_1A999819.png" width="502" height="278" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Visas darbības ar TFS serveri, lai modificēt procesa šablonu, tiek veiktas izmantojot &lt;strong&gt;&lt;font size="2" face="Courier New"&gt;witadmin.exe&lt;/font&gt; &lt;/strong&gt;komandrindinas programmu.&lt;/p&gt;  &lt;p&gt;Procesa šablona fails, kas mums nepieciešams, lai modificētu ātrās pievienošanas paneli, iegūstams ar &lt;strong&gt;&lt;font size="2" face="Courier New"&gt;exportagileprocessconfig&lt;/font&gt; &lt;/strong&gt;programmas operācijas parametru.&lt;/p&gt;  &lt;p&gt;Jāizpilda sekojoša komanda:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="background-color:#f2f2f2;"&gt;&lt;font size="2" face="Courier New"&gt;witadmin exportagileprocessconfig /collection:http://&lt;strong&gt;{server}&lt;/strong&gt;:8080/tfs/&lt;strong&gt;{collection}&lt;/strong&gt; /p:&lt;strong&gt;{project}&lt;/strong&gt; /f:agile.xml       &lt;br /&gt;&lt;/font&gt;&lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Šajā gadījumā jāizpilda bija sekojoša komanda:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="background-color:#f2f2f2;"&gt;   &lt;p&gt;&lt;font size="2" face="Courier New"&gt;witadmin exportagileprocessconfig /collection:http://localhost:8080/tfs/defaultcollection /p:ScrumTest2 /f:agile.xml&lt;/font&gt;&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_0F700DCF.png" rel="lightbox"&gt;&lt;img title="image" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;padding-top:0px;padding-left:0px;margin:0px;display:inline;padding-right:0px;border-top-width:0px;" border="0" alt="image" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_4167AE59.png" width="837" height="287" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Kā rezultātā iegūstam &lt;font size="2" face="Courier New"&gt;agile.xml &lt;/font&gt;failu, kas ir jaunievedums TFS 2012 versijā, lai nodrošinātu šīs jaunās &lt;em&gt;Agile planning&lt;/em&gt; iespējas jebkuram procesa šablonam.     &lt;br /&gt;Failā jāmeklē ir sekojoša hierarhija:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="background-color:#f2f2f2;"&gt;   &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;lt;AgileProjectConfiguration&amp;gt;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;ProductBacklog&amp;gt;         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;AddPanel&amp;gt;         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;Fields&amp;gt;&lt;/font&gt;&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Šajā kolekcijā atrodas lauki, kuriem jāparādās ātrās pievienošanas panelī.&lt;/p&gt;  &lt;p&gt;Sarakstu ar pieejamajiem laukiem ir iespējams iegūt eksportējot PBI definīcijas failu.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="background-color:#f2f2f2;"&gt;   &lt;p&gt;&lt;font size="2" face="Courier New"&gt;witadmin exportwitd /collection:http://localhost:8080/tfs/defaultcollection /p:ScrumTest2 /n:&amp;quot;Product Backlog Item&amp;quot; /f:pbi.xml&lt;/font&gt;&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Un meklējot sadaļu:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="background-color:#f2f2f2;"&gt;   &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;lt;witd&amp;gt;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;WORKITEMTYPE&amp;gt;         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;FIELDS&amp;gt;         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ....         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;FIELD name=&amp;quot;Effort&amp;quot; &lt;strong&gt;refname&lt;/strong&gt;=&amp;quot;Microsoft.VSTS.Scheduling.Effort&amp;quot; type=&amp;quot;Double&amp;quot; reportable=&amp;quot;measure&amp;quot; formula=&amp;quot;sum&amp;quot; /&amp;gt;         &lt;br /&gt;&lt;/font&gt;&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Jāizmanto ir lauka refname atribūta vērtība, lai pievienotu lauku ātrās pievienošanas panelim.&lt;/p&gt;  &lt;p&gt;Effort lauks slēpjas zem refname “&lt;font size="2" face="Courier New"&gt;Microsoft.VSTS.Scheduling.Effort&lt;/font&gt;”.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="background-color:#f2f2f2;"&gt;   &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;lt;AddPanel&amp;gt;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;Fields&amp;gt;         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;Field refname=&amp;quot;System.Title&amp;quot; /&amp;gt;         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;Field refname=&amp;quot;Microsoft.VSTS.Scheduling.Effort&amp;quot; /&amp;gt;         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/Fields&amp;gt;         &lt;br /&gt;&amp;lt;/AddPanel&amp;gt;&lt;/font&gt;&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Lai augšielādētu izmaiņas un mainītu esoša projekta izskatu un uzvedību, jāizmanto tā pati &lt;font size="2" face="Courier New"&gt;witadmin&lt;/font&gt; komanda tikai ar &lt;font size="2" face="Courier New"&gt;importagileprocessconfig&lt;/font&gt; komandas operācijas parametru.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="background-color:#f2f2f2;"&gt;   &lt;p&gt;&lt;font size="2" face="Courier New"&gt;witadmin importagileprocessconfig /collection:http://localhost:8080/tfs/defaultcollection /p:ScrumTest2 /f:agile.xml&lt;/font&gt;&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_363E240F.png" rel="lightbox"&gt;&lt;img title="image" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;padding-top:0px;padding-left:0px;margin:0px;display:inline;padding-right:0px;border-top-width:0px;" border="0" alt="image" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_6835C499.png" width="837" height="239" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Ja komanda izpildās bez kļūdas paziņojumiem, tad jaunās izmaiņas ir stājušās spēkā. Pārbāudīt tās ir iespējams vienkārši ejot uz ātrās pievienošanas paneli.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_5D0C3A4F.png" rel="lightbox"&gt;&lt;img title="image" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;padding-top:0px;padding-left:0px;margin:0px;display:inline;padding-right:0px;border-top-width:0px;" border="0" alt="image" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_3CF12D92.png" width="858" height="378" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Jāpiemin gan, ka šāda veida izmaiņas nav iespējams Team Foundation Services risinājumā, jo Microsoft neļauj procesa šablonu izmaiņas mākoņrisinājumā.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Cerams, ka noderēs!&lt;/p&gt;&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnet.lv/aggbug.aspx?PostID=605721" width="1" height="1"&gt;</content><author><name>valdis.iljuconoks</name><uri>http://dotnet.lv/members/valdis.iljuconoks/default.aspx</uri></author><category term="Tfs" scheme="http://dotnet.lv/blogs/vi/archive/tags/Tfs/default.aspx" /><category term="Team Foundation Server" scheme="http://dotnet.lv/blogs/vi/archive/tags/Team+Foundation+Server/default.aspx" /><category term="Process Templates" scheme="http://dotnet.lv/blogs/vi/archive/tags/Process+Templates/default.aspx" /></entry><entry><title>Calling a service from Windows Phone application reactively</title><link rel="alternate" type="text/html" href="/blogs/vi/archive/2012/06/20/calling-a-service-from-windows-phone-application-reactively.aspx" /><id>/blogs/vi/archive/2012/06/20/calling-a-service-from-windows-phone-application-reactively.aspx</id><published>2012-06-20T06:36:59Z</published><updated>2012-06-20T06:36:59Z</updated><content type="html">&lt;div id="post_content"&gt;&lt;p&gt;If you are creating connected Windows Phone application then most probably have noticed that mostly interface what Visual Studio (VS) generates for you in client proxy class is event-based async pattern.&lt;/p&gt;  &lt;p&gt;For instance we have defined service (usually this is WCF implementation) method:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;   &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;AtmFinderService&lt;/span&gt; : IAtmFinderService       &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; ServiceResponse FindNearby(&lt;span style="color:#0000ff;"&gt;double&lt;/span&gt; latitude, &lt;span style="color:#0000ff;"&gt;double&lt;/span&gt; longitude)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#000000"&gt;...&lt;/font&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/div&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Generating the client proxy class we can see that VS generated event based approach, when we do have an incredible opportunity to use &lt;font face="Courier New"&gt;DoSomethingAsync()&lt;/font&gt; method in our favor and then try to catch event which is raised immediately after operation has been completed.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_25D4B9EA.png" rel="lightbox"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:block;float:none;border-top-width:0px;border-bottom-width:0px;margin-left:auto;border-left-width:0px;margin-right:auto;padding-top:0px;" title="" border="0" alt="" src="http://www.dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_054D7A38.png" width="221" height="194" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Using this method and event code does look pretty much readable (we will touch body of the event handler later on as well).&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;   &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;proxy.FindNearbyCompleted += (sender, args) =&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#808080;"&gt;// do something&lt;/span&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; };&lt;/div&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Suppose if you are sharing the proxy class (for instance, as &lt;font face="Courier New"&gt;static &lt;/font&gt;member of your service façade). Then for sure you will need a mechanism how you can unsubscribe from the event after method has been executed successfully. More info on subscribing and unsubscribing to the events here - &lt;a title="http://msdn.microsoft.com/en-us/library/ms366768.aspx" href="http://msdn.microsoft.com/en-us/library/ms366768.aspx"&gt;http://msdn.microsoft.com/en-us/library/ms366768.aspx&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;So, what we can do is to define event handler and store the reference to the body in class field or member. We can define variable as delegate:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;   &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;&lt;span style="color:#2b91af;"&gt;EventHandler&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;FindNearbyCompletedEventArgs&lt;/span&gt;&amp;gt; delg = &lt;span style="color:#0000ff;"&gt;delegate&lt;/span&gt;(&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; sender, &lt;span style="color:#2b91af;"&gt;FindNearbyCompletedEventArgs&lt;/span&gt; args)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#808080;"&gt;// do something&lt;/span&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; };&lt;/div&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;or we can define to store as &lt;font face="Courier New"&gt;EventHandler&lt;/font&gt;:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;   &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; delg = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;EventHandler&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;FindNearbyCompletedEventArgs&lt;/span&gt;&amp;gt;((sender, args) =&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#808080;"&gt;// do something&lt;/span&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; });&lt;/div&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Then I figured out that the most easiest way to subscribe only once per call is to unsubscribe first and then subscribe:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;   &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;proxy.FindNearbyCompleted -= delg;      &lt;br /&gt;proxy.FindNearbyCompleted += delg;&lt;/div&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;When next time method will be executed event handler added from previous call will be removed first, and then added new one.&lt;/p&gt;  &lt;p&gt;Then we can proceed with the actual service method call. So the complete code is:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;   &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; delg = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;EventHandler&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;FindNearbyCompletedEventArgs&lt;/span&gt;&amp;gt;((sender, args) =&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#808080;"&gt;// do something&lt;/span&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; });       &lt;br /&gt;      &lt;br /&gt;proxy.FindNearbyCompleted -= delg;       &lt;br /&gt;proxy.FindNearbyCompleted += delg;       &lt;br /&gt;      &lt;br /&gt;proxy.FindNearbyAsync(location.Latitude, location.Longitude);&lt;/div&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;This is more or less everything you need to call service method from Windows Phone in async event-based pattern.&lt;/p&gt;  &lt;p&gt;One more note about event handler body. Usually there is requirement to execute event handler on the &lt;font face="Courier New"&gt;Dispatcher &lt;/font&gt;if that updates something in user interface from another thread (that may happen if event handler is called later on).&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;   &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; delg = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;EventHandler&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;FindNearbyCompletedEventArgs&lt;/span&gt;&amp;gt;((sender, args) =&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;Deployment&lt;/span&gt;.Current.Dispatcher.CheckAccess())       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#2b91af;"&gt;Deployment&lt;/span&gt;.Current.Dispatcher.BeginInvoke(&lt;span style="color:#808080;"&gt;/* method */&lt;/span&gt;);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt;;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#808080;"&gt;// do something&lt;/span&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; });&lt;/div&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Here comes another problem that we need to call the same event handler body only within the &lt;font face="Courier New"&gt;Dispatcher &lt;/font&gt;context.&lt;/p&gt;  &lt;p&gt;Easiest way to implement this requirement would be to implement additional method as event handler and then perform dispatcher check there and if call requires dispatcher context, invoke the same method once more within dispatcher context.&lt;/p&gt;  &lt;p&gt;So we are implementing the event handler method first.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;   &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;&lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; ProxyOnFindNearbyCompleted(&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; sender, &lt;span style="color:#2b91af;"&gt;FindNearbyCompletedEventArgs&lt;/span&gt; args)       &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (!&lt;span style="color:#2b91af;"&gt;Deployment&lt;/span&gt;.Current.Dispatcher.CheckAccess())       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#2b91af;"&gt;Deployment&lt;/span&gt;.Current.Dispatcher.BeginInvoke(&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Action&lt;/span&gt;&amp;lt;&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt;, &lt;span style="color:#2b91af;"&gt;FindNearbyCompletedEventArgs&lt;/span&gt;&amp;gt;(ProxyOnFindNearbyCompleted),       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; sender,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; args);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt;;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#808080;"&gt;// do something&lt;/span&gt;       &lt;br /&gt;}&lt;/div&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;And then the original code that attaches the event handler and calls the method remains almost the same:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;   &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;proxy.FindNearbyCompleted -= ProxyOnFindNearbyCompleted;      &lt;br /&gt;proxy.FindNearbyCompleted += ProxyOnFindNearbyCompleted;       &lt;br /&gt;      &lt;br /&gt;proxy.FindNearbyAsync(location.Latitude, location.Longitude);&lt;/div&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;However for me this all seems already converting into unreadable spagetti-like code set.&lt;/p&gt;  &lt;p&gt;There is a more elegant way to accomplish this. I’m going to use Reactive Extensions for Windows Phone – &lt;font face="Courier New"&gt;Microsoft.Phone.Reactive&lt;/font&gt;. Library is coming with Windows Phone SDK.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_0475144E.png" rel="lightbox"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:block;float:none;border-top-width:0px;border-bottom-width:0px;margin-left:auto;border-left-width:0px;margin-right:auto;padding-top:0px;" title="" border="0" alt="" src="http://www.dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_08132F2B.png" width="800" height="438" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;At first we are defining observable from the event-based async pattern.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;   &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; completedObservable = Microsoft.Phone.Reactive.&lt;span style="color:#2b91af;"&gt;Observable&lt;/span&gt;.FromEvent&amp;lt;&lt;span style="color:#2b91af;"&gt;FindNearbyCompletedEventArgs&lt;/span&gt;&amp;gt;(       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ev =&amp;gt; proxy.FindNearbyCompleted += ev,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ev =&amp;gt; proxy.FindNearbyCompleted -= ev);&lt;/div&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Those two arguments for &lt;font face="Courier New"&gt;FromEvent()&lt;/font&gt; method is used to add event handler and to remove event handler for &lt;font face="Courier New"&gt;FindNearbyCompleted&lt;/font&gt; event. This is also an elegant way how to write code that subscribes to the event only once.&lt;/p&gt;  &lt;p&gt;When observable has been created we are able to subscribe to to the event and provide handler to execute when event is raised.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;   &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;completedObservable.Subscribe(result =&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#808080;"&gt;// do something&lt;/span&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; });&lt;/div&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;The complete code looks like following:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;   &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; completedObservable = &lt;span style="color:#2b91af;"&gt;Observable&lt;/span&gt;.FromEvent&amp;lt;&lt;span style="color:#2b91af;"&gt;FindNearbyCompletedEventArgs&lt;/span&gt;&amp;gt;(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ev =&amp;gt; proxy.FindNearbyCompleted += ev,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ev =&amp;gt; proxy.FindNearbyCompleted -= ev);      &lt;br /&gt;      &lt;br /&gt;completedObservable.Subscribe(result =&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#808080;"&gt;// do something&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; });      &lt;br /&gt;      &lt;br /&gt;proxy.FindNearbyAsync(location.Latitude, location.Longitude);&lt;/div&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Pretty straight forward and what’s important – code is readable and understandable.&lt;/p&gt;  &lt;p&gt;One more thing, if you require to run event handler on &lt;font face="Courier New"&gt;Dispatcher&lt;/font&gt; thread, than that’s far more easier than previous implementation with direct checking dispatcher access. You just have to tell reactive extensions that you need to observe events on dispatcher thread rather than on current context.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;   &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;completedObservable.ObserveOnDispatcher().Subscribe(result =&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#808080;"&gt;// do something&lt;/span&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; });&lt;/div&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;In summary, code gets reduced, more readable and understandable.&lt;/p&gt;  &lt;p&gt;Hope this helps!&lt;/p&gt;&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnet.lv/aggbug.aspx?PostID=483446" width="1" height="1"&gt;</content><author><name>valdis.iljuconoks</name><uri>http://dotnet.lv/members/valdis.iljuconoks/default.aspx</uri></author><category term="Architecture" scheme="http://dotnet.lv/blogs/vi/archive/tags/Architecture/default.aspx" /><category term="Design" scheme="http://dotnet.lv/blogs/vi/archive/tags/Design/default.aspx" /><category term="Windows Phone" scheme="http://dotnet.lv/blogs/vi/archive/tags/Windows+Phone/default.aspx" /></entry><entry><title>When you need something stronger..</title><link rel="alternate" type="text/html" href="/blogs/vi/archive/2012/06/05/when-you-need-something-stronger.aspx" /><id>/blogs/vi/archive/2012/06/05/when-you-need-something-stronger.aspx</id><published>2012-06-04T22:22:51Z</published><updated>2012-06-04T22:22:51Z</updated><content type="html">&lt;div id="post_content"&gt;   &lt;p&gt;Have you seen code fragment like this? I mean there are lot of interfaces that provide &lt;a href="http://www.globalnerdy.com/2010/05/09/new-programming-jargon/"&gt;&lt;strong&gt;stringly-typed&lt;/strong&gt;&lt;/a&gt; access to some of the internals of the entity. This particular code fragment could be seen a lot in EPiServer Relate+ product code samples.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;     &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; instance = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;SampleType&lt;/span&gt;();         &lt;br /&gt;instance.SetAttributeValue(&lt;span style="color:#a31515;"&gt;&amp;quot;ThisIsTheAttribute&amp;quot;&lt;/span&gt;, value);&lt;/div&gt;   &lt;/div&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Accessing something that’s not pretty strong enough could be very easy and fast. Not a big deal – just type in attribute name and value.&lt;/p&gt;    &lt;p&gt;Here goes why I don’t like interfaces like these:&lt;/p&gt;    &lt;ol&gt;     &lt;li&gt;When you will margin for a grammar error when typing attribute name – that could be discovered only during runtime. &lt;/li&gt;      &lt;li&gt;You cannot use static code analysis tools. Like to search for all attribute usages. &lt;/li&gt;      &lt;li&gt;You cannot use some of the refactoring tools –&amp;gt; like rename attribute name. &lt;/li&gt;      &lt;li&gt;You can easily change type of the attribute and forget about code that uses that, effect –&amp;gt; runtime error. &lt;/li&gt;      &lt;li&gt;Use cannot leverage all the power of Visual Studio (for instance to provide Intellisense over available attributes) &lt;/li&gt;   &lt;/ol&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;So as we see – there a lot more troubles around stringly-typed interfaces than benefit you gain.&lt;/p&gt;    &lt;p&gt;We are going to change this in this blog post.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;First of all we would need to define client API – that’s how we are going to use our strongly-typed interface to talk to your stringly friend.&lt;/p&gt;    &lt;p&gt;I would like to see following things in client API:&lt;/p&gt;    &lt;ol&gt;     &lt;li&gt;There should be an object that would describe structure of the stringly-typed object. Like enumerating all the properties that we would like to have access to. I would call it – a metadata object. &lt;/li&gt;      &lt;li&gt;There should be an easy way to convert stringly-typed object into this metadata object. &lt;/li&gt;      &lt;li&gt;Metadata object will be used to talk to stringly-typed object via strongly-typed metadata object. &lt;/li&gt;   &lt;/ol&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;I would see client API and some code snippets as following:&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;     &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; instance = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;SampleType&lt;/span&gt;();         &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; metadata = instance.AsAttributeExtendable&amp;lt;&lt;span style="color:#2b91af;"&gt;SampleAttributeMetadata&lt;/span&gt;&amp;gt;();         &lt;br /&gt;metadata.SampleAttribute = value;&lt;/div&gt;   &lt;/div&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Metadata class could be described like this:&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;     &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;SampleAttributeMetadata&lt;/span&gt;         &lt;br /&gt;{         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; SampleAttribute { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }         &lt;br /&gt;}&lt;/div&gt;   &lt;/div&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;This metadata object is just an object that will provide us strongly-typed access later on.&lt;/p&gt;    &lt;p&gt;First things first.&lt;/p&gt;    &lt;p&gt;To convert stringly-typed object into some more meaningful instance we would need something “attachable” to original object. Extension methods will come to rescue today.&lt;/p&gt;    &lt;p&gt;So we are able to write static method that will attach to original object and behave as instance method for that object. No matter which is your original object (for sake of integrity I’ll use EPiServer Relate+ ‘&lt;font face="Courier New"&gt;IAttributeExtendableEntity&lt;/font&gt;’ interface).&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;     &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; T AsAttributeExtendable&amp;lt;T&amp;gt;(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;IAttributeExtendableEntity&lt;/span&gt; entity) &lt;span style="color:#0000ff;"&gt;where&lt;/span&gt; T : &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt;()&lt;/div&gt;   &lt;/div&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;This means that we are defining extension method for objects that implement ‘&lt;font face="Courier New"&gt;IAttributeExtendableEntity&lt;/font&gt;’ interface (those are almost all entities in EPiServer Relate+). This ‘&lt;font face="Courier New"&gt;IAttributeExtendableEntity&lt;/font&gt;’ interface provides stringly-typed access to attributes that you can set or get.&lt;/p&gt;    &lt;p&gt;Generic type parameter &lt;font face="Courier New"&gt;T&lt;/font&gt; – that will be our metadata object class.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Next –&amp;gt; we need to somehow take a control over the metadata object that as given away to the caller of the extension method defined earlier.&lt;/p&gt;    &lt;p&gt;For this reason one of the most easiest way to accomplish this is to use some sort of interceptor infrastructure. What interceptor does? Idea behind the interceptor is that client who got back the metadata object thinks (an result object really looks alike) that object that was given back is of defined metadata object type. And so do all code analysis tools (therefore Intellisense is available) and compiler as well.&lt;/p&gt;    &lt;p&gt;Actually using interceptors we are giving back fake metadata object that has lot of injections in it in order to for us to gain control over the further client’s interaction with the object.&lt;/p&gt;    &lt;p&gt;One of my favorite library to accomplish this is &lt;a href="http://nuget.org/packages/Castle.Core"&gt;&lt;strong&gt;‘Castle project’&lt;/strong&gt;&lt;/a&gt;. Pretty easy to use and straightforward.&lt;/p&gt;    &lt;p&gt;So what we need is to create a fake metadata object with our injections to control what’s going after we return the object. In order to get this done we need to define our interceptor and return a class proxy created using this interceptor.&lt;/p&gt;    &lt;p&gt;So the code for &lt;font face="Courier New"&gt;AsAttributeExtendable() &lt;/font&gt;method is like this:&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;     &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;&lt;strike&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; T AsAttributeExtendable&amp;lt;T&amp;gt;(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;IAttributeExtendableEntity&lt;/span&gt; entity) &lt;span style="color:#0000ff;"&gt;where&lt;/span&gt; T : &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt;()           &lt;br /&gt;{           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (entity == &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ArgumentNullException&lt;/span&gt;(&lt;span style="color:#a31515;"&gt;&amp;quot;entity&amp;quot;&lt;/span&gt;);           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }           &lt;br /&gt;          &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; interceptor = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;DefaultInterceptor&lt;/span&gt;&amp;lt;T&amp;gt;(entity);           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; gen = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ProxyGenerator&lt;/span&gt;();           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; options = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ProxyGenerationOptions&lt;/span&gt;(&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ProxyGenerationHook&lt;/span&gt;());           &lt;br /&gt;          &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; proxy = gen.CreateClassProxy&amp;lt;T&amp;gt;(options, interceptor);           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; proxy;           &lt;br /&gt;}&lt;/strike&gt;&lt;/div&gt;   &lt;/div&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;UPDATE:&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;NB! &lt;/strong&gt;Lessons learned! Actually it’s not quite a good idea to create proxy generator, generation hook and class proxy on each request. Just got through support ticket on memory leak and huge memory consumption. Which ended-up with lot of dynamically generated assemblies loaded into application domain and lot other stuff.&lt;/p&gt;    &lt;p&gt;A better solution is reuse &lt;font face="Courier New"&gt;‘ProxyGenerator’&lt;/font&gt; class instance and cache generated class proxies for particular types.&lt;/p&gt;    &lt;p&gt;First of all need to define static instance of the proxy generator class and store where cached class proxy instances will be stored.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;     &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;&lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;readonly&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ProxyGenerator&lt;/span&gt; gen = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ProxyGenerator&lt;/span&gt;();         &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;readonly&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ProxyGenerationOptions&lt;/span&gt; options = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ProxyGenerationOptions&lt;/span&gt;(&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ProxyGenerationHook&lt;/span&gt;());         &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;readonly&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ConditionalWeakTable&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;IAttributeExtendableEntity&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;object&lt;/span&gt;&amp;gt; table =         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ConditionalWeakTable&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;IAttributeExtendableEntity&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;object&lt;/span&gt;&amp;gt;();&lt;/div&gt;   &lt;/div&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Then we can implement updated method to generate class proxy for particular class of particular type:&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;     &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; T AsAttributeExtendable&amp;lt;T&amp;gt;(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;IAttributeExtendableEntity&lt;/span&gt; entity) &lt;span style="color:#0000ff;"&gt;where&lt;/span&gt; T : &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt;()        &lt;br /&gt;{        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (entity == &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ArgumentNullException&lt;/span&gt;(&lt;span style="color:#a31515;"&gt;&amp;quot;entity&amp;quot;&lt;/span&gt;);        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }        &lt;br /&gt;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; classProxyCached;        &lt;br /&gt;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#808080;"&gt;// try to find already created class proxy from the cache&lt;/span&gt;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#808080;"&gt;// this is required to increase speed a bit and not to create new class proxy for the same class more than once&lt;/span&gt;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; table.TryGetValue(entity, &lt;span style="color:#0000ff;"&gt;out&lt;/span&gt; classProxyCached);        &lt;br /&gt;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (classProxyCached == &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; classProxyCached = GenerateClassProxy&amp;lt;T&amp;gt;(entity);        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; table.Add(entity, classProxyCached);        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }        &lt;br /&gt;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; classProxyCached &lt;span style="color:#0000ff;"&gt;as&lt;/span&gt; T;        &lt;br /&gt;}&lt;/div&gt;   &lt;/div&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;And proxy generation method remains almost unchanged:&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;     &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;&lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; T GenerateClassProxy&amp;lt;T&amp;gt;(&lt;span style="color:#2b91af;"&gt;IAttributeExtendableEntity&lt;/span&gt; entity) &lt;span style="color:#0000ff;"&gt;where&lt;/span&gt; T : &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt;()         &lt;br /&gt;{         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; interceptor = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;DefaultInterceptor&lt;/span&gt;&amp;lt;T&amp;gt;(entity);         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; options = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ProxyGenerationOptions&lt;/span&gt;(&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ProxyGenerationHook&lt;/span&gt;());         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; proxy = gen.CreateClassProxy&amp;lt;T&amp;gt;(options, interceptor);         &lt;br /&gt;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; proxy;         &lt;br /&gt;}&lt;/div&gt;   &lt;/div&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Let’s spilt them up into smaller pieces:&lt;/p&gt;    &lt;ol&gt;     &lt;li&gt;&lt;strong&gt;DefaultInterceptor&lt;/strong&gt; – this is the class that will contain the logic that will be called if client code will try to access something that we marked as interceptable in class &lt;strong&gt;ProxyGenerationHook&lt;/strong&gt; class. &lt;/li&gt;      &lt;li&gt;&lt;strong&gt;ProxyGenerationHook&lt;/strong&gt; – class that describes what is going to be intercepted and what should be passed to the underlying intercepted object. &lt;/li&gt;   &lt;/ol&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Let’s look at hook class (it should implement &lt;font face="Courier New"&gt;‘IProxyGenerationHook’&lt;/font&gt; interface):&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;     &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ProxyGenerationHook&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;IProxyGenerationHook&lt;/span&gt;         &lt;br /&gt;{         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; MethodsInspected()         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }         &lt;br /&gt;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; NonProxyableMemberNotification(&lt;span style="color:#2b91af;"&gt;Type&lt;/span&gt; type, &lt;span style="color:#2b91af;"&gt;MemberInfo&lt;/span&gt; memberInfo)         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;InvalidOperationException&lt;/span&gt;(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.Format(&lt;span style="color:#a31515;"&gt;&amp;quot;Property named &amp;#39;{&lt;/span&gt;&lt;span style="color:#3cb371;"&gt;0}&lt;/span&gt;&lt;span style="color:#a31515;"&gt;&amp;#39; for type &amp;#39;{&lt;/span&gt;&lt;span style="color:#3cb371;"&gt;1}&lt;/span&gt;&lt;span style="color:#a31515;"&gt;&amp;#39; is not marked as virtual.&amp;quot;&lt;/span&gt;,         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; memberInfo.GetProperty().Name,         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; type));         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }         &lt;br /&gt;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; ShouldInterceptMethod(&lt;span style="color:#2b91af;"&gt;Type&lt;/span&gt; type, &lt;span style="color:#2b91af;"&gt;MethodInfo&lt;/span&gt; methodInfo)         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#008000;"&gt;// we are interested only in properties for now&lt;/span&gt;         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; methodInfo.Name.StartsWith(&lt;span style="color:#a31515;"&gt;&amp;quot;get_&amp;quot;&lt;/span&gt;, &lt;span style="color:#2b91af;"&gt;StringComparison&lt;/span&gt;.Ordinal)         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; || methodInfo.Name.StartsWith(&lt;span style="color:#a31515;"&gt;&amp;quot;set_&amp;quot;&lt;/span&gt;, &lt;span style="color:#2b91af;"&gt;StringComparison&lt;/span&gt;.Ordinal);         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }         &lt;br /&gt;}&lt;/div&gt;   &lt;/div&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;This hook is instructing Castle dynamic proxy generation engine that interceptor will intercept &lt;strong&gt;*only*&lt;/strong&gt; properties (setters and getters). Btw, properties are compiled into methods anyway. This particular hook logic of course can be modified and adjusted to meet precise requirements.&lt;/p&gt;    &lt;p&gt;Otherwise (method &lt;font face="Courier New"&gt;NonProxyableMemberNotification()&lt;/font&gt;) will be called if some of the metadata object members could not be intercepted. This is particular useful for error checking. &lt;strong&gt;NB! &lt;/strong&gt;What Castle actually does is that behind the scene another object is created that &lt;strong&gt;*inherits*&lt;/strong&gt; from our defined metadata object. Therefore members (in this case only properties) must be marked as virtual – because Castle tries to override those with its own logic. If that fails - &lt;font face="Courier New"&gt;NonProxyableMemberNotification()&lt;/font&gt; method is called.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Let’s look into &lt;font face="Courier New"&gt;DefaultInterceptor&lt;/font&gt; code (it must implement ‘&lt;font face="Courier New"&gt;IInterceptor&lt;/font&gt;’ interface):&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;     &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;DefaultInterceptor&lt;/span&gt;&amp;lt;T&amp;gt; : &lt;span style="color:#2b91af;"&gt;IInterceptor&lt;/span&gt;         &lt;br /&gt;{         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Intercept(&lt;span style="color:#2b91af;"&gt;IInvocation&lt;/span&gt; invocation)         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {&lt;/div&gt;   &lt;/div&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;It only has single method – &lt;font face="Courier New"&gt;Intercept()&lt;/font&gt;. The most interesting part of interception is parameter – &lt;font face="Courier New"&gt;invocation&lt;/font&gt;, that gives us lot of info about method client code is calling.&lt;/p&gt;    &lt;p&gt;Usually code within Intercept method starts with checking what kind of method client is calling, like:&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;     &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (invocation.Method.Name.StartsWith(&lt;span style="color:#a31515;"&gt;&amp;quot;get_&amp;quot;&lt;/span&gt;, &lt;span style="color:#2b91af;"&gt;StringComparison&lt;/span&gt;.InvariantCultureIgnoreCase))         &lt;br /&gt;{&lt;/div&gt;   &lt;/div&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;or&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;     &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (invocation.Method.Name.StartsWith(&lt;span style="color:#a31515;"&gt;&amp;quot;set_&amp;quot;&lt;/span&gt;, &lt;span style="color:#2b91af;"&gt;StringComparison&lt;/span&gt;.InvariantCultureIgnoreCase))         &lt;br /&gt;{&lt;/div&gt;   &lt;/div&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Just to check either user is getting value from the property or setting value for the property.&lt;/p&gt;    &lt;p&gt;Actual interception code really depends on situation and requirements but usually some of the properties of &lt;font face="Courier New"&gt;IInvocation&lt;/font&gt; class are used:&lt;/p&gt;    &lt;ol&gt;     &lt;li&gt;&lt;font face="Courier New"&gt;invocation.Method&lt;/font&gt; – is the method that is going to be called. &lt;/li&gt;      &lt;li&gt;&lt;font face="Courier New"&gt;invocation.Arguments&lt;/font&gt; – is list of arguments passed the call of the method. &lt;/li&gt;      &lt;li&gt;&lt;font face="Courier New"&gt;invocation.ReturnValue &lt;/font&gt;– set the result of the interception. &lt;/li&gt;   &lt;/ol&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Trick for interceptors – if you want to interrupt interception and return immediately to the caller – just return from the method. Otherwise you’ll need to call &lt;font face="Courier New"&gt;invocation.Proceed()&lt;/font&gt; method that will call next interception or ultimately will call target object’s method.&lt;/p&gt;    &lt;p&gt;And within the interception code you can convert called method (getter or setter for properties) into call to stringly-typed object (&lt;font face="Courier New"&gt;Substring(4)&lt;/font&gt; will remove ‘get_’ or ‘set_’ from the name of the called method):&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;     &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;Entity.SetAttributeValue(invocation.Method.Name.Substring(4), invocation.Arguments[0]);&lt;/div&gt;   &lt;/div&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;or for retrieving something and return that value to the caller’s code:&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;     &lt;div style="padding-bottom:2px;background-color:#f0f0f0;padding-left:5px;padding-right:5px;max-height:500px;overflow:auto;padding-top:2px;"&gt;&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; methodInfo = Entity.GetType().GetMethod(&lt;span style="color:#a31515;"&gt;&amp;quot;GetAttributeValue&amp;quot;&lt;/span&gt;);         &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; genericMethod = methodInfo.MakeGenericMethod(invocation.Method.ReturnType);         &lt;br /&gt;invocation.ReturnValue = genericMethod.Invoke(Entity, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;object&lt;/span&gt;[] { invocation.Method.Name.Substring(4) });&lt;/div&gt;   &lt;/div&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Sequence diagram of final call stack could look something like this:&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://www.dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_5D58DBB0.png" rel="lightbox"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:block;float:none;border-top-width:0px;border-bottom-width:0px;margin-left:auto;border-left-width:0px;margin-right:auto;padding-top:0px;" title="image" border="0" alt="image" src="http://www.dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_1D22C236.png" width="827" height="752" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Sample project where Castle interceptors are used to provide strongly-typed access over EPiServer Relate+ entities can be found &lt;a href="https://github.com/Geta/opensource/tree/master/Geta.Community.EntityAttributeBuilder"&gt;&lt;strong&gt;there&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Hope this helps!&lt;/p&gt; &lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnet.lv/aggbug.aspx?PostID=457871" width="1" height="1"&gt;</content><author><name>valdis.iljuconoks</name><uri>http://dotnet.lv/members/valdis.iljuconoks/default.aspx</uri></author><category term="Architecture" scheme="http://dotnet.lv/blogs/vi/archive/tags/Architecture/default.aspx" /><category term="Design" scheme="http://dotnet.lv/blogs/vi/archive/tags/Design/default.aspx" /><category term="Practices" scheme="http://dotnet.lv/blogs/vi/archive/tags/Practices/default.aspx" /><category term="Languages" scheme="http://dotnet.lv/blogs/vi/archive/tags/Languages/default.aspx" /><category term="Idioms" scheme="http://dotnet.lv/blogs/vi/archive/tags/Idioms/default.aspx" /><category term="C#" scheme="http://dotnet.lv/blogs/vi/archive/tags/C_2300_/default.aspx" /></entry><entry><title>Kad darbs mijas ar hobiju..</title><link rel="alternate" type="text/html" href="/blogs/vi/archive/2012/06/02/kad-darbs-mijas-ar-hobiju.aspx" /><id>/blogs/vi/archive/2012/06/02/kad-darbs-mijas-ar-hobiju.aspx</id><published>2012-06-01T22:47:20Z</published><updated>2012-06-01T22:47:20Z</updated><content type="html">&lt;div id="post_content"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://www.dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_54873D38.png" rel="lightbox"&gt;&lt;img style="background-image:none;border-right-width:0px;margin:20px;padding-left:0px;padding-right:0px;display:inline;float:right;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="" border="0" alt="" align="right" src="http://www.dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_7F5FA14A.png" width="480" height="118" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;Ikdienas gaitas šobrīd aizņem vairāk vai mazāk ļoti interesanta platforma ar nosaukumu EPiServer, kas ir balstīta pārsvarā uz Microsoft produktiem. Par cik rakstus publicēju &lt;strong&gt;dotnet.lv &lt;/strong&gt;mājas lapā un negribas uzturēt vairākus emuāru kontus, tad iespējams, ka ir pa laikam varētu parādīties, kāds ziņojums ar tagu ‘EPiServer’.&lt;/p&gt;    &lt;p&gt;Mēģināšu šīs sērijas rakstos likt informāciju, kas varētu būt ari saistoša cilvēkiem, kas tieši vai netieši nav saistīti ar šo sistēmu. Rakstus plānots veidot, atklājot kādas interesantas nianses sistēmā, daloties ar personisko pieredzi un filozofiju.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Sistēma ir pietiekami liela un sarežģīta, lai tajā nebūtu interesanti atklājumi gan no iedoloģiskā viedokļa, gan no praktiskā. Daudz laika sanāk pārlūkojot dekompilētu kodu un ir pērles, ko var atrast arī nopietnā produktā.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Cerams, ka netraucēs nevienam! :)&lt;/p&gt; &lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnet.lv/aggbug.aspx?PostID=454215" width="1" height="1"&gt;</content><author><name>valdis.iljuconoks</name><uri>http://dotnet.lv/members/valdis.iljuconoks/default.aspx</uri></author><category term="Other" scheme="http://dotnet.lv/blogs/vi/archive/tags/Other/default.aspx" /></entry><entry><title>Team build un Windows SDK kļūda</title><link rel="alternate" type="text/html" href="/blogs/vi/archive/2012/05/23/team-build-un-windows-sdk-k-da.aspx" /><id>/blogs/vi/archive/2012/05/23/team-build-un-windows-sdk-k-da.aspx</id><published>2012-05-23T12:54:39Z</published><updated>2012-05-23T12:54:39Z</updated><content type="html">&lt;div id="post_content"&gt;   &lt;p&gt;Ja kādreiz sanāk ieraudzīt šādu kļūdu savā build log failā (parasti tas mēdz gadīties, kad notiek build serveru migrācijas), tad ir zināmas zāles pret šo.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(2249, 9): error MSB3086: Task could not find &amp;quot;sgen.exe&amp;quot; using the SdkToolsPath &amp;quot;&amp;quot; or the registry key &amp;quot;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A&amp;quot;. Make sure the SdkToolsPath is set and the tool exists in the correct processor specific location under the SdkToolsPath and that the Microsoft Windows SDK is installed&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Tas ko izdarīju es, lai atbrīvotos no šīs kļūdas (kaut gan Windows SDK bija instalēts jaunajā build serverī), bija:&lt;/p&gt;    &lt;ol&gt;     &lt;li&gt;Eksportēt ‘&lt;font face="Courier New"&gt;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A&lt;/font&gt;’ reģistru uzstādījumus. &lt;/li&gt;      &lt;li&gt;Importēt tos jaunajā build serverī. Drošības pēc es importēju arī visu to pašu zem ‘&lt;font face="Courier New"&gt;HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node&lt;/font&gt;’ atslēgas. Lai to izdarītu nākas nodublēt visus uzstādījumus un samainīt reģistra atslēgas ceļus .reg failā. It kā ir izdarāmas arī ar ‘regedit32.exe’, bet risinājums nebija pa rokai.&lt;/li&gt;      &lt;li&gt;Pārkopēt ‘&lt;font face="Courier New"&gt;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A&lt;/font&gt;’ (parasti ceļš ir šāds, ja build serveris ir x64) direktoriju no vecā build servera uz jauno. &lt;/li&gt;   &lt;/ol&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Augstāk minētā kļūda pazuda pēc šīm darbībām.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Cerams, ka noderēs!&lt;/p&gt; &lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnet.lv/aggbug.aspx?PostID=436813" width="1" height="1"&gt;</content><author><name>valdis.iljuconoks</name><uri>http://dotnet.lv/members/valdis.iljuconoks/default.aspx</uri></author><category term="Tfs" scheme="http://dotnet.lv/blogs/vi/archive/tags/Tfs/default.aspx" /><category term="MSBuild" scheme="http://dotnet.lv/blogs/vi/archive/tags/MSBuild/default.aspx" /></entry><entry><title>Debugging locally, testing in the cloud..</title><link rel="alternate" type="text/html" href="/blogs/vi/archive/2012/05/16/debugging-locally-testing-in-the-cloud.aspx" /><id>/blogs/vi/archive/2012/05/16/debugging-locally-testing-in-the-cloud.aspx</id><published>2012-05-15T21:01:12Z</published><updated>2012-05-15T21:01:12Z</updated><content type="html">&lt;div id="post_content"&gt;&lt;p&gt;Dažreiz sanāk kaut ko pameistarot Windows Phone 7 platformai (piemēram, &lt;a href="http://bit.ly/atmfinder"&gt;http://bit.ly/atmfinder&lt;/a&gt;) un nesen saskāros ar interesantu problēmu. Izmantot spraudni SlowCheetah (lejupielādēt var &lt;a href="http://visualstudiogallery.msdn.microsoft.com/69023d00-a4f9-4a34-a6cd-7e854ba318b5"&gt;&lt;strong&gt;šeit&lt;/strong&gt;&lt;/a&gt;), tīmekļa projektos var ērti veikt Xml failu transformācijas, ja tādas ir nepieciešamas. Transformācija var būt katrai projekta konfigurācijai sava – piemēram, lokālā izstrādes vide izmanto vienus uzstādījumus, bet savukārt kopējā testēšanas un skaņošanas instalācijai nepieciešami pavisam citi uzstādījumu. Šo uzstādījumu regulācija un kontrole notiek izmantojot risinājuma uzstādījumus (&lt;em&gt;Configuration Settings&lt;/em&gt;).&lt;/p&gt;  &lt;p&gt;Izmantojot šo lielisko iespēja, nodomāju, ka varētu ieviest vairākas konfigurācijas arī manai aplikācijai: piemēram, ar vienas konfigurācijas palīdzību (pārsvarā tiek izmantots emulatorā) es varētu testēt un skaņot sistēmu, izmantojot lokālos tīmekļa pakalpojumus (WCF servisa adrese būtu &lt;strong&gt;&lt;u&gt;http://localhost/..&lt;/u&gt;&lt;/strong&gt;), savukārt ar citu uzstādījumu palīdzību, varētu regulēt konfigurāciju, ka tīmekļa pakalpojumu atrodas kaut kur – ārā (WCF servisa adrese sāktos ar &lt;strong&gt;&lt;u&gt;http://&amp;lt;kaut kāds mistisks id, kas laikam domāts Azure instances identificēšanai&amp;gt;/..&lt;/u&gt;&lt;/strong&gt;).&lt;/p&gt;  &lt;p&gt;Šim nolūkam WCF klienta bibliotēka jau savu konfigurācijas fragmentus saglabā &lt;strong&gt;ServiceReferences.ClientConfig&lt;/strong&gt; failā, kas ir parasts Xml fails. Šāda veida Xml faili ir ļoti labs kandidāts Xml transformācijai dažādās konfigurācijās dažādām vajadzībām.&lt;/p&gt;  &lt;p&gt;Konfigurācijas faili izskatās šādi:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Oriģinālais fails:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;   &lt;div style="background:#ddd;max-height:500px;overflow:auto;"&gt;     &lt;ol style="padding-bottom:0px;margin:0px 0px 0px 2.5em;padding-left:5px;padding-right:0px;background:#ffffff;padding-top:0px;"&gt;       &lt;li&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;configuration&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li style="background:#f3f3f3;"&gt;&amp;#160; &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;system.serviceModel&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;bindings&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li style="background:#f3f3f3;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;customBinding&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;binding&lt;/span&gt;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;CustomBinding_IAtmFinderService&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li style="background:#f3f3f3;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;binaryMessageEncoding&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;httpTransport&lt;/span&gt;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;maxReceivedMessageSize&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;2147483647&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;maxBufferSize&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;2147483647&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt; /&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li style="background:#f3f3f3;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#a31515;"&gt;binding&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#a31515;"&gt;customBinding&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li style="background:#f3f3f3;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#a31515;"&gt;bindings&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;client&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li style="background:#f3f3f3;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;endpoint&lt;/span&gt;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;address&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;http://localhost:81/AtmFinderService.svc&lt;/span&gt;&amp;quot; &lt;/li&gt;        &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;&lt;/span&gt;&lt;span style="color:#ff0000;"&gt;binding&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;customBinding&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;bindingConfiguration&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;CustomBinding_IAtmFinderService&lt;/span&gt;&amp;quot; &lt;/li&gt;        &lt;li style="background:#f3f3f3;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;&lt;/span&gt;&lt;span style="color:#ff0000;"&gt;contract&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;CloudServiceReference.IAtmFinderService&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;CustomBinding_IAtmFinderService&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt; /&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#a31515;"&gt;client&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li style="background:#f3f3f3;"&gt;&amp;#160; &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#a31515;"&gt;system.serviceModel&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#a31515;"&gt;configuration&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; &lt;/li&gt;     &lt;/ol&gt;   &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Viens no transformācijas failiem, kas uzstāda servisa adresi uz to mākoņa pakalpojumu:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;   &lt;div style="background:#ddd;max-height:400px;overflow:auto;"&gt;     &lt;ol style="padding-bottom:0px;margin:0px 0px 0px 2.5em;padding-left:5px;padding-right:0px;background:#ffffff;padding-top:0px;"&gt;       &lt;li&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;configuration&lt;/span&gt;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;xmlns:xdt&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;http://schemas.microsoft.com/XML-Document-Transform&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li style="background:#f3f3f3;"&gt;&amp;#160; &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;system.serviceModel&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;client&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li style="background:#f3f3f3;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;endpoint&lt;/span&gt;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;address&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;http://azure-instances-id.cloudapp.net/AtmFinderService.svc&lt;/span&gt;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;CustomBinding_IAtmFinderService&lt;/span&gt;&amp;quot; &lt;/li&gt;        &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;&lt;/span&gt;&lt;span style="color:#ff0000;"&gt;xdt:Transform&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;SetAttributes(address)&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;xdt:Locator&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;Match(name)&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li style="background:#f3f3f3;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#a31515;"&gt;client&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li&gt;&amp;#160; &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#a31515;"&gt;system.serviceModel&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li style="background:#f3f3f3;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#a31515;"&gt;configuration&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; &lt;/li&gt;     &lt;/ol&gt;   &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Sākotnēji likās iespēja tiešām lieliska un eleganta, bet pēc neilgiem eksperimentiem atklājās, ka SlowCheetah tiek izpildīts sekmīgi, bet XAP failā aiziet oriģinālais Xml / .config fails no source direktorijas (direktorijas, kurā atrodas projekta sakne), savukārt spraudnis transformē oriģinālo failu no source direktorijas pārveidojot to kopē vietā, kur tiek novietoti arī pārējie projekta izejas artefakti.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Šis fakts traucē Xap failā iekļauj pareizo jau &lt;strong&gt;*transformēto*&lt;/strong&gt; failu.&lt;/p&gt;  &lt;p&gt;Izstaigājot Silverlight MSBuild konfigurācijas definīcijas failus, sapratu, ka labāk nemēģināt pārtaisīt, bet gan pielāgoties Xap faila pakošanas procesam.&lt;/p&gt;  &lt;p&gt;Beigu beigās sanāca .targets fails, kas domāts tieši priekš šādam situācijām, kad nepieciešams WCF klienta konfigurācijas failus transformēt un rezultātu iekļaut Xap failā.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;   &lt;div style="background:#ddd;overflow:auto;"&gt;     &lt;ol style="padding-bottom:0px;margin:0px 0px 0px 2em;padding-left:5px;padding-right:0px;background:#ffffff;padding-top:0px;"&gt;       &lt;li&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Project&lt;/span&gt;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;ToolsVersion&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;4.0&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;xmlns&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;http://schemas.microsoft.com/developer/msbuild/2003&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li style="background:#f3f3f3;"&gt;&amp;#160; &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Target&lt;/span&gt;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;BeforeBuild&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;CallTarget&lt;/span&gt;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;Targets&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;TransformAllFiles&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt; /&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li style="background:#f3f3f3;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Exec&lt;/span&gt;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;Command&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;attrib -r ServiceReferences.ClientConfig&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;WorkingDirectory&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;$(MSBuildProjectDirectory)&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt; /&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Exec&lt;/span&gt;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;Command&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;xcopy &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;&amp;amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;$(OutDir)ServiceReferences.ClientConfig&lt;/span&gt;&lt;span style="color:#ff0000;"&gt;&amp;amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt; ServiceReferences.ClientConfig /y&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;WorkingDirectory&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;$(MSBuildProjectDirectory)&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt; /&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li style="background:#f3f3f3;"&gt;&amp;#160; &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Target&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; &lt;/li&gt;        &lt;li&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Project&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; &lt;/li&gt;     &lt;/ol&gt;   &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Šo .targets failu var iekļaut savā projektā:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;"&gt;   &lt;div style="background:#ddd;max-height:500px;overflow:auto;"&gt;     &lt;ol style="padding-bottom:0px;margin:0px 0px 0px 2em;padding-left:5px;padding-right:0px;background:#ffffff;padding-top:0px;"&gt;       &lt;li&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Import&lt;/span&gt;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;Project&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt;ServiceReferences.Transform.targets&lt;/span&gt;&amp;quot;&lt;span style="color:#0000ff;"&gt; /&amp;gt;&lt;/span&gt; &lt;/li&gt;     &lt;/ol&gt;   &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Ja slinkums pārrakstīt faila saturu, tad fails pilnā saturā pieejams &lt;a href="https://skydrive.live.com/redir.aspx?cid=38746a08ebe72be7&amp;amp;resid=38746A08EBE72BE7!810&amp;amp;parid=38746A08EBE72BE7!521"&gt;&lt;strong&gt;šeit&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Šim paņēmienam ir gan viena neliela problēmiņa, kuru man nav izdevies vēl atrisināt –&amp;gt; pēc sekmīga būvējuma, oriģinālais fails satur transformētā faila saturu. Jāatdzīst, ka man neizdevās sameklēt notikumu, kas tiktu izsaukts pašās build procesa beigās (&lt;strong&gt;AfterEndToEndIteration&lt;/strong&gt; notikums nestrādā). Savukārt, ja transformācijas ir rakstītas pareizi, tad šai niansei nevajadzētu sagādāt nekādas problēmas.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Cerams, ka noderēs!&lt;/p&gt;&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnet.lv/aggbug.aspx?PostID=423864" width="1" height="1"&gt;</content><author><name>valdis.iljuconoks</name><uri>http://dotnet.lv/members/valdis.iljuconoks/default.aspx</uri></author><category term="Tfs" scheme="http://dotnet.lv/blogs/vi/archive/tags/Tfs/default.aspx" /><category term="MSBuild" scheme="http://dotnet.lv/blogs/vi/archive/tags/MSBuild/default.aspx" /><category term="Xml" scheme="http://dotnet.lv/blogs/vi/archive/tags/Xml/default.aspx" /><category term="Windows Phone" scheme="http://dotnet.lv/blogs/vi/archive/tags/Windows+Phone/default.aspx" /><category term="Windows Azure" scheme="http://dotnet.lv/blogs/vi/archive/tags/Windows+Azure/default.aspx" /><category term="Xap" scheme="http://dotnet.lv/blogs/vi/archive/tags/Xap/default.aspx" /></entry><entry><title>TPL (Task Parallel Library) prezentācijas source code.</title><link rel="alternate" type="text/html" href="/blogs/vi/archive/2012/05/07/tpl-task-parallel-library-prezent-cijas-source-code.aspx" /><id>/blogs/vi/archive/2012/05/07/tpl-task-parallel-library-prezent-cijas-source-code.aspx</id><published>2012-05-07T19:54:36Z</published><updated>2012-05-07T19:54:36Z</updated><content type="html">&lt;div id="post_content"&gt;   &lt;p&gt;Pēc Latvijas Universitātes auditorijas lūgumu izvietoju prezentācijas demo source code. Pieejams &lt;a href="https://skydrive.live.com/redir.aspx?cid=38746a08ebe72be7&amp;amp;resid=38746A08EBE72BE7!785&amp;amp;parid=38746A08EBE72BE7!521"&gt;&lt;strong&gt;šeit&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;    &lt;p&gt;Ja rodas kādi jautājumi, iebildumi vai filozofiskas pārdomas – noteikti gaidu jūsu feedback: valdis punkts iljuconoks at dotnet punkts lv.&lt;/p&gt;    &lt;p&gt;&lt;a href="http://www.dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_33C280F8.png" rel="lightbox"&gt;&lt;img style="background-image:none;border-right-width:0px;margin:20px;padding-left:0px;padding-right:0px;display:inline;float:right;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="" border="0" alt="" align="right" src="http://www.dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_738C677D.png" width="573" height="306" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Happy parallelisming!&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnet.lv/aggbug.aspx?PostID=399523" width="1" height="1"&gt;</content><author><name>valdis.iljuconoks</name><uri>http://dotnet.lv/members/valdis.iljuconoks/default.aspx</uri></author><category term="Design" scheme="http://dotnet.lv/blogs/vi/archive/tags/Design/default.aspx" /><category term="Parallel FX" scheme="http://dotnet.lv/blogs/vi/archive/tags/Parallel+FX/default.aspx" /><category term="TPL" scheme="http://dotnet.lv/blogs/vi/archive/tags/TPL/default.aspx" /></entry><entry><title>Schedule</title><link rel="alternate" type="text/html" href="/blogs/vi/archive/2012/04/19/schedule.aspx" /><id>/blogs/vi/archive/2012/04/19/schedule.aspx</id><published>2012-04-18T21:09:00Z</published><updated>2012-04-18T21:09:00Z</updated><content type="html">&lt;div id="post_content"&gt;
&lt;p&gt;Kā izrādās, tad aprīļa pa&amp;scaron;as beigas un maija mēnesis izvērties par diezgan aizņemtu laika posmu. Katrā ziņā, var noķert mani kaut kur tur&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img height="352" width="469" src="http://i.i.com.com/cnwk.1d/i/tim/2010/10/13/businessman-running-4x3_540x405.jpg" align="right" border="0" style="background-image:none;border-right-width:0px;margin:20px;padding-left:0px;padding-right:0px;display:inline;float:right;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size:large;"&gt;Aprīlis 2012:&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size:medium;"&gt;2012.04.26&lt;/span&gt;: Transporta un Sakaru Institūts:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;18:15 &amp;ndash; 19:15 &amp;ldquo;MSF &amp;amp; Agile&amp;rdquo; &lt;/p&gt;
&lt;p&gt;19:15 &amp;ndash; 19:45 &amp;ldquo;TFS 2012 Overview (Dev &amp;lsquo;11)&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size:large;"&gt;Maijs 2012:&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size:medium;"&gt;2012.05.07&lt;/span&gt;: Latvijas Universitāte:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;18:15&lt;/strong&gt; &amp;ndash; 19:15 &amp;ldquo;Parallel Computing in Visual Studio 2010&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size:medium;"&gt;2012.05.08&lt;/span&gt;: Vidzemes Augstskola:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;10:00&lt;/strong&gt; &amp;ndash; 10:55 &amp;ldquo;Asp.Net MVC&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;11:00&lt;/strong&gt; &amp;ndash; 11:55 &amp;ldquo;Funkcionālā programmē&amp;scaron;ana - F#&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;12:00&lt;/strong&gt; &amp;ndash; 12:55 &amp;ldquo;Visual Studio 2012 - What&amp;#39;s new?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;13:00&lt;/strong&gt; &amp;ndash; 13:55 &amp;ldquo;Requirements Management in TFS&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size:medium;"&gt;2012.05.14&lt;/span&gt;: Latvijas Universitāte:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;18:15&lt;/strong&gt; &amp;ndash; 19:15 &amp;ldquo;Funkcionālā programmē&amp;scaron;ana - F#&amp;ldquo;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size:medium;"&gt;2012.05.17&lt;/span&gt;: Ventspils Augstskola:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;11:00&lt;/strong&gt; &amp;ndash; 11:45 &amp;ldquo;Designing Software Architecture in VS 2010&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;12:45&lt;/strong&gt; &amp;ndash; 13:30 &amp;ldquo;C# 3.0 &amp;amp; C# 4.0&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;13:40&lt;/strong&gt; &amp;ndash; 14:25 &amp;ldquo;MSF &amp;amp; Agile&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;14:35&lt;/strong&gt; &amp;ndash; 15:20 &amp;ldquo;Requirements Management in TFS&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size:medium;"&gt;2012.05.21&lt;/span&gt;: Latvijas Universitāte:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;18:15&lt;/strong&gt; &amp;ndash; 19:15 &amp;ldquo;C# 5.0 &amp;ndash; async&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size:medium;"&gt;2012.05.28&lt;/span&gt;: Latvijas Universitāte:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;18:15&lt;/strong&gt; &amp;ndash; 19:15 &amp;ldquo;Ievads jQuery&amp;ldquo;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Cerams, ka noderēs!&lt;/p&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnet.lv/aggbug.aspx?PostID=355406" width="1" height="1"&gt;</content><author><name>valdis.iljuconoks</name><uri>http://dotnet.lv/members/valdis.iljuconoks/default.aspx</uri></author><category term="ASP.NET" scheme="http://dotnet.lv/blogs/vi/archive/tags/ASP.NET/default.aspx" /><category term="Tfs" scheme="http://dotnet.lv/blogs/vi/archive/tags/Tfs/default.aspx" /><category term="Other" scheme="http://dotnet.lv/blogs/vi/archive/tags/Other/default.aspx" /><category term="Architecture" scheme="http://dotnet.lv/blogs/vi/archive/tags/Architecture/default.aspx" /><category term="Design" scheme="http://dotnet.lv/blogs/vi/archive/tags/Design/default.aspx" /><category term="Parallel FX" scheme="http://dotnet.lv/blogs/vi/archive/tags/Parallel+FX/default.aspx" /><category term="F#" scheme="http://dotnet.lv/blogs/vi/archive/tags/F_2300_/default.aspx" /><category term="C#" scheme="http://dotnet.lv/blogs/vi/archive/tags/C_2300_/default.aspx" /><category term="TFS 11" scheme="http://dotnet.lv/blogs/vi/archive/tags/TFS+11/default.aspx" /><category term="Visual Studio Dev 11" scheme="http://dotnet.lv/blogs/vi/archive/tags/Visual+Studio+Dev+11/default.aspx" /><category term="Visual Studio 2012" scheme="http://dotnet.lv/blogs/vi/archive/tags/Visual+Studio+2012/default.aspx" /><category term="jQuery" scheme="http://dotnet.lv/blogs/vi/archive/tags/jQuery/default.aspx" /><category term="Agile" scheme="http://dotnet.lv/blogs/vi/archive/tags/Agile/default.aspx" /></entry><entry><title>`Fakes’ iekš VS Dev ‘11</title><link rel="alternate" type="text/html" href="/blogs/vi/archive/2012/04/06/fakes.aspx" /><id>/blogs/vi/archive/2012/04/06/fakes.aspx</id><published>2012-04-06T19:45:35Z</published><updated>2012-04-06T19:45:35Z</updated><content type="html">&lt;div id="post_content"&gt;   &lt;p&gt;Interesanta lieta, kas varbūt nav tik bieži un daudz apskatīta lasot par jaunās versijas iespējām un jaunajām “fīčām” – Fakes Framework.&lt;/p&gt;    &lt;p&gt;Šī platforma paredzēta tieši vienumu testu efektīvākai un vieglākai rakstīšanai.&lt;/p&gt;    &lt;p&gt;Dažkārt vienumu testu veidošanas laikā ir nepieciešams simulēt kādas izmantotas komponentes uzvedību vai funkcionalitāti. Ja programma, kuru vēlas notestēt un pārējās komponentes ir veidotas ar ņemot vērā vienumu testu īpatnības (piemēram, komponentes paļaujas un izmanto funkcionalitāti, kas slēpjas aiz klašu interfeisiem, kurus “saņem” no ārpuses), tad lielas grūtības pareizu vienumu testu uzrakstīt parasti nesagādā problēmas.&lt;/p&gt;    &lt;p&gt;Problēmas parasti rodas situācijās, kad nepieciešams simulēt uzvedību kādai no komponentēm, kurai nav pieejams izejas kods, kurai nav iespējams pārrakstīt uzvedību (virtuālās metodes) vai arī kuras paļaujas uz kādu konkrētu iekodētu implementāciju, kuru izmainīt parasti sagādā problēmas.&lt;/p&gt;    &lt;p&gt;Pieņemsim, ir neliela metode, kas pārbauda entity “derīguma termiņu” un nosaka, vai šo entity var dzēst no sistēmas. Pieņemsim, ka entity no sistēma var tikai tad, kad tā tur pabijusi vairāk par 5 dienām, t.i., entity pievienošanas datums ir par 5 dienām mazāks nekā &lt;font face="Consolas"&gt;{sistēmas pašreizējais}&lt;/font&gt; datums. Un šajā vietā sākas interesantākais. &lt;font face="Consolas"&gt;{Pašreizējais datums}&lt;/font&gt; ir lieta, kuru parasti implementē ar &lt;font face="Consolas"&gt;&lt;font color="#2b91af"&gt;DateTime&lt;/font&gt;.Now&lt;/font&gt;.&lt;/p&gt;    &lt;p&gt;Viss ir kārtībā un sistēma visticamāk arī uzvedīsies pareizi run-time laikā, bet jautājums: kā, lai pārbauda šāda veida kodu no vienumu testiem. Un vienumu testi noteikti gribēs pārbaudīt abus loģiskos zarus – kad entity pievienošanas laiks ir mazāks un kad ir lielāks par definētajām 5 dienām, tādā veidā tiešām pārliecinoties, ka abi loģikas zari nostrādā pareizi.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:84f3c5d6-d24e-4fcb-b4fb-2bf7907f9256" class="wlWriterEditableSmartContent" style="float:none;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;display:inline;padding-right:0px;"&gt; &lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt; &lt;div style="background-color:#ffffff;max-height:300px;overflow:auto;padding:2px 5px;"&gt;&lt;span style="background:#ffffff;color:#0000ff;"&gt;public&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt; &lt;/span&gt;&lt;span style="background:#ffffff;color:#0000ff;"&gt;bool&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt; CanEntityRemove(&lt;/span&gt;&lt;span style="background:#ffffff;color:#2b91af;"&gt;Entity&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt; entity)&lt;/span&gt;&lt;br /&gt; &lt;span style="background:#ffffff;color:#000000;"&gt;{&lt;/span&gt;&lt;br /&gt;     &lt;span style="background:#ffffff;color:#000000;"&gt;&lt;/span&gt;&lt;span style="background:#ffffff;color:#0000ff;"&gt;if&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt; (entity == &lt;/span&gt;&lt;span style="background:#ffffff;color:#0000ff;"&gt;null&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt;)&lt;/span&gt;&lt;br /&gt;     &lt;span style="background:#ffffff;color:#000000;"&gt;{&lt;/span&gt;&lt;br /&gt;         &lt;span style="background:#ffffff;color:#000000;"&gt;&lt;/span&gt;&lt;span style="background:#ffffff;color:#0000ff;"&gt;throw&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt; &lt;/span&gt;&lt;span style="background:#ffffff;color:#0000ff;"&gt;new&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt; &lt;/span&gt;&lt;span style="background:#ffffff;color:#2b91af;"&gt;ArgumentNullException&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt;(&lt;/span&gt;&lt;span style="background:#ffffff;color:#800000;"&gt;&amp;quot;entity&amp;quot;&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt;);&lt;/span&gt;&lt;br /&gt;     &lt;span style="background:#ffffff;color:#000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;     &lt;span style="background:#ffffff;color:#000000;"&gt;&lt;/span&gt;&lt;span style="background:#ffffff;color:#0000ff;"&gt;var&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt; delta = entity.Added.Subtract(&lt;/span&gt;&lt;span style="background:#ffffff;color:#2b91af;"&gt;DateTime&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt;.Now);&lt;/span&gt;&lt;br /&gt;     &lt;span style="background:#ffffff;color:#000000;"&gt;&lt;/span&gt;&lt;span style="background:#ffffff;color:#0000ff;"&gt;return&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt; delta.Days &amp;gt; 5;&lt;/span&gt;&lt;br /&gt; &lt;span style="background:#ffffff;color:#000000;"&gt;}&lt;/span&gt;&lt;/div&gt; &lt;/div&gt; &lt;/div&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Viens no variantiem, būtu definēt pašiem savu datuma piegādātāja klasi, kas varētu atgriezt virtuālo laiku, ar kuru varētu veikt nepieciešamās manipulācijas pirms atgriešanas. Bet jautājums, ko darīt, ja vēlamies pārbaudīt &lt;strong&gt;*tieši*&lt;/strong&gt; šādu kodu? Talkā nāk Fakes Framework, kas pieejams Visual Studio Dev ’11 versijā.&lt;/p&gt;    &lt;p&gt;Lai aizvietotu &lt;font face="Consolas"&gt;&lt;font color="#2b91af"&gt;DateTime&lt;/font&gt;.Now &lt;/font&gt;īpašības vērtības, nepieciešams vispirms vienumu testa projektam uz nepieciešamo references bibliotēku, kur definēta klase &lt;font face="Consolas"&gt;DateTime&lt;/font&gt;, izpildīt komandu “Add Fakes Assembly”.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_5FD0B393.png" rel="lightbox"&gt;&lt;img title="" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin-left:auto;display:block;padding-right:0px;border-top-width:0px;margin-right:auto;" border="0" alt="" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_069EC9D4.png" width="596" height="362" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Šī komanda ģenerēs jaunu bibliotēku &lt;font face="Consolas"&gt;{OriginalName} + “.Fakes”&lt;/font&gt;. Par cik &lt;font face="Consolas"&gt;DateTime&lt;/font&gt; ir definēts mscorlib bibliotēkā, bet pēc noklusējuma tā nav redzama references sarakstā, tad pēc Fakes bibliotēkas ģenerācijas, pieejama ir mscorlib.4.0.0.0.Fakes bibliotēka, kas satur &lt;font face="Consolas"&gt;stubs&lt;/font&gt; vai &lt;font face="Consolas"&gt;shims&lt;/font&gt; objektu veidus.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_7F7F8D5B.png" rel="lightbox"&gt;&lt;img title="" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin:0px auto;display:block;padding-right:0px;border-top-width:0px;" border="0" alt="" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_5F64809E.png" width="336" height="519" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Microsoft Visual Studio Dev ‘11 pašlaik izmanto divu klašu “izbāžņu” veidus:&lt;/p&gt;    &lt;ol&gt;     &lt;li&gt;&lt;strong&gt;Stub&lt;/strong&gt;: ir veids, kurā ģenerētā klase pilnībā ir spējīga aizvietot mērķa klasi, piedāvājot noklusēto uzvedību un funkcionalitāti visām virtuālajām vai abstraktajām metodēm, īpašībām un notikumiem. Šīs klašu “izkārtnes” iespējams ģenerēt arī interfeisiem un nemarķētām (non-sealed) klasēm. Savukārt pārējiem gadījumiem: statiskām vai ne-virtuālām metodēm jāģenerē būs &lt;strong&gt;Shim &lt;/strong&gt;veida aizbāžņi. &lt;/li&gt;      &lt;li&gt;&lt;strong&gt;Shim&lt;/strong&gt;: ar šī veida palīdzību ir iespējams simulēt uzvedību statiskām vai ne-virutālām metodēm. Šī veida “izbāžņi” pārķers visus orģinālos izsaukumus un pāradresēs to alternatīvajai implementācijai. &lt;/li&gt;   &lt;/ol&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Abu šo veidu klašu “izbāžņi” ļauj izmantot &lt;font face="Consolas"&gt;delegates&lt;/font&gt;, lai implementētu vai pārrakstītu nepieciešamo funkcionalitāti.&lt;/p&gt;    &lt;p&gt;Direktorija “Fakes/” satur sarakstu un papildus informāciju par bibliotēkām, kurām ir jāģenerē klašu “izbāžņi”.&lt;/p&gt;    &lt;p&gt;&lt;font face="Consolas"&gt;&amp;lt;Fakes xmlns=&amp;quot;&lt;/font&gt;&lt;a href="http://schemas.microsoft.com/fakes/2011/&amp;quot;"&gt;&lt;font face="Consolas"&gt;http://schemas.microsoft.com/fakes/2011/&amp;quot;&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt;&amp;gt;        &lt;br /&gt;&amp;#160; &amp;lt;Assembly Name=&amp;quot;mscorlib&amp;quot; Version=&amp;quot;4.0.0.0&amp;quot;/&amp;gt;         &lt;br /&gt;&amp;lt;/Fakes&amp;gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Ja gribam simulēt &lt;font face="Consolas"&gt;&lt;font color="#2b91af"&gt;DateTime&lt;/font&gt;.Now &lt;/font&gt;īpašības vērtību, tad nozīmē, ka jāizmanto būs Shim veida ģenerācija, jo īpašība ir statiska.&lt;/p&gt;    &lt;p&gt;Lai darbotos &lt;font face="Consolas"&gt;Shim&lt;/font&gt; veida ģenerētās klases, vispirms nepieciešams ieslēgt &lt;font face="Consolas"&gt;Shim&lt;/font&gt; kontekstu vienuma testa izpildes laikā. &lt;font face="Consolas"&gt;Shim&lt;/font&gt; konteksts paļaujas uz speciāli veidotu &lt;font face="Consolas"&gt;TraceProfilerInstrumentationProvider&lt;/font&gt;, kas arī nodarbojas ar izsaukumu pārķeršanu.&lt;/p&gt;    &lt;p&gt;Tātad, ja vēlamies izmantot &lt;font face="Consolas"&gt;Shim&lt;/font&gt; veida klašu ģenerāciju, tad no sākuma jāieslēdz:&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:c3316a1d-b300-4bc8-82b5-d558c70410b2" class="wlWriterEditableSmartContent" style="float:none;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;display:inline;padding-right:0px;"&gt; &lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt; &lt;div style="background-color:#ffffff;max-height:300px;overflow:auto;padding:2px 5px;"&gt;&lt;span style="background:#ffffff;color:#000000;"&gt;[&lt;/span&gt;&lt;span style="background:#ffffff;color:#2b91af;"&gt;TestMethod&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt;]&lt;/span&gt;&lt;br /&gt; &lt;span style="background:#ffffff;color:#0000ff;"&gt;public&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt; &lt;/span&gt;&lt;span style="background:#ffffff;color:#0000ff;"&gt;void&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt; CanEntityAddedOnJanuaryRemoved_Test()&lt;/span&gt;&lt;br /&gt; &lt;span style="background:#ffffff;color:#000000;"&gt;{&lt;/span&gt;&lt;br /&gt;     &lt;span style="background:#ffffff;color:#000000;"&gt;&lt;/span&gt;&lt;span style="background:#ffffff;color:#0000ff;"&gt;using&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt; (&lt;/span&gt;&lt;span style="background:#ffffff;color:#2b91af;"&gt;ShimsContext&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt;.Create())&lt;/span&gt;&lt;br /&gt;     &lt;span style="background:#ffffff;color:#000000;"&gt;{&lt;/span&gt;&lt;/div&gt; &lt;/div&gt; &lt;/div&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Ja aizmirsīsim kontekstu ievietot &lt;font face="Consolas"&gt;using&lt;/font&gt; blokā, tad simulācija būs spēkā visa &lt;font face="Consolas"&gt;AppDomain&lt;/font&gt; dzīves laikā. Tāpēc svarīgi ir atcerēties kontrolēt &lt;font face="Consolas"&gt;Shim&lt;/font&gt; konteksta scope. Pēc tam, kad &lt;font face="Consolas"&gt;Shim&lt;/font&gt; konteksts ir uzstādīts, ir nepieciešams nodot instrukcijas klasei, kura jāsimulē.&lt;/p&gt;    &lt;p&gt;Tas notiek ar lambda izteiksmes palīdzību:&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:c93eda98-a7ae-4398-83d3-81158d423a00" class="wlWriterEditableSmartContent" style="float:none;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;display:inline;padding-right:0px;"&gt; &lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt; &lt;div style="background-color:#ffffff;max-height:300px;overflow:auto;padding:2px 5px;"&gt;&lt;span style="background:#ffffff;color:#0000ff;"&gt;using&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt; (&lt;/span&gt;&lt;span style="background:#ffffff;color:#2b91af;"&gt;ShimsContext&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt;.Create())&lt;/span&gt;&lt;br /&gt; &lt;span style="background:#ffffff;color:#000000;"&gt;{&lt;/span&gt;&lt;br /&gt;     &lt;span style="background:#ffffff;color:#000000;"&gt;&lt;/span&gt;&lt;span style="background:#ffffff;color:#2b91af;"&gt;ShimDateTime&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt;.NowGet = () =&amp;gt; &lt;/span&gt;&lt;span style="background:#ffffff;color:#0000ff;"&gt;new&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt; &lt;/span&gt;&lt;span style="background:#ffffff;color:#2b91af;"&gt;DateTime&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt;(2012, 1, 1);&lt;/span&gt;&lt;/div&gt; &lt;/div&gt; &lt;/div&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Šajā gadījumā tiek simulēts &lt;font face="Consolas"&gt;&lt;font color="#2b91af"&gt;DateTime&lt;/font&gt;.Now &lt;/font&gt;īpašības uzvedība un atgrieztā vērtība.&lt;/p&gt;    &lt;p&gt;Izpildot vienuma testu redzams, ka Shim konteksts strādā un patiešām &lt;font face="Consolas"&gt;&lt;font color="#2b91af"&gt;DateTime&lt;/font&gt;.Now &lt;/font&gt;property atgriež nepieciešamo vērtību.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_064AACF2.png" rel="lightbox"&gt;&lt;img title="" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin:0px auto;display:block;padding-right:0px;border-top-width:0px;" border="0" alt="" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_662FA034.png" width="842" height="468" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Ja nepieciešams, piemēram, aizvietot vispār &lt;font face="Consolas"&gt;EntityValidator&lt;/font&gt; loģiku un testēt pavisam kādu citu sistēmas apgabalu pieņemot , ka vienumu testā šai klasei vienmēr ir jāatgriež &lt;font face="Consolas"&gt;true &lt;/font&gt;vērtība?&lt;/p&gt;    &lt;p&gt;Tas nozīmē, ka iespējami ir 2 scenāriji:&lt;/p&gt;    &lt;ol&gt;     &lt;li&gt;Izmantojam &lt;font face="Consolas"&gt;Shims&lt;/font&gt; ģenerācijas veidu un pielietojam jau apskatīto tehnoloģiju, kā modificēt vērtības klasēm, kurām nespējam piekļūt vienkāršā veidā. &lt;/li&gt;      &lt;li&gt;Pārdefinējam metodi &lt;font face="Consolas"&gt;CanEntityRemove()&lt;/font&gt; par virtuālu un izmantojam &lt;font face="Consolas"&gt;Stub&lt;/font&gt; klašu “izbāzeņu” ģenerācijas veidu, lai simulētu, ka dzēst no sistēmas var entity ar jebkādu datumu. &lt;/li&gt;   &lt;/ol&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Lai šāda veida uzvedību nosimulētu, nepieciešams atkal &lt;font face="Consolas"&gt;Stub&lt;/font&gt; ģenerētajai klasei noinstruēt, ka vienmēr neskatoties uz kādu entity pievienošanas datumu, jāatgriež vienmēr &lt;font face="Consolas"&gt;true&lt;/font&gt;.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:a65d4d5c-2b79-49bf-8041-a59b4a18cf81" class="wlWriterEditableSmartContent" style="float:none;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;display:inline;padding-right:0px;"&gt; &lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt; &lt;div style="background-color:#ffffff;max-height:300px;overflow:auto;padding:2px 5px;"&gt;&lt;span style="background:#ffffff;color:#000000;"&gt;[&lt;/span&gt;&lt;span style="background:#ffffff;color:#2b91af;"&gt;TestMethod&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt;]&lt;/span&gt;&lt;br /&gt; &lt;span style="background:#ffffff;color:#0000ff;"&gt;public&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt; &lt;/span&gt;&lt;span style="background:#ffffff;color:#0000ff;"&gt;void&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt; CanEntityRemove_StubTest()&lt;/span&gt;&lt;br /&gt; &lt;span style="background:#ffffff;color:#000000;"&gt;{&lt;/span&gt;&lt;br /&gt;     &lt;span style="background:#ffffff;color:#000000;"&gt;&lt;/span&gt;&lt;span style="background:#ffffff;color:#0000ff;"&gt;var&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt; stub = &lt;/span&gt;&lt;span style="background:#ffffff;color:#0000ff;"&gt;new&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt; &lt;/span&gt;&lt;span style="background:#ffffff;color:#2b91af;"&gt;StubEntityValidator&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt;();&lt;/span&gt;&lt;br /&gt;     &lt;span style="background:#ffffff;color:#000000;"&gt;stub.CanEntityRemoveEntity = (entity =&amp;gt; &lt;/span&gt;&lt;span style="background:#ffffff;color:#0000ff;"&gt;true&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt;);&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;     &lt;span style="background:#ffffff;color:#000000;"&gt;&lt;/span&gt;&lt;span style="background:#ffffff;color:#0000ff;"&gt;var&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt; result = stub.CanEntityRemove(&lt;/span&gt;&lt;span style="background:#ffffff;color:#0000ff;"&gt;new&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt; &lt;/span&gt;&lt;span style="background:#ffffff;color:#2b91af;"&gt;Entity&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt; {Added = &lt;/span&gt;&lt;span style="background:#ffffff;color:#0000ff;"&gt;new&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt; &lt;/span&gt;&lt;span style="background:#ffffff;color:#2b91af;"&gt;DateTime&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt;(2012, 12, 12)});&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;     &lt;span style="background:#ffffff;color:#000000;"&gt;&lt;/span&gt;&lt;span style="background:#ffffff;color:#2b91af;"&gt;Assert&lt;/span&gt;&lt;span style="background:#ffffff;color:#000000;"&gt;.IsTrue(result);&lt;/span&gt;&lt;br /&gt; &lt;span style="background:#ffffff;color:#000000;"&gt;}&lt;/span&gt;&lt;/div&gt; &lt;/div&gt; &lt;/div&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Šāda veida Stub ģenerētu uz noinstruēt klases instance var padot tālāk jau citām komponentēm, kurām nepieciešama šis objekts.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Cerams, ka noderēs!&lt;/p&gt; &lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnet.lv/aggbug.aspx?PostID=338131" width="1" height="1"&gt;</content><author><name>valdis.iljuconoks</name><uri>http://dotnet.lv/members/valdis.iljuconoks/default.aspx</uri></author><category term="C# 5.0" scheme="http://dotnet.lv/blogs/vi/archive/tags/C_2300_+5.0/default.aspx" /><category term="Unit testing" scheme="http://dotnet.lv/blogs/vi/archive/tags/Unit+testing/default.aspx" /><category term="Visual Studio Dev 11" scheme="http://dotnet.lv/blogs/vi/archive/tags/Visual+Studio+Dev+11/default.aspx" /><category term=".NET4.5" scheme="http://dotnet.lv/blogs/vi/archive/tags/.NET4.5/default.aspx" /></entry><entry><title>Marta knockout.js prezentācijas materiāli</title><link rel="alternate" type="text/html" href="/blogs/vi/archive/2012/03/09/marta-knockout-js-prezent-cijas-materi-li.aspx" /><id>/blogs/vi/archive/2012/03/09/marta-knockout-js-prezent-cijas-materi-li.aspx</id><published>2012-03-09T00:22:00Z</published><updated>2012-03-09T00:22:00Z</updated><content type="html">&lt;div id="post_content"&gt;   &lt;p&gt;Marta prezentācijas materāli Microsoft .Net user group pasākumā par knockout.js bibliotēku, kas dod lielisku iespēju vienkārši un deklaratīvi veidot interakctīvas aplikācijas. Ar šīs bibliotēkas palīdzību iespējams ērti un viegli veidot sarežģītas aplikācijas, kurām nepieciešamas sarežģītas klieta puses DOM manipulācijas.&lt;/p&gt;    &lt;p&gt;&lt;img style="margin:5px 50px 0px 0px;display:inline;float:right;" align="right" src="http://learn.knockoutjs.com/Content/App/icon.png" width="130" height="130" alt="" /&gt;&lt;/p&gt;    &lt;div style="width:425px;" id="__ss_11942851"&gt;&lt;strong style="margin:12px 0px 4px;display:block;"&gt;&lt;a title="Knockoutjs UG meeting presentation" href="http://www.slideshare.net/valdisiljuconoks/knockoutjs-ug-meeting-presentation" target="_blank"&gt;Knockoutjs UG meeting presentation&lt;/a&gt;&lt;/strong&gt;       &lt;div style="padding-bottom:12px;padding-left:0px;padding-right:0px;padding-top:5px;"&gt;View more &lt;a href="http://www.slideshare.net/thecroaker/death-by-powerpoint" target="_blank"&gt;PowerPoint&lt;/a&gt; from &lt;a href="http://www.slideshare.net/valdisiljuconoks" target="_blank"&gt;Valdis Iljuconoks&lt;/a&gt; &lt;/div&gt;   &lt;/div&gt;    &lt;p&gt;Pielikumā prezentācijas ppt - &lt;a href="https://skydrive.live.com/redir.aspx?cid=38746a08ebe72be7&amp;amp;resid=38746A08EBE72BE7!522&amp;amp;parid=38746A08EBE72BE7!521&amp;amp;authkey=!AMuTI-uxjwfiz2E"&gt;šeit&lt;/a&gt;.&lt;/p&gt;    &lt;p&gt;Kā arī izejas kods, ja nu kādam tiešām ieinteresēja, iespējams papētīt - &lt;a href="https://skydrive.live.com/redir.aspx?cid=38746a08ebe72be7&amp;amp;resid=38746A08EBE72BE7!523&amp;amp;parid=38746A08EBE72BE7!521&amp;amp;authkey=!AGD5cY0ceugiqRE"&gt;šeit&lt;/a&gt;.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Cerams, ka noderēs!&lt;/p&gt; &lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnet.lv/aggbug.aspx?PostID=296841" width="1" height="1"&gt;</content><author><name>valdis.iljuconoks</name><uri>http://dotnet.lv/members/valdis.iljuconoks/default.aspx</uri></author><category term="javascript client-side UI" scheme="http://dotnet.lv/blogs/vi/archive/tags/javascript+client-side+UI/default.aspx" /></entry><entry><title>Izejas koda review process made easy VS 11</title><link rel="alternate" type="text/html" href="/blogs/vi/archive/2011/10/25/izejas-koda-review-process-made-easy-vs-11.aspx" /><id>/blogs/vi/archive/2011/10/25/izejas-koda-review-process-made-easy-vs-11.aspx</id><published>2011-10-25T20:53:51Z</published><updated>2011-10-25T20:53:51Z</updated><content type="html">&lt;div id="post_content"&gt;&lt;p&gt;Nesen Microsoft laida klajā Visual Studio 11 Developer Preview, kas paredzēts dažādiem agrīnās programmas interesentiem, kuri neskatoties uz pieļaujamajām kļūdām un runtime exception studijas darbošanās laikā, tāpat instalē, pēta un skatās, ko Microsoft ir šoreiz saražojis un ko jaunu piedāvā.&lt;/p&gt;  &lt;p&gt;Āri Team Foundation Server nav palicis maliņā un arī šai brīnišķīgajai programmatūrai ir pieejama 11 versija, kas paredzēta, lai mēs varētu ieskatīties, kas mūs sagaida pēc kāda laiciņa.&lt;/p&gt;  &lt;p&gt;Šoreiz aplūkosim, kas notiek ar code-review procesu, kas līdz šim īpaši atbalstīts pašā studijā netika. Pie izejas koda checkin procesa bija viens vienīgs text box lauciņš, kurā var ierakstīt kaut ko par code-review procesu, kas notika pirms šī konkrētā check-in. Ir pieejami arī visādi rīki un trešās puses spraudņi, kas šo procesu mēģināja iedzīvināt studijā, bet līdz šim tas nav bijis 1st class citizen VS programmā.&lt;/p&gt;  &lt;p&gt;Ar Dev 11 versiju viss izskatās, ka nedaudz ir pamainījies un code review process nu ir kļuvis daudz ērtāks un pārskatāmāks un tuvāks izstrādātājiem, jo integrējas tieši TFS serverī.&lt;/p&gt;  &lt;p&gt;Btw, TFS serveris ir palaists arī mākonī (Windows Azure) un atrodams &lt;a href="http://tfspreview.com" target="_blank"&gt;tfspreview.com&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Tātad viss code review process, protams, sākas ar check-in procesu. Pagaidām neatradu check-in politiku, kas aizliegtu izejas koda ievietošanu iekš repozitorija, nepaprasot kādam source code review akceptu, bet domājams, ka šāda veida politikas sāks ražot, kad platforma būs tuvāk kādam publiskākam un daudz stabilākam jūdžakmenim.&lt;/p&gt;  &lt;p&gt;Pirmāmkārtām, ir jau mainījies viss darbs ar TFS source code repozitoriju. Sadarbība ar TFS notiek pārsvarā caur Team Explorer logu.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_6EBE2E7A.png" rel="lightbox"&gt;&lt;img title="" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin-left:auto;display:block;padding-right:0px;border-top-width:0px;margin-right:auto;" border="0" alt="" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_679EF202.png" width="385" height="482" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Izejas koda repozitorijā ievietošanas laikā ir iespējams uzsākt izejas koda pārlūkošanas procesu.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_607FB58A.png" rel="lightbox"&gt;&lt;img title="image" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin:0px auto;display:block;padding-right:0px;border-top-width:0px;" border="0" alt="image" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_2768D888.png" width="352" height="233" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Šī komanda savukārt atver jauna code review pieprasījuma formu, kurā iespējams diezgan ērtā veidā pievienot izejas koda pārlūkotājus no projekta komandas biedriem.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_1C3F4E3E.png" rel="lightbox"&gt;&lt;img title="image" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin:0px auto;display:block;padding-right:0px;border-top-width:0px;" border="0" alt="image" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_7C244180.png" width="359" height="449" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Šajā forma ir iespējams uzrādīt nosaukumu code review pieprasījumam, kā arī pievienot kādus papildus komentārus, kas palīdzētu ātrāk reviewer’im saprast, kas un kā ir jāpārlūko un kā efektīvāk un ātrāk dot savu akceptu, lai neizveidotos kaut kādi pudeļu kakliņi vai citi aizcietējumi.&lt;/p&gt;  &lt;p&gt;Pagaidām gan īsti neatradu veidu, kādā varētu ērti parakstīties uz notikumiem TFS serverī, kas dotu iespēju momentā, kad kāds ir pieprasījis veikt code review no manas, es par to uzzinātu savā e-pasta kastītē vai kādā citā sociālo tīklu notifikācijas veidā.&lt;/p&gt;  &lt;p&gt;Atradu gan vienu notikumu, ka varētu strādāt šajā gadījumā, neesmu vēl līdz galam izmēģinājis vai tas strādā ar TFS Services Preview, kurā īsti SMTP serveri nav iespējams konfigurēt. TFS notikums ir:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_2E1BE20B.png" rel="lightbox"&gt;&lt;img title="image" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin:0px auto;display:block;padding-right:0px;border-top-width:0px;" border="0" alt="image" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_22F257C1.png" width="585" height="344" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Lai nu kā, bet otrs lietotājs, no kā tiek pieprasīts veikt code review, savā darāmo darbu sarakstā ierauga sekojošu ainu:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_54E9F84B.png" rel="lightbox"&gt;&lt;img title="image" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin:0px auto;display:block;padding-right:0px;border-top-width:0px;" border="0" alt="image" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_34CEEB8E.png" width="337" height="438" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Šajā logā pārskatāmā veidā redzams, ka kāds ir pieprasījis veikt code review kādai komponentei. Atverot konkrēto code review pieprasījumu, iespējams ieraudzīt detalizētāku informāciju par to, kas ir pieprasīts pārskatīt, kurš to izdarīja, kāds ir status un vai ir vēl kāds, kam tika nosūtīts šāds pats code review pieprasījumus (un ja ir bijis nosūtīts, tad iespējams arī ērtā veidā uzreiz redzēt citu pārskatītāju sniegtos verdiktus, ja nu pašam raustās vienpersoniski pieņemt lēmumu).&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_29A56144.png" rel="lightbox"&gt;&lt;img title="image" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin:0px auto;display:block;padding-right:0px;border-top-width:0px;" border="0" alt="image" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_5B9D01CE.png" width="328" height="426" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Un starp citu, pārsteigums man bija, kad divreiz nospiedu uz “Program.cs”. Es gaidīju, kad atvērsies automaģiski WinMerge vai kāda cita jauka rīka logs, kurā varētu redzēt faila veiktās izmaiņas. Bet šoreiz izmaiņu fails tika atvērts tieši Visual Studio 11 logā.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_7E60CA3C.png" rel="lightbox"&gt;&lt;img title="image" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin:0px auto;display:block;padding-right:0px;border-top-width:0px;" border="0" alt="image" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_30586AC7.png" width="635" height="301" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Šāda veida funkcionalitāte manuprāt ir liels solis uz priekšu Visual Studio feature sarakstā. Izmaiņas var aplūkot dažādos režīmos: pārklājošais, viens otram blakus, rādīt tikai labo pusi vai arī rādīt tikai kreiso pusi. &lt;/p&gt;  &lt;p&gt;Vēlāk kad visas izmaiņas ir aplūkotas, pārbaudīts un akceptētas, ir iespējams noslēgt code review procesu. Šim nolūkam kaut kādā veidā ir jāģenerē code review request response TFS work items, kas sniegtu informāciju par izejas koda pārlūkošanas procesa gala rezultātu. Šo darbību ir iespējams izdarīt no paša Team Explorer.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_103D5E0A.png" rel="lightbox"&gt;&lt;img title="image" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin:0px auto;display:block;padding-right:0px;border-top-width:0px;" border="0" alt="image" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_0513D3C0.png" width="359" height="467" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Pozitīvi ir tas, ka katrai darbībai ir iespējams pievienot kādu komentāru. Ir iespējams pierakstīt savus komentārus par izejas koda pārlūkošanas pieprasījumu kopumā, kā arī ir iespējams atstāt komentāru par katru atsevišķo failu arī.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_64F8C702.png" rel="lightbox"&gt;&lt;img title="image" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin:0px auto;display:block;padding-right:0px;border-top-width:0px;" border="0" alt="image" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_16F0678D.png" width="359" height="450" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Pozitīvi ir tas, ka viss paliek TFS arhīva datubāzē. Šajā gadījumā code reviewer ir iespējams atbildēt uz pieprasījumu ar kādu no iespējamajām atbildēt:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Looks Good&lt;/strong&gt; – Viss ir forši, turpini darbu. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;With Commens&lt;/strong&gt; – Man ir pāris jautājumi. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Needs Work&lt;/strong&gt; – Es, protams, saprotu, ka es gudrs un smalks programmētājs, bet nu tādus mēs*** no Tevis nebiju gaidījis. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Pēc tam, kad code reviewer ir beidzis savu darbu - atzīmējis savas domas par veiktajām koda izmaiņām – kontrole tālāk nonāk pieprasītāja rokās, kur viņš var izlemt, ko iesākt tālāk ar šo code review pieprasījumu.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_76D55ACF.png" rel="lightbox"&gt;&lt;img title="image" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin:0px auto;display:block;padding-right:0px;border-top-width:0px;" border="0" alt="image" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_04A7A0CB.png" width="359" height="95" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Ja izvēlas “Complete”, tad code review process ir noslēdzies un sākotnējais autors izmainītos izejas failus var ievietot repozitorijā. Pie izejas koda ievietošanas procesa tiek arī pierakstīts, kādā code review kontekstā šis konkrētais labojums via papildinājumus ir nonācis izejas koda repozitorijā. Šo ierakstu(-s) var aplūkot, kad skatāmies uz changeset izmaiņām.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_797E1680.png" rel="lightbox"&gt;&lt;img title="image" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin:0px auto;display:block;padding-right:0px;border-top-width:0px;" border="0" alt="image" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_2B75B70B.png" width="523" height="307" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Starpcitu, noskaidroju, ka code review procesu var iedarbināt arī pēc tam, kad izejas kods ir ievietots repozitorijā. Piemēram, šajā gadījumā sūtām source code review pieprasījumu par veselu changeset’u.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_204C2CC1.png" rel="lightbox"&gt;&lt;img title="image" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin:0px auto;display:block;padding-right:0px;border-top-width:0px;" border="0" alt="image" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_5243CD4B.png" width="556" height="321" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Visi šie code review pieprasījumi galu galā TFS serverī parādās kā parasti WI (Work Item), kas nozīmē, ka šiem WI ir papildus meta datu informācija, kas satur vitālu informāciju par šo labojumu. Piemēram, TFS serverī ir iespējams sameklēt un atvērt šo code review pieprasījumu kā jebkuru citu WI.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_3228C08E.png" rel="lightbox"&gt;&lt;img title="image" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;float:none;padding-top:0px;padding-left:0px;margin:0px auto;display:block;padding-right:0px;border-top-width:0px;" border="0" alt="image" src="http://dotnet.lv/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vi/image_5F00_thumb_5F00_26FF3644.png" width="584" height="474" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Kā arī ir iespējams šo code review pieprasījumu atvērt ar Team Explorer (nospiežot saiti kreisajā augšējā stūrī – “Open Code Review in Team Explorer”), kas dod sākotnējo code review skatu, kurā var aplūkot visus iekļautos failus un komentārus, ja tādi bijuši.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Izskatās, ka Microsoft cilvēki nopietni sāk domāt par koda kvalitāti un ievieš tik vitāli svarīgu procesu kā code review jau kā pirmās klases Visual Studio ģimenes locekli. Dzīvosim un redzēsim kā tas viss attīstīsies tālāk!&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Cerams, ka noderēs!&lt;/p&gt;&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnet.lv/aggbug.aspx?PostID=246194" width="1" height="1"&gt;</content><author><name>valdis.iljuconoks</name><uri>http://dotnet.lv/members/valdis.iljuconoks/default.aspx</uri></author><category term="Tfs" scheme="http://dotnet.lv/blogs/vi/archive/tags/Tfs/default.aspx" /><category term="Practices" scheme="http://dotnet.lv/blogs/vi/archive/tags/Practices/default.aspx" /><category term="Windows Azure" scheme="http://dotnet.lv/blogs/vi/archive/tags/Windows+Azure/default.aspx" /><category term="TFS 11" scheme="http://dotnet.lv/blogs/vi/archive/tags/TFS+11/default.aspx" /><category term="Visual  Studio Dev 11" scheme="http://dotnet.lv/blogs/vi/archive/tags/Visual++Studio+Dev+11/default.aspx" /></entry></feed>