<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tim Van Wassenhove &#187; Information Technology</title>
	<atom:link href="http://www.timvw.be/category/information-technology/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.timvw.be</link>
	<description>The journey of a thousand miles begins with one step.</description>
	<lastBuildDate>Thu, 29 Jul 2010 17:07:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Quick reminder about the workings of Type.IsAssignableFrom</title>
		<link>http://www.timvw.be/quick-reminder-about-the-workings-of-type-isassignablefrom/</link>
		<comments>http://www.timvw.be/quick-reminder-about-the-workings-of-type-isassignablefrom/#comments</comments>
		<pubDate>Wed, 21 Jul 2010 09:55:23 +0000</pubDate>
		<dc:creator>timvw</dc:creator>
				<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://www.timvw.be/?p=1833</guid>
		<description><![CDATA[Here is a quick reminder about the workings of Type.IsAssignableFrom: class Fruit {} class Banana : Fruit {} [Test] public void CanAssignBananaToFruit() { var fruit = typeof (Fruit); var banana = typeof (Banana); Assert.IsTrue(fruit.IsAssignableFrom(banana)); } [Test] public void CanNotAssignFruitToBanana() { var fruit = typeof(Fruit); var banana = typeof(Banana); Assert.IsFalse(banana.IsAssignableFrom(fruit)); } I really hate this API [...]]]></description>
			<content:encoded><![CDATA[<p>Here is a quick reminder about the workings of <a href="http://msdn.microsoft.com/en-us/library/system.type.isassignablefrom.aspx">Type.IsAssignableFrom</a>:</p>

<pre class="brush: csharp;">class Fruit {}
class Banana : Fruit {}

[Test]
public void CanAssignBananaToFruit()
{
 var fruit = typeof (Fruit);
 var banana = typeof (Banana);
 Assert.IsTrue(fruit.IsAssignableFrom(banana));
}

[Test]
public void CanNotAssignFruitToBanana()
{
 var fruit = typeof(Fruit);
 var banana = typeof(Banana);
 Assert.IsFalse(banana.IsAssignableFrom(fruit));
}</pre>

<p>I really hate this API because it always seems backward to me. Here is how i really want to use it:</p>

<pre class="brush: csharp;">Assert.IsTrue(banana.CanBeAssignedTo(fruit));
Assert.IsFalse(fruit.CanBeAssignedTo(banana));</pre>

<p>With the aid of an extension method we can easily achieve this:</p>

<pre class="brush: csharp;">public static bool CanBeAssignedTo(this Type sourceType, Type destinationType)
{
 return destinationType.IsAssignableFrom(sourceType);
}</pre>]]></content:encoded>
			<wfw:commentRss>http://www.timvw.be/quick-reminder-about-the-workings-of-type-isassignablefrom/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Removing Dead Tracks (Duplicates that don&#8217;t exist) from iTunes using C#</title>
		<link>http://www.timvw.be/removing-dead-tracks-duplicates-that-dont-exist-from-itunes-using-c/</link>
		<comments>http://www.timvw.be/removing-dead-tracks-duplicates-that-dont-exist-from-itunes-using-c/#comments</comments>
		<pubDate>Tue, 20 Jul 2010 17:59:15 +0000</pubDate>
		<dc:creator>timvw</dc:creator>
				<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://www.timvw.be/?p=1811</guid>
		<description><![CDATA[Last week i noticed the following post from Scott Hanselman: Removing Dead Tracks (Duplicates that don&#8217;t exist) from iTunes using C#. As a good boy scout i noticed that these days iTunesLib.IITTrackCollection inherits from IEnumerable so i rewrote the code a little: class Program { [STAThread] static void Main() { var itunes = new iTunesApp(); [...]]]></description>
			<content:encoded><![CDATA[<p>Last week i noticed the following post from Scott Hanselman: <a href="http://www.hanselman.com/blog/RemovingDeadTracksDuplicatesThatDontExistFromITunesUsingC.aspx">Removing Dead Tracks (Duplicates that don&#8217;t exist) from iTunes using C#</a>. As a good boy scout i noticed that these days iTunesLib.IITTrackCollection inherits from IEnumerable so i rewrote the code a little:</p>

<pre class="brush: csharp;">class Program
{
 [STAThread]
 static void Main()
 {
  var itunes = new iTunesApp();
  itunes.DeleteTracksThatDoNotExist();
 }
}

public static class ITunesExtensions
{
 public static void DeleteTracksThatDoNotExist(this IiTunes itunes)
 {
  var tracksThatDoNotExist = FindTracksThatDoNotExist(itunes);
  foreach (var track in tracksThatDoNotExist) track.Delete();
 }

 public static IEnumerable&lt;IITFileOrCDTrack&gt; FindTracksThatDoNotExist(this IiTunes iTunes)
 {
  return iTunes.LibraryPlaylist.Tracks
   .OfType&lt;IITFileOrCDTrack&gt;()
   .Where(track =&gt; !File.Exists(track.Location));
 }
}</pre>]]></content:encoded>
			<wfw:commentRss>http://www.timvw.be/removing-dead-tracks-duplicates-that-dont-exist-from-itunes-using-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sometimes you can write it better than Resharper</title>
		<link>http://www.timvw.be/sometimes-you-can-write-it-better-than-resharper/</link>
		<comments>http://www.timvw.be/sometimes-you-can-write-it-better-than-resharper/#comments</comments>
		<pubDate>Sat, 03 Jul 2010 16:11:11 +0000</pubDate>
		<dc:creator>timvw</dc:creator>
				<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://www.timvw.be/?p=1768</guid>
		<description><![CDATA[Here is a real-life example of when people are much better expressing intent than a tool: Consider the following code from a typical Silverlight Navigation application: foreach (UIElement child in LinksStackPanel.Children) { var hb = child as HyperlinkButton; if (hb != null &#38;&#38; hb.NavigateUri != null) { .. } } Resharper proposed to write this [...]]]></description>
			<content:encoded><![CDATA[<p>Here is a real-life example of when people are much better expressing intent than a tool: Consider the following code from a typical Silverlight Navigation application:</p>

<pre class="brush: csharp;">foreach (UIElement child in LinksStackPanel.Children)
{
 var hb = child as HyperlinkButton;
 if (hb != null &amp;&amp; hb.NavigateUri != null)
 { .. }
}</pre>

<p>Resharper proposed to write this as following:</p>

<pre class="brush: csharp;">foreach (var hb in LinksStackPanel.Children
 .Select(child =&gt; child as HyperlinkButton)
 .Where(hb =&gt; hb != null &amp;&amp; hb.NavigateUri != null)) 
{ .. }</pre> 

<p>Here is what i wrote instead:</p>

<pre class="brush: csharp;">foreach (var hb in LinksStackPanel.Children
 .OfType&lt;HyperlinkButton&gt;()
 .Where(hb =&gt; hb.NavigateUri != null)) 
{ .. }</pre>]]></content:encoded>
			<wfw:commentRss>http://www.timvw.be/sometimes-you-can-write-it-better-than-resharper/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Setting up a self-contained build</title>
		<link>http://www.timvw.be/setting-up-a-self-contained-build/</link>
		<comments>http://www.timvw.be/setting-up-a-self-contained-build/#comments</comments>
		<pubDate>Sat, 26 Jun 2010 15:31:35 +0000</pubDate>
		<dc:creator>timvw</dc:creator>
				<category><![CDATA[MSBuild]]></category>

		<guid isPermaLink="false">http://www.timvw.be/?p=1779</guid>
		<description><![CDATA[Here is something you may have experienced already: As a newcomer on an existing project, you check out the code from source-control and discover that the build is broken. When you ask around no-one else seems to have that problem but a helpful collegue is kind enough to tell you that you can find the [...]]]></description>
			<content:encoded><![CDATA[<p>Here is something you may have experienced already: As a newcomer on an existing project, you check out the code from source-control and discover that the build is broken. When you ask around no-one else seems to have that problem but a helpful collegue is kind enough to tell you that you can find the installers for the missing dependencies at location X (Let&#8217;s not even mention the places where those installers are not available *sigh*).</p>

<p>Anway, in order to avoid such a situation you could organize your solution in such a way that all the dependencies (libraries and tools) are part of it. A typical folder structure would look like this:</p>

<img src="http://www.timvw.be/wp-content/images/solution_tools.png" alt="screenshot of typical solution folder organization" />

<p>In order to get those files out of the installer and in your solution (instead of installed under %Program Files%) you could do an administrative install of the msi (eg: msiexec /a Blah.msi) but i find it easier to use <a href="http://www.qwerty-msi.com/">Qwerty.Msi</a>.</p>

<p>Here are a couple of settings you may want to add to your build configuration in order to make your self-contained build work:</p>

<pre class="brush: xml;">&lt;!-- Configure solution directories --&gt;
&lt;BasePath Condition=&quot;'$(BasePath)'==''&quot;&gt;$(MSBuildThisFileDirectory)..&lt;/BasePath&gt;
&lt;BuildPath&gt;$(BasePath)\build&lt;/BuildPath&gt;
&lt;SourcePath&gt;$(BasePath)\src&lt;/SourcePath&gt;
&lt;ToolsPath&gt;$(BasePath)\tools&lt;/ToolsPath&gt;
		
&lt;!-- Configure tool directories --&gt;
&lt;!-- the ending \ is required for the extension pack --&gt;
&lt;ExtensionTasksPath&gt;$(ToolsPath)\MSBuild.ExtensionPack\&lt;/ExtensionTasksPath&gt;
&lt;MSBuildCommunityTasksPath&gt;$(ToolsPath)\MSBuildCommunityTasks&lt;/MSBuildCommunityTasksPath&gt;	
&lt;ILMergeToolPath&gt;$(ToolsPath)\ILMerge&lt;/ILMergeToolPath&gt;
&lt;SvnToolPath&gt;$(ToolsPath)\Subversion\bin&lt;/SvnToolPath&gt;	
&lt;!-- wix will use this property to determine the location of other files --&gt;
&lt;WixToolPath&gt;$(ToolsPath)\Wix&lt;/WixToolPath&gt;
		
&lt;!-- Configure target file paths --&gt;
&lt;CommonTargetsPath&gt;$(BuildPath)\common.targets&lt;/CommonTargetsPath&gt;
&lt;MSBuildCommunityTasksTargetsPath&gt;$(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.Targets&lt;/MSBuildCommunityTasksTargetsPath&gt;
&lt;ExtensionPackTargetsPath&gt;$(ExtensionTasksPath)MSBuild.ExtensionPack.tasks&lt;/ExtensionPackTargetsPath&gt;

&lt;!-- Configure WIX --&gt;
&lt;WixTargetsPath&gt;$(WixToolPath)\Wix.targets&lt;/WixTargetsPath&gt;
&lt;WixTasksPath&gt;$(WixToolPath)\WixTasks.dll&lt;/WixTasksPath&gt;
&lt;WixTargetsPath&gt;$(WixToolPath)\Wix.targets&lt;/WixTargetsPath&gt;
&lt;WixTasksPath&gt;$(WixToolPath)\WixTasks.dll&lt;/WixTasksPath&gt;
&lt;LuxTargetsPath&gt;$(WixToolPath)\Lux.targets&lt;/LuxTargetsPath&gt;
&lt;LuxTasksPath&gt;$(WixToolPath)\LuxTasks.dll&lt;/LuxTasksPath&gt;
&lt;LuxTargetsPath&gt;$(WixToolPath)\Lux.targets&lt;/LuxTargetsPath&gt;
&lt;LuxTasksPath&gt;$(WixToolPath)\LuxTasks.dll&lt;/LuxTasksPath&gt;</pre>

<p>With this solution in place the next &#8216;new guy&#8217; does not have to waste time trying to figure out where those dependencies are <img src='http://www.timvw.be/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>]]></content:encoded>
			<wfw:commentRss>http://www.timvw.be/setting-up-a-self-contained-build/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Convention over configuration with MSBuild</title>
		<link>http://www.timvw.be/convention-over-configuration-with-msbuild/</link>
		<comments>http://www.timvw.be/convention-over-configuration-with-msbuild/#comments</comments>
		<pubDate>Sat, 26 Jun 2010 12:44:52 +0000</pubDate>
		<dc:creator>timvw</dc:creator>
				<category><![CDATA[MSBuild]]></category>

		<guid isPermaLink="false">http://www.timvw.be/?p=1766</guid>
		<description><![CDATA[A while ago i blogged that i was using the TemplateFile task from the]]></description>
			<content:encoded><![CDATA[<p>A while ago i blogged that i was using the TemplateFile task from the <a hrefhttp://msbuildtasks.tigris.org/">MSBuild Community Tasks Project</a> to generate configuration files. Each project that required templating would have modified it&#8217;s csproj file as following:</p>

<pre class="brush: xml;">&lt;!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
Other similar extension points exist, see Microsoft.Common.targets. --&gt;
&lt;Import Project=&quot;$(MSBuildProjectDirectory)\config.msbuild&quot; /&gt;
&lt;Target Name=&quot;BeforeBuild&quot;&gt;
 &lt;CallTarget Targets=&quot;GenerateConfigurationFiles&quot; /&gt;
&lt;/Target&gt;</pre>

<p>And each of these config.msbuild files looked as following:</p>

<pre class="brush: xml;">
&lt;TemplateFile Template=&quot;web.template.config&quot; OutputFileName=&quot;web.config&quot; Tokens=&quot;@(TemplateTokens)&quot; /&gt;
&lt;TemplateFile Template=&quot;Config\WcfClients.config&quot; OutputFileName=&quot;Config\WcfClients.config&quot; Tokens=&quot;@(TemplateTokens)&quot; /&gt;
&lt;/Target&gt;</pre>

<p>As you can notice the convention here is that each template file has &#8216;.template.&#8217; in it&#8217;s name, and the name of an output file is the template file name without &#8216;.template.&#8217;.</p>

<pre class="brush: xml;">
 &lt;!-- valide input --&gt;
 &lt;Error Condition=&quot;'$(SourceFile)'==''&quot; Text=&quot;Missing SourceFile&quot; /&gt;
 &lt;!-- calculate destination file --&gt;
 &lt;RegexReplace Input=&quot;$(SourceFile)&quot; Expression=&quot;(\.template)\.&quot; Replacement=&quot;.&quot; Count=&quot;1&quot;&gt;
  &lt;Output TaskParameter=&quot;Output&quot; PropertyName=&quot;DestinationFile&quot; /&gt;
 &lt;/RegexReplace&gt;
 &lt;!-- generate file --&gt;
 &lt;TemplateFile Template=&quot;$(SourceFile)&quot; OutputFileName=&quot;$(DestinationFile)&quot; Tokens=&quot;@(TemplateTokens)&quot; /&gt;
&lt;/Target&gt;</pre>

<p>Now that we can do it for one file, we can do it for many files too:</p>

<pre class="brush: xml;">
 &lt;!-- valide input --&gt;
 &lt;Error Condition=&quot;'$(SourceDir)'==''&quot; Text=&quot;Missing SourceDir&quot; /&gt;
 &lt;!-- find all template files --&gt;
 &lt;ItemGroup&gt;
  &lt;TemplateFiles Include=&quot;$(SourceDir)\**\*.template.*&quot; Exlude=&quot;$(SourceDir)\**\*.svn*&quot; /&gt;
 &lt;/ItemGroup&gt;
 &lt;!-- process each template file --&gt;
 &lt;MSBuild Projects=&quot;$(MSBuildProjectFile)&quot; Targets=&quot;ProcessTemplate&quot; Properties=&quot;SourceFile=%(TemplateFiles.FullPath)&quot; /&gt;
&lt;/Target&gt;</pre>

<p>After these core improvements we wrote a common.proj.targets file as following:</p>

<pre class="brush: xml;">
 &lt;!-- import global variables --&gt;
 &lt;Import Project=&quot;$(MSBuildThisFileDirectory)\configuration.proj&quot; /&gt;

 &lt;PropertyGroup&gt;
  &lt;BuildDependsOn&gt;CommonBeforeBuild;$(BuildDependsOn);CommonAfterBuild&lt;/BuildDependsOn&gt;
 &lt;/PropertyGroup&gt;

 &lt;Target Name=&quot;CommonBeforeBuild&quot;&gt;
  &lt;MSBuild Projects=&quot;$(CommonTargetsPath)&quot; Targets=&quot;ProcessTemplates&quot; Properties=&quot;SourceDir=$(MSBuildProjectDirectory)&quot; /&gt;
 &lt;/Target&gt;

 &lt;Target Name=&quot;CommonAfterBuild&quot;&gt;
  &lt;!--&lt;MSBuild Projects=&quot;$(CommonBuildTargetsPath)&quot; Targets=&quot;PEVerify&quot; Properties=&quot;SourceFile=$(TargetPath)&quot; /&gt;--&gt;
 &lt;/Target&gt;
&lt;/Project&gt;</pre>

<p>Now we only need to import our common.proj.targets file in projects that have template files and focus on real business problems <img src='http://www.timvw.be/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>]]></content:encoded>
			<wfw:commentRss>http://www.timvw.be/convention-over-configuration-with-msbuild/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WCF REST: generate correct Content-Length header for HEAD request</title>
		<link>http://www.timvw.be/wcf-rest-generate-correct-content-length-header-for-head-request/</link>
		<comments>http://www.timvw.be/wcf-rest-generate-correct-content-length-header-for-head-request/#comments</comments>
		<pubDate>Fri, 28 May 2010 19:50:54 +0000</pubDate>
		<dc:creator>timvw</dc:creator>
				<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://www.timvw.be/?p=1754</guid>
		<description><![CDATA[The point of a HEAD request is to return a Content-Length header, but with an empty body. The WCF transport stack has the annoying &#8216;feature&#8217; that it &#8216;corrects&#8217; the Content-Length header based on the stream that is returned. With the aid of Carlos Figueira&#8217;s MyLengthOnlyStream i was able to workaround that &#8216;feature&#8217; (I know, i [...]]]></description>
			<content:encoded><![CDATA[<p> The point of a HEAD request is to return a Content-Length header, but with an empty body. The WCF transport stack has the annoying &#8216;feature&#8217; that it &#8216;corrects&#8217; the Content-Length header based on the stream that is returned. With the aid of Carlos Figueira&#8217;s <a href="http://social.msdn.microsoft.com/Forums/en/wcf/thread/c2672206-f255-4b14-b45e-7e3d057f4ffc">MyLengthOnlyStream</a> i was able to workaround that &#8216;feature&#8217; <img src='http://www.timvw.be/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  (I know, i know, a good old HttpHandler is so much easier to implement!)</p>]]></content:encoded>
			<wfw:commentRss>http://www.timvw.be/wcf-rest-generate-correct-content-length-header-for-head-request/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Support both GET and HEAD requests on the same method with WCF REST</title>
		<link>http://www.timvw.be/support-both-get-and-head-requests-on-the-same-method-with-wcf-rest/</link>
		<comments>http://www.timvw.be/support-both-get-and-head-requests-on-the-same-method-with-wcf-rest/#comments</comments>
		<pubDate>Fri, 28 May 2010 19:33:05 +0000</pubDate>
		<dc:creator>timvw</dc:creator>
				<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://www.timvw.be/?p=1737</guid>
		<description><![CDATA[A while ago i had to modify an existing WCF REST service which was being consumed by BITS. Apparently the implementation has changed in Windows7 in such a way that the BITS client first makes a HEAD request to discover the file size. The following attempts did not work: // A method can not have [...]]]></description>
			<content:encoded><![CDATA[<p>A while ago i had to modify an existing <a href="http://msdn.microsoft.com/en-us/netframework/cc950529.aspx">WCF REST</a> service which was being consumed by <a href="http://en.wikipedia.org/wiki/Background_Intelligent_Transfer_Service">BITS</a>. Apparently the implementation has changed in Windows7 in such a way that the BITS client first makes a HEAD request to discover the file size.</p>

<p>The following attempts did not work:</p>

<pre class="brush: csharp;">// A method can not have both WebGet and WebInvoke attributes
[OperationContract]
[WebGet]
[WebInvoke(Method=&quot;HEAD&quot;)]
public Stream Download(string token) { }</pre>

<br/> 

<pre class="brush: csharp;">// A method can not have multiple WebInvoke attributes
[OperationContract]
[WebInvoke(Method=&quot;GET&quot;)]
[WebInvoke(&quot;HEAD&quot;)]
public Stream Download(string token) { }</pre>

<p>The trick is to use * as Method and handle the method related logic in your code:</p>

<pre class="brush: csharp;">[OperationContract]
[WebInvoke(Method=&quot;*&quot;)]
public Stream Download(string token) 
{
 var method = WebOperationContext.Current.IncomingRequest.Method;
 if (method == &quot;HEAD&quot;) return ProcessHead();
 if (method == &quot;GET&quot;) return ProcessGet();
 throw new ArgumentException(method + &quot; is not supported.&quot;);   
}</pre>

]]></content:encoded>
			<wfw:commentRss>http://www.timvw.be/support-both-get-and-head-requests-on-the-same-method-with-wcf-rest/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Enumerating SpecialFolders</title>
		<link>http://www.timvw.be/enumerating-specialfolders/</link>
		<comments>http://www.timvw.be/enumerating-specialfolders/#comments</comments>
		<pubDate>Sun, 02 May 2010 06:02:16 +0000</pubDate>
		<dc:creator>timvw</dc:creator>
				<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://www.timvw.be/?p=1719</guid>
		<description><![CDATA[Environment.SpecialFolder is a value-type that i always seem to forget about. Let&#8217;s try to do something about that by posting about it here foreach (var name in Enum.GetNames(typeof(Environment.SpecialFolder))) { var specialFolder = (Environment.SpecialFolder)Enum.Parse(typeof(Environment.SpecialFolder), name); Console.WriteLine(&#34;{0,25} =&#62; {1}&#34;, name, Environment.GetFolderPath(specialFolder)); } DesktopC:\Users\timvw\Desktop ProgramsC:\Users\timvw\AppData\Roaming\Microsoft\Windows\Start Menu\Programs PersonalC:\Users\timvw\Documents MyDocumentsC:\Users\timvw\Documents FavoritesC:\Users\timvw\Favorites StartupC:\Users\timvw\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup RecentC:\Users\timvw\AppData\Roaming\Microsoft\Windows\Recent SendToC:\Users\timvw\AppData\Roaming\Microsoft\Windows\SendTo StartMenuC:\Users\timvw\AppData\Roaming\Microsoft\Windows\Start Menu MyMusicC:\Users\timvw\Music DesktopDirectoryC:\Users\timvw\Desktop MyComputer [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://msdn.microsoft.com/en-us/library/system.environment.specialfolder.aspx">Environment.SpecialFolder</a> is a value-type that i always seem to forget about. Let&#8217;s try to do something about that by posting about it here <img src='http://www.timvw.be/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>

<pre class="brush: csharp;">foreach (var name in Enum.GetNames(typeof(Environment.SpecialFolder)))
{
 var specialFolder = (Environment.SpecialFolder)Enum.Parse(typeof(Environment.SpecialFolder), name);
 Console.WriteLine(&quot;{0,25} =&gt; {1}&quot;, name, Environment.GetFolderPath(specialFolder));
}</pre>

<br/>

<table>
<tr><td>Desktop</td><td>C:\Users\timvw\Desktop</td></tr>
<tr><td>Programs</td><td>C:\Users\timvw\AppData\Roaming\Microsoft\Windows\Start Menu\Programs</td></tr>
<tr><td>Personal</td><td>C:\Users\timvw\Documents</td></tr>
<tr><td>MyDocuments</td><td>C:\Users\timvw\Documents</td></tr>
<tr><td>Favorites</td><td>C:\Users\timvw\Favorites</td></tr>
<tr><td>Startup</td><td>C:\Users\timvw\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup</td></tr>
<tr><td>Recent</td><td>C:\Users\timvw\AppData\Roaming\Microsoft\Windows\Recent</td></tr>
<tr><td>SendTo</td><td>C:\Users\timvw\AppData\Roaming\Microsoft\Windows\SendTo</td></tr>
<tr><td>StartMenu</td><td>C:\Users\timvw\AppData\Roaming\Microsoft\Windows\Start Menu</td></tr>
<tr><td>MyMusic</td><td>C:\Users\timvw\Music</td></tr>
<tr><td>DesktopDirectory</td><td>C:\Users\timvw\Desktop</td></tr>
<tr><td>MyComputer</td><td></td></tr>
<tr><td>Templates</td><td>C:\Users\timvw\AppData\Roaming\Microsoft\Windows\Templates</td></tr>
<tr><td>ApplicationData</td><td>C:\Users\timvw\AppData\Roaming</td></tr>
<tr><td>LocalApplicationData</td><td>C:\Users\timvw\AppData\Local</td></tr>
<tr><td>InternetCache</td><td>C:\Users\timvw\AppData\Local\Microsoft\Windows\Temporary Internet Files</td></tr>
<tr><td>Cookies</td><td>C:\Users\timvw\AppData\Roaming\Microsoft\Windows\Cookies</td></tr>
<tr><td>History</td><td>C:\Users\timvw\AppData\Local\Microsoft\Windows\History</td></tr>
<tr><td>CommonApplicationData</td><td>C:\ProgramData</td></tr>
<tr><td>System</td><td>C:\Windows\system32</td></tr>
<tr><td>ProgramFiles</td><td>C:\Program Files</td></tr>
<tr><td>MyPictures</td><td>C:\Users\timvw\Pictures</td></tr>
<tr><td>CommonProgramFiles</td><td>C:\Program Files\Common Files</td></tr>
</table>]]></content:encoded>
			<wfw:commentRss>http://www.timvw.be/enumerating-specialfolders/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Get root directory for IsolatedStorageFiles</title>
		<link>http://www.timvw.be/get-root-directory-for-isolatedstoragefiles/</link>
		<comments>http://www.timvw.be/get-root-directory-for-isolatedstoragefiles/#comments</comments>
		<pubDate>Sat, 01 May 2010 19:07:04 +0000</pubDate>
		<dc:creator>timvw</dc:creator>
				<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://www.timvw.be/?p=1715</guid>
		<description><![CDATA[Sometimes you want to know the absolute path of a file that is persisted with IsolatedStorageFile. Apparently there is an internal property RootDirectory which contains this information: public static class IsolatedStorageFileExtensions { public static string GetRootDirectory(this IsolatedStorageFile isf) { var property = isf.GetType().GetProperty(&#34;RootDirectory&#34;, BindingFlags.Instance &#124; BindingFlags.Public &#124; BindingFlags.NonPublic &#124; BindingFlags.GetProperty); return (string)property.GetValue(isf, null); } } [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes you want to know the absolute path of a file that is persisted with <a href="http://msdn.microsoft.com/en-us/library/system.io.isolatedstorage.isolatedstoragefile(VS.95).aspx">IsolatedStorageFile</a>.  Apparently there is an internal property RootDirectory which contains this information:</p>

<pre class="brush: csharp;">public static class IsolatedStorageFileExtensions
{
 public static string GetRootDirectory(this IsolatedStorageFile isf)
 {
  var property = isf.GetType().GetProperty(&quot;RootDirectory&quot;, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetProperty);
  return (string)property.GetValue(isf, null);
 }
}</pre>

<p>Here is a real world example of using <a href="http://sharpbits.codeplex.com/">SharpBITS.NET</a> to download a file to IsolatedStorage:</p>

<pre class="brush: csharp;">class Program
{
 static void Main()
 {
  var mgr = new BitsManager();
  mgr.OnJobError += mgr_OnJobError;
  mgr.OnJobTransferred += mgr_OnJobTransferred;

  var job = mgr.CreateJob(&quot;job@&quot; + DateTime.Now, JobType.Download);
  var src = @&quot;http://localhost/&quot;;
  var dst = Path.Combine(GetIsfRoot(), &quot;test.html&quot;);
  job.AddFile(src,dst);
  job.Resume();

  Console.WriteLine(&quot;running...&quot;);
  Console.ReadKey();
 }

 static void mgr_OnJobTransferred(object sender, NotificationEventArgs e)
 {
   e.Job.Complete();
   Console.WriteLine(&quot;completed: &quot; + e.Job.DisplayName);
  }

 static void mgr_OnJobError(object sender, ErrorNotificationEventArgs e)
 {
  Console.WriteLine(&quot;error: &quot; + e.Error.Description);
 }

 static string GetIsfRoot()
 {
  using (var f = IsolatedStorageFile.GetUserStoreForAssembly())
  {
   return f.GetRootDirectory();
  }
 }
}</pre>]]></content:encoded>
			<wfw:commentRss>http://www.timvw.be/get-root-directory-for-isolatedstoragefiles/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Exploring System.Interactive</title>
		<link>http://www.timvw.be/exploring-system-interactive/</link>
		<comments>http://www.timvw.be/exploring-system-interactive/#comments</comments>
		<pubDate>Thu, 18 Feb 2010 19:09:15 +0000</pubDate>
		<dc:creator>timvw</dc:creator>
				<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://www.timvw.be/?p=1702</guid>
		<description><![CDATA[A couple of weeks ago i was working on an application that would transfer data through a couple of components as a List&#60;object&#62;. In essence, all we were doing over and over again was the following: interface IMapper&#60;TEntity&#62; { TEntity FromObjectList(List&#60;object&#62; objectList); List&#60;object&#62; ToObjectList(TEntity entity); } My initial implementation (using EnumerableEx operators from Reactive Extensions) [...]]]></description>
			<content:encoded><![CDATA[<p>A couple of weeks ago i was working on an application that would transfer data through a couple of components as a List&lt;object&gt;. In essence, all we were doing over and over again was the following:</p>

<pre class="brush: csharp;">interface IMapper&lt;TEntity&gt;
{
 TEntity FromObjectList(List&lt;object&gt; objectList);
 List&lt;object&gt; ToObjectList(TEntity entity);
}</pre>

<p>My initial implementation (using EnumerableEx operators from <a href="http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx">Reactive Extensions</a>) looked like this:</p>

<pre class="brush: csharp;">public TEntity FromObjectList(List&lt;object&gt; objectList)
{
 var entity = new TEntity();

 properties
  .Zip(objectList, (property, value) =&gt; AssignValueToProperty(entity, property, value))
  .Run();

 return entity;
}

int AssignValueToProperty(object entity, PropertyInfo property, object value)
{
 property.SetValue(entity, value, null);
 return 0;
}

public List&lt;object&gt; ToObjectList(TEntity entity)
{
 return properties
  .Select(property =&gt; property.GetValue(entity, null))
  .ToList();
 }</pre>

<p>And the consumer code looks like this:</p>

<pre class="brush: csharp;">var person = new Person {  Id = 2, Score = 1.3, Name = &quot;Tim&quot;, Title = &quot;Sir&quot; };

var personMapper = new Mapper&lt;Person&gt;()
 .Map(x =&gt; x.Id)
 .Map(x =&gt; x.Score)
 .Map(x =&gt; x.Name)
 .Map(x =&gt; x.Title);

var data = personMapper.ToObjectList(person);
var clonedPerson = personMapper.FromObjectList(data);</pre>

<p>Wait a minute, in most situations we simply want to map all properties on the object. Let&#8217;s create a mapper for this:</p>

<pre class="brush: csharp;">class AutoMapper&lt;TEntity&gt; : Mapper&lt;TEntity&gt; where TEntity : new()
{
 public AutoMapper()
 {
  typeof(TEntity).GetProperties().Run(property =&gt; Map(property));
 }
}</pre>

<p>And now we don&#8217;t have to waste time doing the same thing over and over again! Because we always need to map all properties of our types we ended up with the following:</p>

<pre class="brush: csharp;">public static class Mapper
{
 public static List&lt;Object&gt; ToObjectsList&lt;TEntity&gt;(this TEntity entity)
 {
  return entity.GetType().GetProperties()
   .Select(property =&gt; property.GetValue(entity, null))
   .ToList();
  }

 public static TEntity ToEntity&lt;TEntity&gt;(this List&lt;Object&gt; objectsList) where TEntity : new()
 {
  TEntity entity = new TEntity();
  entity.GetType().GetProperties()
   .Zip(objectsList, (property, value) =&gt;{ property.SetValue(entity, value,null); return 0;})
   .Run();
  return entity;
 }
}</pre>]]></content:encoded>
			<wfw:commentRss>http://www.timvw.be/exploring-system-interactive/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
