<?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>hardcodet.net</title>
	<atom:link href="http://www.hardcodet.net/feed" rel="self" type="application/rss+xml" />
	<link>http://www.hardcodet.net</link>
	<description>Confessions of a Code Addict</description>
	<lastBuildDate>Sat, 02 Apr 2016 07:07:16 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.9.13</generator>
	<item>
		<title>WPF NotifyIcon 1.0.8 released</title>
		<link>http://www.hardcodet.net/2016/04/wpf-notifyicon-1-0-8-released</link>
					<comments>http://www.hardcodet.net/2016/04/wpf-notifyicon-1-0-8-released#comments</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Fri, 01 Apr 2016 18:09:13 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/?p=941</guid>

					<description><![CDATA[I just published a maintenance release of my WPF NotifyIcon control. The update fixes an issue with potential null references during initialization. Links and downloads as usual on the control&#8217;s project page. Happy coding!]]></description>
										<content:encoded><![CDATA[<p>I just published a maintenance release of my WPF NotifyIcon control. The update fixes an issue with potential null references during initialization.</p>
<p>Links and downloads as usual on the control&#8217;s <a title="Go to project page" href="http://www.hardcodet.net/wpf-notifyicon">project page</a>. Happy coding!</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2016/04/wpf-notifyicon-1-0-8-released/feed</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>WPF NotifyIcon 1.0.6 released</title>
		<link>http://www.hardcodet.net/2016/03/wpf-notifyicon-1-0-6-released</link>
					<comments>http://www.hardcodet.net/2016/03/wpf-notifyicon-1-0-6-released#comments</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Mon, 21 Mar 2016 09:34:22 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/?p=937</guid>

					<description><![CDATA[I just published a maintenance release of my NotifyIcon control, which addresses a potential null reference issue, and optionally removes the double-click delay, which allows the NotifyIcon to react to single clicks immediately. Links and downloads as usual on the control&#8217;s project page. Happy coding!]]></description>
										<content:encoded><![CDATA[<p>I just published a maintenance release of my NotifyIcon control, which addresses a potential null reference issue, and optionally removes the double-click delay, which allows the NotifyIcon to react to single clicks immediately.</p>
<p>Links and downloads as usual on the control&#8217;s <a title="Go to project page" href="http://www.hardcodet.net/wpf-notifyicon">project page</a>. Happy coding!</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2016/03/wpf-notifyicon-1-0-6-released/feed</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>We&#8217;re hiring: WPF UI Developer (Swiss Office)</title>
		<link>http://www.hardcodet.net/2014/03/ui-developer-spring-2014</link>
					<comments>http://www.hardcodet.net/2014/03/ui-developer-spring-2014#respond</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Wed, 12 Mar 2014 10:56:51 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/?p=914</guid>

					<description><![CDATA[XAML UI designer / developer? We&#8217;re hiring! My work at Vistaprint is focused on the UI architecture of the distributed software system that runs in our factories. Today, we process more than 120,000 individually customized pieces in over 70,000 shipments per day, with diverse human-machine interaction taking place while produced items are making their way [&#8230;]]]></description>
										<content:encoded><![CDATA[<h3>XAML UI designer / developer? We&#8217;re hiring!</h3>
<p><img loading="lazy" class="alignright size-full wp-image-835" title="vistaprintlogo" alt="vistaprintlogo" src="http://blog.hardcodet.net/wp-content/uploads/2012/09/vistaprintlogo.png" width="195" height="79" /></p>
<p>My work at Vistaprint is focused on the UI architecture of the distributed software system that runs in our factories. Today, we process more than 120,000 individually customized pieces in over 70,000 shipments per day, with diverse human-machine interaction taking place while produced items are making their way through the plant. This includes desktops, touch panels, handhelds, or dashboards. <strong>And we are currently trying to rethink the way our UIs should work &#8211; which is where YOU come in: </strong>A brilliant UI designer, XAML wizard, UX geek, who wants to make a difference and join us in implementing an exciting, cutting edge UI infrastructure that will support both our stakeholders on the factory floor as your fellow developers all around the globe. Recognize yourself? Come join us in our beautiful, and slightly chaotic <a title="Winterthur" href="http://careers.vistaprint.com/winterthur" target="_blank">Winterthur </a>office in Switzerland!</p>
<p><a href="http://www.hardcodet.net/wp-content/uploads/2014/03/WtrOffice.png"><img loading="lazy" class="alignnone size-medium wp-image-921" alt="WtrOffice" src="http://www.hardcodet.net/wp-content/uploads/2014/03/WtrOffice-300x169.png" width="300" height="169" srcset="http://www.hardcodet.net/wp-content/uploads/2014/03/WtrOffice-300x169.png 300w, http://www.hardcodet.net/wp-content/uploads/2014/03/WtrOffice-1024x577.png 1024w, http://www.hardcodet.net/wp-content/uploads/2014/03/WtrOffice.png 1306w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>Job details here:<br />
<a href="http://careers.vistaprint.com/winterthur/technology/lead-software-engineer%2c-ui-development/10869" target="_self">http://careers.vistaprint.com/winterthur/technology/lead-software-engineer%2c-ui-development/10869<br />
</a></p>
<p>Take the wording on the posting with a grain of salt. We really are looking for a Blend wizard more than a Visual Studio crack. This is all about creating exciting user interfaces, and evangelizing / teaching UI goodness to a globally distributed team.</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2014/03/ui-developer-spring-2014/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>WPF NotifyIcon 1.0.5 Released</title>
		<link>http://www.hardcodet.net/2013/11/wpf-notifyicon-1-0-5-released</link>
					<comments>http://www.hardcodet.net/2013/11/wpf-notifyicon-1-0-5-released#comments</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Mon, 25 Nov 2013 12:52:37 +0000</pubDate>
				<category><![CDATA[WPF NotifyIcon]]></category>
		<category><![CDATA[Controls]]></category>
		<category><![CDATA[NotifyIcon]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[WPF]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/?p=893</guid>

					<description><![CDATA[I just published a maintenance release of my NotifyIcon control, which addresses a few (long due) issues, most notably for applications that target more recent versions of the .NET framework, or x64 applications. Source code and samples can be downloaded via the control&#8217;s project page. Alternatively, there&#8217;s now also an official NuGet package for the [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I just published a maintenance release of my NotifyIcon control, which addresses a few (long due) issues, most notably for applications that target more recent versions of the .NET framework, or x64 applications.</p>
<p>Source code and samples can be downloaded via the control&#8217;s <a title="Go to project page" href="http://www.hardcodet.net/wpf-notifyicon">project page</a>. Alternatively, there&#8217;s now also an <a title="NuGet package home" href="https://www.nuget.org/packages/Hardcodet.NotifyIcon.Wpf/">official NuGet package </a>for the control (binaries only) that contains builds for .NET 3.5 up to 4.5.1.</p>
<p><img loading="lazy" class="alignnone" alt="" src="http://www.hardcodet.net/uploads/2009/04/image13.png" width="297" height="94" /></p>
<h3>What&#8217;s next?</h3>
<p>I already started working on a new version of the control. The most important feature will be interactive tooltips (so you can hover over them and interact with clickable content), along with a few minor new features. Check back in a few days/weeks, or <a title="@phsumi" href="http://twitter.com/phsumi">follow me </a>on Twitter in order to get the update once it&#8217;s released. Also, if you have specific feature requests, let me know!</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2013/11/wpf-notifyicon-1-0-5-released/feed</wfw:commentRss>
			<slash:comments>12</slash:comments>
		
		
			</item>
		<item>
		<title>Updated ToolTips Library</title>
		<link>http://www.hardcodet.net/2013/11/updated-tooltips-library</link>
					<comments>http://www.hardcodet.net/2013/11/updated-tooltips-library#comments</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Thu, 21 Nov 2013 23:16:32 +0000</pubDate>
				<category><![CDATA[WPF Controls]]></category>
		<category><![CDATA[ToolTips]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/?p=870</guid>

					<description><![CDATA[I just uploaded an updated version of the clickable ToolTips library I released this month. The changes add string formatting for bindings, plus the option to disable ToolTips via a the bindable boolean IsEnabled flag. You can download the current version 1.0.1 here. &#160;]]></description>
										<content:encoded><![CDATA[<p>I just uploaded an updated version of the <a title="Quick and dirty (but nice!) ToolTips – revisited and interactive" href="http://www.hardcodet.net/2013/11/quick-and-dirty-but-nice-tooltips-revisited-and-interactive">clickable ToolTips library </a>I released this month. The changes add string formatting for bindings, plus the option to disable ToolTips via a the bindable boolean IsEnabled flag. You can download the current version 1.0.1 <a href="/uploads/projects/tooltips/Hardcodet.ToolTips.zip">here</a>.</p>
<p>&nbsp;</p>
<p><img alt="" src="data:image/png;base64,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" /></p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2013/11/updated-tooltips-library/feed</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Quick and dirty (but nice!) ToolTips &#8211; revisited and interactive</title>
		<link>http://www.hardcodet.net/2013/11/quick-and-dirty-but-nice-tooltips-revisited-and-interactive</link>
					<comments>http://www.hardcodet.net/2013/11/quick-and-dirty-but-nice-tooltips-revisited-and-interactive#comments</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Tue, 12 Nov 2013 16:15:11 +0000</pubDate>
				<category><![CDATA[CodeProject]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[WPF]]></category>
		<category><![CDATA[Blend]]></category>
		<category><![CDATA[ToolTips]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/?p=837</guid>

					<description><![CDATA[&#160; Download sources, binaries, and sample application (Version: 1.0.1, 2013.11.22) &#160; A few years ago, I posted an article that leveraged markup extensions to quickly show localized ToolTips with minimal effort. Fast forward to 2013: I still like ToolTips, but interactive / clickable ones would be nice, and there&#8217;s Blend Behaviors that provides developers with [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>&nbsp;</p>
<p><a class="download" title="Download Hardcodet.ToolTips" href="/uploads/projects/tooltips/Hardcodet.ToolTips.zip">Download sources, binaries, and sample application</a> <span style="font-size: xx-small;">(Version: 1.0.1, 2013.11.22)</span></p>
<p>&nbsp;</p>
<p>A few years ago, I posted <a href="http://www.hardcodet.net/2009/04/wpf-tooltips-through-markup-extension">an article </a>that leveraged markup extensions to quickly show localized ToolTips with minimal effort. Fast forward to 2013: I still like ToolTips, but interactive / clickable ones would be nice, and there&#8217;s Blend Behaviors that provides developers with a great design-time experience. As a result, I wrote a simple control and a complementary Blend Behavior that get&#8217;s me quite a bit of flexibility with minimal impementation effort.</p>
<p>The behavior allows you very easily create simple ToolTips like this:</p>
<p><img loading="lazy" class="alignnone size-full wp-image-840" alt="A simple ToolTip" src="http://www.hardcodet.net/wp-content/uploads/2013/11/SimpleToolTip.png" width="188" height="112" /></p>
<p>&nbsp;</p>
<p>However, it doesn&#8217;t stop there. The following Blend Behavior generates an error ToolTip:</p>
<p><a href="http://www.hardcodet.net/wp-content/uploads/2013/11/ToolTipBehavior_Properties.png"><img loading="lazy" class="alignnone size-medium wp-image-849" alt="Behavior properties in Expression Blend" src="http://www.hardcodet.net/wp-content/uploads/2013/11/ToolTipBehavior_Properties-300x233.png" width="300" height="233" srcset="http://www.hardcodet.net/wp-content/uploads/2013/11/ToolTipBehavior_Properties-300x233.png 300w, http://www.hardcodet.net/wp-content/uploads/2013/11/ToolTipBehavior_Properties.png 380w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>&nbsp;</p>
<p><img loading="lazy" class="alignnone size-full wp-image-842" alt="ErrorToolTip" src="http://www.hardcodet.net/wp-content/uploads/2013/11/ErrorToolTip.png" width="282" height="121" /></p>
<p>&nbsp;</p>
<p>Also, unlike the built-in ToolTip service, the behavior supports interactive/clickable ToolTips. As the ToolTip takes arbitary XAML or a user control for Content or Header properties, you can display arbitrary controls on the popup.</p>
<p><img loading="lazy" class="alignnone size-full wp-image-845" alt="InteractiveToolTip" src="http://www.hardcodet.net/wp-content/uploads/2013/11/InteractiveToolTip.png" width="270" height="139" /></p>
<p>&nbsp;</p>
<p>Features at a glance:</p>
<ul>
<li>Blend Behavior with design-time support &#8211; you can setup rich ToolTips within Blend in a matter of seconds.</li>
<li>Unlike regular ToolTips, those are clickable &#8211; you can put interactive content such as buttons or Hyperlinks on them.</li>
<li>Built-in header / content support.</li>
<li>Data Binding and MVVM-friendly.</li>
<li>Content and header not limited to text.</li>
<li>Built-in themes: You can show a ToolTip as an information, warning, or error.</li>
<li>If bound to strings, values can be formatted on the fly using the <em>HeaderStringFormat</em> and <em>ContentStringFormat</em> properties.</li>
<li>Disabling ToolTips through a bindable <em>IsEnabled</em> flag.</li>
</ul>
<p>&nbsp;</p>
<p>Some final notes: I didn&#8217;t make everything configurable &#8211; that would have been overkill for the scope of a ToolTip. Instead, I recommend you to tweak the control styles to your needs. Things you might want to change:</p>
<ul>
<li>When being displayed, ToolTips are slightly transparent &#8211; full opacity is only set if you hover over them. You can easily adjust this in the animation that fades in the control.</li>
<li>If you shorten the delay in which the ToolTip is being displayed remarkably, you should also adjust animations (fade-in / fade-out in order to not cut them off.</li>
<li>Placement of the ToolTip&#8217;s popup (near Mouse pointer) is currently hardcoded in the Behavior class.</li>
</ul>
<p>Happy coding <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2013/11/quick-and-dirty-but-nice-tooltips-revisited-and-interactive/feed</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>Understanding the &#8220;yield&#8221; keyword in 120 Seconds</title>
		<link>http://www.hardcodet.net/2011/04/understanding-yield-in-120-seconds</link>
					<comments>http://www.hardcodet.net/2011/04/understanding-yield-in-120-seconds#respond</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Sun, 17 Apr 2011 10:11:51 +0000</pubDate>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Activities]]></category>
		<category><![CDATA[Yield]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/?p=828</guid>

					<description><![CDATA[I’m about to release my own take on coroutines, and as a complementary app, I created a very simple sample that lets developers (hopefully) experience the fundamental behavioral difference of returning a sequence of values through the yield keyword. There’s a lot of great material that can be read about iterator blocks (Google is your [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I’m about to release my own take on coroutines, and as a complementary app, I created a very simple sample that lets developers (hopefully) experience the fundamental behavioral difference of returning a sequence of values through the yield keyword.</p>
<p>There’s a lot of great material that can be read about iterator blocks (Google is your friend), and I’m not planning to add another article on top of that. So, stop reading and:</p>
<ul>
<li>Download the sample (VS2010). </li>
<li>Quickly glance at the few lines in the code-behind of the window. </li>
<li>Run the app. </li>
<li>Bow in front of the power of iterators <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> </li>
</ul>
<p><img loading="lazy" 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://blog.hardcodet.net/wp-content/uploads/2011/04/image.png" width="404" height="337" /></p>
<p>&#160;</p>
<p><a class="download" href="/uploads/2011/04/hello_yield.zip">Download Sample Application</a></p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2011/04/understanding-yield-in-120-seconds/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>A Parser for Formatted Text in WPF / Silverlight</title>
		<link>http://www.hardcodet.net/2010/11/parser-for-formatted-text-in-wpf-and-silverlight</link>
					<comments>http://www.hardcodet.net/2010/11/parser-for-formatted-text-in-wpf-and-silverlight#comments</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Fri, 05 Nov 2010 20:46:17 +0000</pubDate>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Sketchables]]></category>
		<category><![CDATA[WPF]]></category>
		<category><![CDATA[Open Source]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/2010/11/parser-for-formatted-text-in-wpf-and-silverlight</guid>

					<description><![CDATA[I finally got round to implement on-the-fly text formatting for Sketchables, which will&#160; allow you to define text formatting while typing (similar to wikis or forum posts). Sketchables will parse such strings and format them on the fly for you: the star renders *bold* text I didn’t rely on regular expressions here, but wrote a [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I finally got round to implement on-the-fly text formatting for Sketchables, which will&#160; allow you to define text formatting while typing (similar to wikis or forum posts). Sketchables will parse such strings and format them on the fly for you:</p>
<p><font face="Courier New">the star renders *bold* text</font></p>
<p>I didn’t rely on regular expressions here, but wrote a simple forwarding parser to process markup text. As it makes a pretty neat tool, I extracted it into a little sample app that shows a possible use for it. The presented implementation just creates nested text blocks, but you should be able to easily adjust it to your needs.</p>
<p>&#160;</p>
<p><img loading="lazy" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2010/11/image.png" width="540" height="297" /></p>
<p><font size="1"></font></p>
<p><font size="1"><strong>Latest Update:&#160; 2010.11.07 – Fixed issue with single character chunks.</strong></font></p>
<p><font size="1"></font></p>
<p><font size="1"></font></p>
<p><a class="download" href="/uploads/2010/11/FormatParser.zip">Download Sample Application</a></p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2010/11/parser-for-formatted-text-in-wpf-and-silverlight/feed</wfw:commentRss>
			<slash:comments>10</slash:comments>
		
		
			</item>
		<item>
		<title>Back in Switzerland</title>
		<link>http://www.hardcodet.net/2010/09/back-in-switzerland-sept-2010</link>
					<comments>http://www.hardcodet.net/2010/09/back-in-switzerland-sept-2010#comments</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Fri, 03 Sep 2010 08:24:35 +0000</pubDate>
				<category><![CDATA[Personal]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/2010/09/back-in-switzerland-sept-2010</guid>

					<description><![CDATA[The blog (and myself) has been dormant a while &#8211; I’ve been literally working my *** off (doing over 600 hours in just two months isn’t too healthy) and have rewarded myself by travelling the US for three weeks. However, I’m back in Switzerland now and will try to reply to pending posts and questions [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>The blog (and myself) has been dormant a while &#8211; I’ve been literally working my *** off (doing over 600 hours in just two months isn’t too healthy) and have rewarded myself by travelling the US for three weeks. However, I’m back in Switzerland now and will try to reply to pending posts and questions asap (read: once I get rid of my current sleep deprivation), along with an update on Sketchables.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2010/09/back-in-switzerland-sept-2010/feed</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Sketchables 0.9 – Public Preview Release</title>
		<link>http://www.hardcodet.net/2010/07/public-sketchables-preview-release</link>
					<comments>http://www.hardcodet.net/2010/07/public-sketchables-preview-release#comments</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Tue, 20 Jul 2010 21:28:01 +0000</pubDate>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Sketchables]]></category>
		<category><![CDATA[WPF]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/2010/07/public-sketchables-preview-release</guid>

					<description><![CDATA[I wanted to officially release Sketchables weeks ago, but business just got in the way – and it turned out that my plan to just working at night / on weekends didn’t work either because, well, business got in the way there, too. However, my deadline ends in little more than a week (and I’ll [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I wanted to officially release Sketchables weeks ago, but business just got in the way – and it turned out that my plan to just working at night / on weekends didn’t work either because, well, business got in the way there, too.</p>
<p>However, my deadline ends in little more than a week (and I’ll have quite some time at my hands in August), so I’ll be able to finally package Sketchables, record some more videos, and of course add a few goodies. For now, I’ve prepared a preview release of the package which already works quite solid:</p>
<p>&#160;</p>
<p><a class="download" href="http://cid-af1d05bafed3356a.office.live.com/self.aspx/Public/Sketchables/sketchables.preview.zip">Sketchables Preview</a></p>
<p>&#160;</p>
<p>If you compare this package to the contents in the <a href="http://www.youtube.com/watch?v=JmXkqRR9kes">YouTube video</a>, the most prominent addition is <strong>built-in navigation support</strong> which gives you point-and-click navigation, and allows you to trigger other actions for a Sketchable&#8217;s items:</p>
<p><font size="1">(Click on screenshot to show in full size)</font></p>
<p><a href="http://blog.hardcodet.net/wp-content/uploads/2010/07/image.png"><img loading="lazy" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2010/07/image-thumb.png" width="404" height="138" /></a> </p>
<p>&#160;</p>
<p>As always, critical feedback is appreciated – happy sketching! <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2010/07/public-sketchables-preview-release/feed</wfw:commentRss>
			<slash:comments>33</slash:comments>
		
		
			</item>
		<item>
		<title>Announcing Sketchables – Rapid Mockup Creation with SketchFlow</title>
		<link>http://www.hardcodet.net/2010/05/announcing-sketchables</link>
					<comments>http://www.hardcodet.net/2010/05/announcing-sketchables#comments</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Mon, 24 May 2010 17:48:08 +0000</pubDate>
				<category><![CDATA[Sketchables]]></category>
		<category><![CDATA[Blend]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[SketchFlow]]></category>
		<category><![CDATA[WPF]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/2010/05/announcing-sketchables</guid>

					<description><![CDATA[SketchFlow is a great addition to Blend, but I was missing the ability to create quick mockups of user interfaces. I’m a huge fan of productivity tools such as Balsamiq, and I was sorely missing its ease and speed in SketchFlow. Meet Sketchables. Sketchables is a simple framework complemented by a set of controls that [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><a href="http://electricbeach.org/?p=664">SketchFlow</a> is a great addition to Blend, but I was missing the ability to create quick mockups of user interfaces. I’m a huge fan of productivity tools such as <a href="http://www.balsamiq.com/">Balsamiq</a>, and I was sorely missing its ease and speed in SketchFlow.</p>
<p>Meet Sketchables. Sketchables is a simple framework complemented by a set of controls that allow you to quickly create common controls in a matter of seconds. Here’s a screenshot from one of the samples, which was created in just a few minutes:</p>
<p><a href="http://blog.hardcodet.net/wp-content/uploads/2010/05/image.png"><img loading="lazy" style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2010/05/image-thumb.png" width="570" height="339" /></a> </p>
<p>&#160;</p>
<p>…and here’s a complementary recording that shows how the above mockup was created:</p>
<p>&#160;</p>
<div style="padding-bottom: 0px; margin: 0px auto; padding-left: 0px; width: 425px; padding-right: 0px; display: block; float: none; padding-top: 0px" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:ad824a18-021a-42d1-9b0b-2aeaf129fe04" class="wlWriterSmartContent"><embed height="355" type="application/x-shockwave-flash" width="425" src="http://www.youtube.com/v/JmXkqRR9kes" wmode="transparent" /></div>
<p>&#160;</p>
<p>&#160;</p>
<p>Sketchables will be free software, requires Blend 4 RTM and fully supports both WPF and Silverlight SketchFlow projects. Version 1.0 is approaching completion, so I hope I’ll be able to release it as soon as Blend 4 goes live.</p>
<p>Still time for you to slip in some last-minute feature requests though <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2010/05/announcing-sketchables/feed</wfw:commentRss>
			<slash:comments>34</slash:comments>
		
		
			</item>
		<item>
		<title>An Abstraction Layer for Temporary Data in .NET and Silverlight</title>
		<link>http://www.hardcodet.net/2010/04/temp-files-in-net-and-silverlight</link>
					<comments>http://www.hardcodet.net/2010/04/temp-files-in-net-and-silverlight#comments</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Thu, 15 Apr 2010 09:22:29 +0000</pubDate>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Temp Files]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/2010/04/temp-files-in-net-and-silverlight</guid>

					<description><![CDATA[Up until now, I’ve dealt with temporary data in my .NET applications using local files and FileInfo instances.&#160; This worked just fine – until I needed a solution that works under both .NET and Silverlight. The problem: In Silverlight, you can’t just create a temporary file on the file system for security reasons. Instead, there’s [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Up until now, I’ve dealt with temporary data in my .NET applications using local files and <span class="code">FileInfo </span>instances.&#160; This worked just fine – until I needed a solution that works under both .NET and Silverlight.</p>
<p>The problem: In Silverlight, you can’t just create a temporary file on the file system for security reasons. Instead, there’s the concept of <a href="http://msdn.microsoft.com/en-us/library/bdts8hk0%28v=VS.95%29.aspx">isolated storage</a> that provides you with the means to store data in files and directories. The API is very similar to working with the local file system, but it doesn’t use the <span class="code">FileInfo </span>class. As a result, I needed to get rid of the (proprietary) concept of <span class="code">FileInfo </span>in my temporary file handling and came up with a simple yet generic solution.</p>
<p>&#160;</p>
<p><a class="download" title="Download sample project" href="/uploads/projects/various/hardcodet.tempstorage.zip">Download Sample Project</a></p>
<p>&#160;</p>
<p>Here’s a sample usage of the API. This code transparently creates temporary storage, and works in both .NET and Silverlight:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> Foo(ITempStreamFactory factory)
{
  <span style="color: #0000ff">using</span> (Stream stream = factory.CreateTempStream())
  {
    <span style="color: #008000">//write to the stream, read from it</span>
  }

  <span style="color: #008000">//once we get outside the &quot;using&quot; block, temporary data has been discarded</span>
}</pre>
</div>
<p>&#160;</p>
<p>The snippet above relies on a factory of type <span class="code">ITempStreamFactory </span>that returns a simple <span class="code">Stream </span>instance. I do not need to know anything about this returned stream – it’s the factory’s responsibility to return a <span class="code">Stream </span>instance that will clean up after itself once it is being disposed.</p>
<p><span id="more-803"></span></p>
<p>In the snippet above, disposal happens implicitly through the using statement. But of course, the stream can also be disposed explicitly:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">private</span> Stream tempStream;

<span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> CreateAndWrite(ITempStreamFactory factory)
{
  <span style="color: #008000">//get stream</span>
  tempStream = factory.CreateTempStream();

  <span style="color: #008000">//write to the stream</span>
  ...
}

<span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> ReadAndDispose()
{
  <span style="color: #008000">//read data</span>
  ...

  <span style="color: #008000">//close the temp stream, which removes the file from isolated storage</span>
  tempStream.Dispose();
}</pre>
</div>
<p>&#160;</p>
<h2>Factories</h2>
<p>&#160;</p>
<p>Factory implementations are very simple – they just need to create a <span class="code">Stream </span>class that can be used. Here’s the interface:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">/// &lt;summary&gt;</span>
<span style="color: #008000">/// Responsible for the creation of stream instances</span>
<span style="color: #008000">/// which can be used to read and write temporary data.</span>
<span style="color: #008000">/// &lt;/summary&gt;</span>
<span style="color: #0000ff">public</span> <span style="color: #0000ff">interface</span> ITempStreamFactory
{
  <span style="color: #008000">/// &lt;summary&gt;</span>
  <span style="color: #008000">/// Creates a stream that automatically cleans up after itself.</span>
  <span style="color: #008000">/// &lt;/summary&gt;</span>
  Stream CreateTempStream();
}</pre>
</div>
<p>&#160;</p>
<p>&#160;</p>
<h2>TempStream Base Class</h2>
</p>
<p>So basically, the convention is that <span class="code">ITempStreamFactory</span> returns streams that clean up after themselves. In order simplify the implementation of such streams, I created an abstract base class called <span class="code">TempStream</span>. <span class="code">TempStream </span>itself derives from <span class="code">Stream</span>, and applies the <a title="Decorate Pattern (GoF)" href="http://en.wikipedia.org/wiki/Decorator_pattern">Decorator</a> pattern. All stream-related methods just forward requests to an underlying (decorated) stream. As an example, here’s the implementation of the <span class="code">Write </span>method:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> Write(<span style="color: #0000ff">byte</span>[] buffer, <span style="color: #0000ff">int</span> offset, <span style="color: #0000ff">int</span> count)
{
  <span style="color: #008000">//everything is just forwarded to an underlying (decorated) stream</span>
  DecoratedStream.Write(buffer, offset, count);
}</pre>
</div>
<p>&#160;</p>
<p>However, besides just forwarding request to a decorated stream, the <span class="code">TempStream </span>class provides two abstract methods that need to be implemented by deriving classes:</p>
<ul>
<li>The <span class="code">CreateTempDataStream </span>method is invoked in order to create that decorated stream. </li>
<li>The <span class="code">DiscardTempResources </span>method is invoked during disposal. When invoked, implementing classes should clean up (e.g. delete temp files). </li>
</ul>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">/// &lt;summary&gt;</span>
<span style="color: #008000">/// Creates the underlying stream. This method is being invoked on the first</span>
<span style="color: #008000">/// request of the &lt;see cref=&quot;DecoratedStream&quot;/&gt; property.</span>
<span style="color: #008000">/// &lt;/summary&gt;</span>
<span style="color: #008000">/// &lt;returns&gt;A temporary stream that supports seeking.&lt;/returns&gt;</span>
<span style="color: #0000ff">protected</span> <span style="color: #0000ff">abstract</span> Stream CreateTempDataStream();


<span style="color: #008000">/// &lt;summary&gt;</span>
<span style="color: #008000">/// When invoked (which happens during disposal), implementing classes</span>
<span style="color: #008000">/// should clean up temporary resources. Note that at the time this</span>
<span style="color: #008000">/// method is being invoked, the &lt;see cref=&quot;DecoratedStream&quot;/&gt; has</span>
<span style="color: #008000">/// already been disposed.</span>
<span style="color: #008000">/// &lt;/summary&gt;</span>
<span style="color: #0000ff">protected</span> <span style="color: #0000ff">abstract</span> <span style="color: #0000ff">void</span> DiscardTempResources();</pre>
</div>
<p>&#160;</p>
<p>&#160;</p>
<h2>Implementations for Local Files / Isolated Storage</h2>
<p>&#160;</p>
<h3>Local File System</h3>
<p>In order to handle temporary files on the local file system, I implemented the <span class="code">TempFileStream </span>class that takes a reference to a temporary file. The <span class="code">CreateTempDataStream </span>method opens a stream to that file, and the <span class="code">DiscardTempResources </span>deletes the file once it’s no longer required.</p>
<p>This is a simplistic implementation for the sample – the one I’ll be using in production code also deals with a temporary root directory and so forth. But the concept is the same.</p>
<p>&#160;</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> TempFileStream : TempStream
{
  <span style="color: #008000">// The maintained temporary file.</span>
  <span style="color: #0000ff">public</span> FileInfo TempFile { get; <span style="color: #0000ff">private</span> set; }


  <span style="color: #0000ff">public</span> TempFileStream(FileInfo tempFile)
  {
    Ensure.ArgumentNotNull(tempFile, <span style="color: #006080">&quot;tempFile&quot;</span>);
    TempFile = tempFile;
  }


  <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> Stream CreateTempDataStream()
  {
    <span style="color: #008000">//open stream to the local file</span>
    <span style="color: #0000ff">return</span> TempFile.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite,<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; FileShare.ReadWrite | FileShare.Delete);
  }


  <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> DiscardTempResources()
  {
    <span style="color: #008000">//delete temp file</span>
    TempFile.Refresh();
    <span style="color: #0000ff">if</span> (TempFile.Exists) TempFile.Delete();
  }
}</pre>
</div>
<p>&#160;</p>
<p><span class="code">TempFileStream </span>instances can be acquired via the <span class="code">TempFileStreamFactory</span>, which implements the <span class="code">ITempStreamFactory </span>interface. Here’s a simplistic implementation (the one in the attached project is a little smarter):</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">/// &lt;summary&gt;</span>
<span style="color: #008000">/// A factory implementation that returns</span>
<span style="color: #008000">/// &lt;see cref=&quot;TempFileStream&quot;/&gt; instances which</span>
<span style="color: #008000">/// use local temporary files.</span>
<span style="color: #008000">/// &lt;/summary&gt;</span>
<span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> TempFileStreamFactory : ITempStreamFactory
{
  <span style="color: #0000ff">public</span> Stream CreateTempStream()
  {
    FileInfo fi = <span style="color: #0000ff">new</span> FileInfo(Path.GetTempFileName());
    <span style="color: #0000ff">return</span> <span style="color: #0000ff">new</span> TempFileStream(fi);
  }
}</pre>
</div>
<p>&#160;</p>
<p>&#160;</p>
<h3>Silverlight / Isolated Storage</h3>
<p>In order to handle temporary files in the Silverlight sample, I implemented the <span class="code">IsolatedStorageTempStream </span>class that creates and deletes a temporary file in isolated storage. The <span class="code">CreateTempDataStream </span>method creates the stream using a GUID as a temporary name, and the <span class="code">DiscardTempResources </span>override removes the data from isolated storage once it’s no longer required.</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">/// &lt;summary&gt;</span>
<span style="color: #008000">/// Provides temporary file management for Silverlight</span>
<span style="color: #008000">/// applications based on isolated storage.</span>
<span style="color: #008000">/// &lt;/summary&gt;</span>
<span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> IsolatedStorageTempStream : TempStream
{
  <span style="color: #008000">/// &lt;summary&gt;</span>
  <span style="color: #008000">/// The name of the tempoarary file that is being created</span>
  <span style="color: #008000">/// in isolated storage.</span>
  <span style="color: #008000">/// &lt;/summary&gt;</span>
  <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> TempFileName { get; <span style="color: #0000ff">private</span> set; }

     

  <span style="color: #0000ff">public</span> IsolatedStorageTempStream()
  {
    <span style="color: #008000">//use a GUID as the temporary file name</span>
    TempFileName = String.Format(<span style="color: #006080">&quot;{0}.tmp&quot;</span>, Guid.NewGuid());
  }


  <span style="color: #008000">/// &lt;summary&gt;</span>
  <span style="color: #008000">/// Creates the underlying stream. This method is being invoked on the first</span>
  <span style="color: #008000">/// request of the &lt;see cref=&quot;TempStream.DecoratedStream&quot;/&gt; property.</span>
  <span style="color: #008000">/// &lt;/summary&gt;</span>
  <span style="color: #008000">/// &lt;returns&gt;A temporary stream that supports seeking.&lt;/returns&gt;</span>
  <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> Stream CreateTempDataStream()
  {
    IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication();
    <span style="color: #0000ff">return</span> store.CreateFile(TempFileName);
  }


  <span style="color: #008000">/// &lt;summary&gt;</span>
  <span style="color: #008000">/// When invoked (which happens during disposal), implementing classes</span>
  <span style="color: #008000">/// should clean up temporary resources. Note that at the time this</span>
  <span style="color: #008000">/// method is being invoked, the &lt;see cref=&quot;TempStream.DecoratedStream&quot;/&gt; has</span>
  <span style="color: #008000">/// already been disposed.</span>
  <span style="color: #008000">/// &lt;/summary&gt;</span>
  <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> DiscardTempResources()
  {
    IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication();
    store.DeleteFile(TempFileName);
  }
}</pre>
</div>
<p>&#160;</p>
<p>In the sample, <span class="code">IsolatedStorageTempStream </span>instances are being acquired via the <span class="code">TempStreamFactory</span>, which implements the <span class="code">ITempStreamFactory </span>interface. The implementation is trivial:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">/// &lt;summary&gt;</span>
<span style="color: #008000">/// Factory that creates temporary streams in the Silverlight</span>
<span style="color: #008000">/// sample.</span>
<span style="color: #008000">/// &lt;/summary&gt;</span>
<span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> TempStreamFactory : ITempStreamFactory
{
  <span style="color: #008000">/// &lt;summary&gt;</span>
  <span style="color: #008000">/// Gets a &lt;see cref=&quot;Stream&quot;/&gt; that automatically cleans up</span>
  <span style="color: #008000">/// after itself.</span>
  <span style="color: #008000">/// &lt;/summary&gt;</span>
  <span style="color: #008000">/// &lt;returns&gt;A stream that allows to write and read temporary</span>
  <span style="color: #008000">/// data.&lt;/returns&gt;</span>
  <span style="color: #0000ff">public</span> Stream CreateTempStream()
  {
    <span style="color: #0000ff">return</span> <span style="color: #0000ff">new</span> IsolatedStorageTempStream();
  }
}</pre>
</div>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2010/04/temp-files-in-net-and-silverlight/feed</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>A Custom Text Encoding Generator For Silverlight</title>
		<link>http://www.hardcodet.net/2010/03/silverlight-text-encoding-class-generator</link>
					<comments>http://www.hardcodet.net/2010/03/silverlight-text-encoding-class-generator#comments</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Tue, 30 Mar 2010 22:29:00 +0000</pubDate>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Encoding]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/2010/03/silverlight-text-encoding-class-generator</guid>

					<description><![CDATA[A tool that creates custom text encoding classes which can be used in Silverlight projects.]]></description>
										<content:encoded><![CDATA[<p>Unlike the .NET platform, Silverlight only provides two text encodings out of the box: UTF-8 (<span class="code">UTF8Encoding </span>class) and UTF-16 (<span class="code">UnicodeEncoding </span>class).</p>
<p>Accordingly, if you find yourself in a situation where you need to encode or decode data with another encoding (e.g. <em>iso-8859-1</em>), you’ll have to write your own <a href="http://msdn.microsoft.com/en-us/library/system.text.encoding%28VS.95%29.aspx">Encoding</a> class (or delegate the work to a server-side service).</p>
<p>I found myself in this exact situation yesterday, and came up with a little tool which automates the process. The Encoding Generator is a WPF application which takes the name or code page of a well known encoding, and generates source code for a custom Encoding class which compiles under Silverlight.</p>
<p>&#160;</p>
<p><strong><font color="#ff0000" size="1"></font></strong></p>
<p><a class="download" href="/uploads/projects/silverlight/encoding-generator-src.zip">Get Source Code</a></p>
<p>&#160;</p>
<p><a class="download" href="/uploads/projects/silverlight/encoding-generator-bin.zip">Get Compiled Executable</a></p>
<p><font color="#ff0000" size="1"><strong>Current version: 1.0.0, 2010.03.31, requires .NET 3.5 SP1 or higher</strong></font></p>
<p><font color="#000000" size="1">(You can subscribe to the <a href="http://www.hardcodet.net/feed">RSS feed</a> or follow me on <a href="http://twitter.com/phsumi">Twitter</a> in order to get notified about updates and bug fixes)</font></p>
<p>&#160;</p>
<p><a href="http://blog.hardcodet.net/wp-content/uploads/2010/03/image11.png"><img loading="lazy" style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2010/03/image-thumb1.png" width="524" height="535" /></a> </p>
<p>&#160;</p>
<p>&#160;</p>
<h2>How Does It Work?</h2>
<p>&#160;</p>
<h3>Specifying the Encoding</h3>
<p>In order to specify the encoding you want to use, you can either enter the name or numeric code page of a well-known encoding. As soon as you enter a valid value, some information for the encoding is being displayed in the right hand border you can see on the screenshot.</p>
<p>As a sample for valid encoding names or code pages, here’s some values you can enter in order to tell the tool to generate an iso-8859-1 encoder (see screenshot):</p>
<ul>
<li>iso-8859-1 (name) </li>
<li>latin1 (name) </li>
<li>28591 (code page) </li>
</ul>
<ul>A list of encodings can be found <a href="http://msdn.microsoft.com/en-us/library/86hf4sb8%28v=VS.90%29.aspx">here</a>.</ul>
<h3>Fallback Character</h3>
<p>The tool gives you the option to specify a fallback character value, which is used as a default in case a character or byte value is being processed during encoding/decoding. In case you don’t specify the character, the encoding class will crash at runtime should it receive data that cannot be properly encoded or decoded.</p>
<h3>Single-Byte Encoding Limitation</h3>
<p>The generated class only works if a single byte can be translated into a single character and vice versa. Accordingly, if you try to generate code for an encoding that uses several bytes per (e.g. <em>utf-8</em>) character, the generator shows an error message.</p>
<h3>Byte Range</h3>
<p>You need to specify the byte range of the encoding. For example, ASCII supports only 128 characters, and therefore has a byte range of 128 bytes. Most other encodings support a byte range of 256 bytes, though. 256 is the maximum value that can be specified, as a single byte cannot deliver more values (the byte data type covers a numeric range from 0 – 255).</p>
<h3>Testing</h3>
<p>The generator also creates an NUnit test class that compares the results of the generated class against the original encoding. Accordingly, this test class is supposed to run in a regular .NET environment, not in Silverlight (if the original encoding that is used in the test was available in SL, you wouldn’t have to generate a custom encoding class in the first place…).</p>
<h3>Internals</h3>
<p>At runtime, the following is happening: Basically, the generator maintains mapping tables to do the encoding and decoding from characters to bytes and vice versa. Fore every request, it just looks up the translation tables for every supported character/byte value of the encoding.</p>
<p>The generator creates these translation tables on the fly in the form of a static array and dictionary.</p>
<h2>Performance</h2>
<p>The library doesn’t contain any performance tweaks and performs much slower than the built-in encodings that rely on all sorts of black magic. However, as long as you don’t have to encode or decode huge amounts of data, this shouldn’t be noticeable.</p>
<p>Here’s the results from my machine for <strong>10000 iterations</strong>:</p>
<ul>
<li>Encoding the whole character table to a byte array (256 characters)
<ul>
<li>17 milliseconds with the built-in encoding </li>
<li>94 milliseconds with the generated encoding </li>
</ul>
</li>
<li>Decoding the bytes back into a string
<ul>
<li>2 milliseconds with the built-in encoding </li>
<li>46 milliseconds with the custom encoding </li>
</ul>
</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2010/03/silverlight-text-encoding-class-generator/feed</wfw:commentRss>
			<slash:comments>28</slash:comments>
		
		
			</item>
		<item>
		<title>Input Focus from the View Model &#8211; Configured via Blend Behaviors</title>
		<link>http://www.hardcodet.net/2010/03/input-focus-from-the-view-model-configured-via-blend-behaviors</link>
					<comments>http://www.hardcodet.net/2010/03/input-focus-from-the-view-model-configured-via-blend-behaviors#comments</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Wed, 17 Mar 2010 11:22:03 +0000</pubDate>
				<category><![CDATA[WPF]]></category>
		<category><![CDATA[Disciples]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/2010/03/input-focus-from-the-view-model-configured-via-blend-behaviors</guid>

					<description><![CDATA[Discusses the usage of Blend behaviors in order to wire up input focs control between UI and View Model.]]></description>
										<content:encoded><![CDATA[<h3>Background / Focus of this Article</h3>
<p>WPF wizard and fellow WPF Disciple <a href="http://joshsmithonwpf.wordpress.com">Josh Smith</a> published an article yesterday that showed how to control input focus from View Model objects using attached properties and a custom binding extension. Prior to the article, there was a discussion in the Disciples group, during which I looked into using Blend behaviors as an alternative configuration approach to Josh’s markup extension – this article here discusses this approach.</p>
<p>Accordingly, this posting is not about controlling input focus. Josh did all the legwork there, and you should <a href="http://joshsmithonwpf.wordpress.com/2010/03/16/control-input-focus-from-viewmodel-objects/"><strong>check out the article on his blog</strong></a>. Everything that goes beyond the Behavior classes is Josh’s work, not mine&#160; &#8211; I merely discuss a different approach regarding the <strong><em>declaration</em></strong> of focus control on the UI using Blend Behaviors.</p>
<p>&#160;</p>
<p><a class="download" title="Download" href="/uploads/2010/03/focusbehaviors.zip">Download Source Code and Sample Application</a></p>
<p>&#160;</p>
<h3>Differences</h3>
<p>Let’s start by looking at the difference from a developer’s point of view. Assume you have a simple <span class="code">TextBox </span>control that is bound to a <span class="code">FirstName </span>property on the View Model:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">&lt;!-- simple textbox --&gt;</span>
<span style="color: #0000ff">&lt;</span><span style="color: #800000">TextBox</span> <span style="color: #ff0000">Text</span><span style="color: #0000ff">=&quot;{Binding FirstName}&quot;</span> <span style="color: #0000ff">/&gt;</span></pre>
</div>
<p>&#160;</p>
<h4>Markup Extensions – One for the XAML Guys / Gals</h4>
<p>Josh’s approach using a markup extension is a very lean way to wire up your control with the focus controller. If you’re used to coding in XAML, this is pretty much the quickest way to get things running. Note that only the <span class="code">Binding </span>keyword was replaced by a the custom <span class="code">FocusBinding </span>markup extension:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">&lt;!-- simple textbox --&gt;</span>
<span style="color: #0000ff">&lt;</span><span style="color: #800000">TextBox</span> <span style="color: #ff0000">Text</span><span style="color: #0000ff">=&quot;{jas:FocusBinding FirstName}&quot;</span> <span style="color: #0000ff">/&gt;</span></pre>
</div>
<p>&#160;</p>
<p>If you’re working in Visual Studio, this is the way to go (even more so if you have ReSharper to take care of the namespace declarations for you). It might become tedious, however, if&#8217; you’re working in a Blend environment: For one thing, there’s the namespace declarations. And then, you can no longer wire up your bindings directly in Blend on the designer surface.</p>
<p>&#160;</p>
<h4>Blend Behaviors – Designer’s Flavor</h4>
<p>The Blend Behaviors don’t require you to write any XAML at all. The data binding itself remains unchanged, and the <span class="code">TextBoxFocusBehavior </span>was just dragged/dropped on the TextBox in Blend. Accordingly, you can set up both binding and input focus control with a few mouse clicks without having to leave the designer surface:</p>
<p><img loading="lazy" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2010/03/image7.png" width="268" height="50" /></p>
<p>&#160;</p>
<p>If you look at XAML source, you’ll notice that the Behavior above actually produces substantially more markup – this isn’t something you’d want to type in manually:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">&lt;</span><span style="color: #800000">TextBox</span> <span style="color: #ff0000">Text</span><span style="color: #0000ff">=&quot;{Binding FirstName}&quot;</span> <span style="color: #0000ff">&gt;</span>
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">i:Interaction.Behaviors</span><span style="color: #0000ff">&gt;</span>
        <span style="color: #0000ff">&lt;</span><span style="color: #800000">FocusVMLib_Behaviors:TextBoxFocusBehavior</span><span style="color: #0000ff">/&gt;</span>
    <span style="color: #0000ff">&lt;/</span><span style="color: #800000">i:Interaction.Behaviors</span><span style="color: #0000ff">&gt;</span>
<span style="color: #0000ff">&lt;/</span><span style="color: #800000">TextBox</span><span style="color: #0000ff">&gt;</span></pre>
</div>
<p>&#160;</p>
<p>In order to compare the two approaches, just download the attached sample and have a look at the two Window classes. <span class="code">Window1 </span>is the original implementation (using the markup extension), <span class="code">Window2 </span>uses the Blend behaviors. The end result is the same – the only difference is the different declaration approaches.</p>
<p>&#160;</p>
<h3>The Behavior Classes</h3>
<p>The rest of this blog post discusses the implementation of the behavior classes, and suggests an approach to support different control types. </p>
<p><span id="more-790"></span></p>
<h4>A Problem: Where to get the Bound Property?</h4>
<p>Josh’s focus helper library uses the binding between the UI and the View Model in order to observe the View Model for a change on a relevant property.</p>
<p>Accordingly, the Blend Behavior needs to determine the bound property somehow in order to submit it to the <span class="code">FocusController </span>class. Basically, there’s two solutions:</p>
<ul>
<li>Write control-aware Behaviors that implicitly use the correct property. </li>
<li>Write a Behavior that lets you specify the bound property at design time. </li>
</ul>
<p>I decided to support both approaches. The sample application consists of three classes:</p>
<ul>
<li>An abstract base class that wires up the control in order to take part in focus control. </li>
<li>A generic Behavior class that allows to specify the bound property manually. </li>
<li>A exemplary Behavior that can be used on <span class="code">TextBox </span>controls without having to do any further configuration. You will see that you can create similar classes for other controls in a matter of seconds. </li>
</ul>
<p>&#160;</p>
<p><img loading="lazy" style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2010/03/image8.png" width="499" height="372" /> </p>
<p>&#160;</p>
<p>&#160;</p>
<h4>The FocusBehaviorBase Class</h4>
<p>This <em>abstract</em> base class takes care about wiring up the associated UI element with the <span class="code">FocusController </span>of Josh’s focus helper library:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">abstract</span> <span style="color: #0000ff">class</span> FocusBehaviorBase : Behavior&lt;FrameworkElement&gt;
{
  <span style="color: #0000ff">protected</span> <span style="color: #0000ff">abstract</span> DependencyProperty GetSourceProperty();


  <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> OnAttached()
  {
    <span style="color: #008000">//get the bound property discovery</span>
    DependencyProperty sourceProperty = GetSourceProperty();

    <span style="color: #008000">//delegate focus handling</span>
    FocusController.SetFocusableProperty(AssociatedObject, sourceProperty);
  }
}</pre>
</div>
<p>&#160;</p>
<p>As you can see in the snippet above, the base class delegates the job to resolve the bound property via the abstract <span class="code">GetSourceProperty </span>method. This property, along with the associated object, is then forwarded to the <span class="code">FocusController </span>class which takes care of the rest.</p>
<p>&#160;</p>
<h4>Generic but Complex Behaviors</h4>
<p>The first working Behavior implementation is a generic version that lets you specify the bound property yourself. As such, the class exposes a <span class="code">BoundSource </span>property, which takes an arbitrary <span class="code">DependencyProperty</span>. The <span class="code">GetSourceProperty </span>method then just returns that property:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> CustomFocusBehavior : FocusBehaviorBase
{
  <span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">readonly</span> DependencyProperty BoundSourceProperty =
    DependencyProperty.Register(<span style="color: #006080">&quot;BoundSource&quot;</span>, <span style="color: #0000ff">typeof</span> (DependencyProperty), <span style="color: #0000ff">typeof</span> (CustomFocusBehavior));


  <span style="color: #0000ff">public</span> DependencyProperty BoundSource
  { 
    get { <span style="color: #0000ff">return</span> (DependencyProperty)GetValue(BoundSourceProperty); }
    set { SetValue(BoundSourceProperty, <span style="color: #0000ff">value</span>); }
  }


  <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> DependencyProperty GetSourceProperty()
  {
    <span style="color: #008000">//return the property value to the base class</span>
    <span style="color: #0000ff">return</span> BoundSource;
  }
}</pre>
</div>
<p>&#160;</p>
<p>This class is already sufficient to cover any binding scenarios, but it requires you to specify the property yourself with a rather unusual binding expression (you are not binding to a property value, but a dependency property itself):</p>
<p>&#160;</p>
<p>&#160;<img loading="lazy" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2010/03/image9.png" width="337" height="111" /> </p>
<p>&#160;</p>
<p>The advantage of this generic Behavior is that you can bind to arbitrary properties. On the other hand, it’s obvious that this approach isn’t exactly designer friendly, which is why I’d recommend to simplify things for common controls with custom Behaviors.</p>
<p>&#160;</p>
<h4>Controls Specific Behaviors</h4>
<p>The <span class="code">FocusBehaviorBase </span>class expects only one thing from an implementing class: Information about a bound property. This makes it extremely simple to create control-aware behaviors. The sample application contains one example that can be used with TextBoxes, called <span class="code">TextBoxFocusBehavior</span>. The implementation is trivial:</p>
<p>&#160;</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> TextBoxFocusBehavior : FocusBehaviorBase
{
  <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> DependencyProperty GetSourceProperty()
  {
    <span style="color: #0000ff">return</span> TextBox.TextProperty;
  }
}</pre>
</div>
<p>&#160;</p>
</p>
<p>A behavior like this requires no additional configuration if you are working in Blend. Just drag and drop the behavior on the control and be on your way. And of course, nothing stops you from writing your own behavior classes.</p>
<p>As an additional example, here’s a behavior that covers all controls of type <span class="code">ToggleButton</span>, which includes checkboxes and radio buttons:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">//this also covers CheckBox and RadioButton</span>
<span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> ToggleFocusBehavior : FocusBehaviorBase
{
  <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> DependencyProperty GetSourceProperty()
  {
    <span style="color: #0000ff">return</span> ToggleButton.IsCheckedProperty;
  }
}</pre>
</div>
<p>&#160;</p>
<p>You could also write a Behavior that looks at the <span class="code">AssociatedObject </span>before returning a property, or one that takes a string argument and resolves the dependency property via reflection. Basically, there’s no limits here. However, I assume you will probably only have to write a few behaviors to cover your whole application – accordingly, I’d recommend you to write simple behaviors such as the <span class="code">TextBoxFocusBehavior</span>.</p>
<p>&#160;</p>
<h3>Conclusion</h3>
<p>Behaviors are a very convenient way if you are working in Blend. Just dropping a few behaviors on your controls is more comfortable than tampering with XAML, and the bindings remain untouched, so you can edit them in Blend at any time.</p>
<p>On the other hand, if you’re working with Visual Studio, or if you are used to set up your bindings directly in XAML anyway, just using the markup extension is the faster and leaner choice.</p>
<p>In my opinion, the two approaches complement themselves. Both are just means to wire up your controls with the View Model, so the outcome is the same. In the end, it’s about preference.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2010/03/input-focus-from-the-view-model-configured-via-blend-behaviors/feed</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>Remote File Access in VFS using OpenRasta – Part 1 (Introduction)</title>
		<link>http://www.hardcodet.net/2010/02/remote-file-access-in-vfs-part-1</link>
					<comments>http://www.hardcodet.net/2010/02/remote-file-access-in-vfs-part-1#comments</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Sun, 14 Feb 2010 12:54:39 +0000</pubDate>
				<category><![CDATA[REST]]></category>
		<category><![CDATA[VFS]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/?p=775</guid>

					<description><![CDATA[This lose series of articles will cover the implementation of a file system façade that allows transparent remote file system access in VFS. The series will cover the following topics: Introduction and basic concept (this article) Implementing a RESTful file system proxy service with OpenRasta (coming soon) Unit testing the OpenRasta proxy service (not yet [&#8230;]]]></description>
										<content:encoded><![CDATA[</p>
<p>This lose series of articles will cover the implementation of a file system façade that allows transparent remote file system access in <a href="http://vfs.codeplex.com/">VFS</a>.</p>
<p>The series will cover the following topics:</p>
<ul>
<li>Introduction and basic concept (this article)</li>
<li>Implementing a RESTful file system proxy service with <a href="http://trac.caffeine-it.com/openrasta">OpenRasta</a> (coming soon)</li>
<li>Unit testing the OpenRasta proxy service (not yet published)</li>
<li>General tutorial: Streaming binary data in Silverlight</li>
<li>Implementing VFS client libraries for both .NET and Silverlight (not yet published)</li>
</ul>
<h3>VFS File System Providers</h3>
<p>VFS abstracts access to arbitrary file systems through so-called “File System Providers”, which expose a common interface (<span class="code">IFileSystemProvider</span>) that allows you to browse and modify the file system. The interface is not exactly lean, but easy to understand:</p>
<p><img loading="lazy" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2010/02/image1.png" width="300" height="483" /> </p>
<p>Now, common file system providers directly operate on some kind of hierarchical data. Here’s a few examples:</p>
<ul>
<li>The “Local File System Provider” allows you to access your local machine, or the contents of a dedicated directory. </li>
<li>The “ZIP File System Provider” works upon a single ZIP file, and allows you to transparently access and modify its contents. </li>
<li>An “FTP File System Provider” connects to a given FTP server and gives you access to the server’s files through the VFS API. </li>
<li>… </li>
</ul>
<p>So basically, an application uses a VFS provider, which in turn directly accesses the exposed file system:</p>
<p><img loading="lazy" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2010/02/image2.png" width="262" height="46" /> </p>
<p>&#160;</p>
<h3>Tunneling Façades</h3>
<p>There is, however, a special family of file system providers that do not access any files. Instead, they forward file system requests to another file system provider, thus creating a tunnel to another file system. Basically, these file system providers are <em><strong>façades</strong></em> to another, arbitrary file system provider.</p>
<p><img loading="lazy" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2010/02/image3.png" width="550" height="123" /> </p>
<p>&#160;</p>
<p>Here’s an exemplary scenario that uses a façade in order to access a ZIP file that is exposed through a ZIP file provider (click on the UML diagram in order to see it in full size).</p>
<p>&#160;<a href="http://blog.hardcodet.net/wp-content/uploads/2010/02/tunnelling.png"><img loading="lazy" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Tunnelling" border="0" alt="Tunnelling" src="http://blog.hardcodet.net/wp-content/uploads/2010/02/tunnelling-thumb.png" width="550" height="250" /></a> </p>
<p>&#160;</p>
<p>The interesting point here: From the client’s perspective, there is no difference in accessing the file system. The façade itself implements the <span class="code">IFileSystemProvider </span>interface – it provides <em>exactly</em> the same API as any other provider.</p>
<p>As you can see from the diagram above, a façade is usually complemented by some kind of proxy that receives the forwarded requests, so in order to implement the pattern, there’s two components to be written:</p>
<ol>
<li>The façade, which implements <span class="code">IFileSystemProvider</span>. </li>
<li>The proxy that takes the forwarded requests, forwards them its own file system provider, and eventually returns the requested data. This proxy is not a VFS component, and you don’t have to implement any VFS interfaces. </li>
</ol>
<p>As you can guess, tunnels come in handy in order to access remote data. Here’s a few scenarios:</p>
<ul>
<li>Run a local file system provider on a server that provides a download service. Clients don’t have direct access to the files, but use a tunnel to access the files that are exposed through the provider that runs on the server. </li>
<li>Allow a Silverlight client to browse the contents of a ZIP file on the server, without having to download the whole ZIP file first (sample coming).</li>
<li>Host a cloud file system provider within a WCF service, and expose parts of the cloud’s data to clients. Like this, clients don’t have direct access to the cloud data.</li>
</ul>
<h3>A RESTful Façade Implementation</h3>
<p>Every façade itself is an independent file system provider – so tunneling is rather a pattern than an API, and you can write your own façade should you wish to (actually, contributions will be most welcome!).</p>
<p>However, VFS 1.0 will ship with a single façade implementation that uses HTTP/REST to create a tunnel to a remote file system. It is built upon the following libraries:</p>
<ul>
<li>On the server side, <a href="http://trac.caffeine-it.com/openrasta">OpenRasta</a> was used to expose file system access as RESTful services. OpenRasta is a lightweight, but powerful framework that comes with a API.</li>
<li>On the client side, the WCF REST Starter Kit was used for both <a href="http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24644">.NET</a> and Silverlight clients (the <a href="http://www.hardcodet.net/2010/02/wcf-rest-starter-kit-for-silverlight">Silverlight library</a> hacked together by myself). The starter kit’s client libraries allow for simple access to RESTful resources, even if there is no WCF involved.</li>
</ul>
<p>&#160;</p>
<p>The upcoming articles will walk you through the implementation of the both the client and service libraries, and will also be complemented by a preview release of VFS. Stay tuned <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2010/02/remote-file-access-in-vfs-part-1/feed</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>REST Client Library for Silverlight</title>
		<link>http://www.hardcodet.net/2010/02/wcf-rest-starter-kit-for-silverlight</link>
					<comments>http://www.hardcodet.net/2010/02/wcf-rest-starter-kit-for-silverlight#comments</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Mon, 08 Feb 2010 16:49:08 +0000</pubDate>
				<category><![CDATA[REST]]></category>
		<category><![CDATA[Silverlight]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/2010/02/wcf-rest-starter-kit-for-silverlight</guid>

					<description><![CDATA[A port of the WCF REST Starter Kit to Silverlight.]]></description>
										<content:encoded><![CDATA[<p>I’ve been doing some hackery and ported the client libraries of the <a href="http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24644">WCF REST Starter Kit</a> to Silverlight. The library greatly simplifies things when it comes to accessing and consuming RESTful services and resources in your Silverlight application.</p>
<p>Here’s a sample for a simple GET using the <span class="code">HttpClient </span>class:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> User GetUser(<span style="color: #0000ff">string</span> userId)
{
  <span style="color: #008000">//init client with base URI</span>
  HttpClient client = <span style="color: #0000ff">new</span> HttpClient(<span style="color: #006080"><a href="http://localhost:56789/users/">http://localhost:56789/users/</a></span>);

  <span style="color: #008000">//send a HTTP GET request for a given resource</span>
  HttpResponseMessage response = client.Get(userId);

  <span style="color: #008000">//parse the received data on the fly</span>
  <span style="color: #0000ff">return</span> response.Content.ReadAsDataContract&lt;User&gt;();
}</pre>
</div>
<p>&#160;</p>
<p>Or, in order to send a DTO via HTTP POST:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> PostUser(User user)
{
  <span style="color: #008000">//init client with base URI</span>
  HttpClient client = <span style="color: #0000ff">new</span> HttpClient(<span style="color: #006080">&quot;http://localhost:56789/&quot;</span>);

  <span style="color: #008000">//serialize user object</span>
  HttpContent content = HttpContentExtensions.CreateDataContract(user);

  <span style="color: #008000">//post to user service</span>
  HttpResponseMessage response = client.Post(<span style="color: #006080">&quot;/user&quot;</span>, content);
}</pre>
</div>
<p>&#160;</p>
<p>I have removed a few bits, but most of the functionality should be there, and I added “NOTE” comments to all the sections that I had to modify. I haven’t used this port in-depth but managed to access my RESTful resources as expected so far, and I hope it will work just fine as in most scenarios that are covered in the original Starter Kit. Of course, given the Starter Kit itself is prerelease software, this applies to this release even more.</p>
<p>&#160;</p>
<h4>Blocking vs. Async Operations</h4>
<p>If you try to initiate a blocking request to your REST service on the UI thread, an <span class="code">InvalidOperationException</span> is thrown due to synchronization issues. Accordingly, a snippet as the one above should always be invoked on a worker thread (which is a best practice anyway).</p>
<p>However, in order to simplify things, I’ve added a bunch of <span class="code">XXXAsync</span> extension methods for the <span class="code">HttpClient </span>class that allow you to invoke HTTP operations such as GET, POST, PUT etc. directly on the UI thread, and have the result delivered back to you through a simple callback action. Here’s the same snippet as above, this time using the <span class="code">GetAsync </span>method of the <span class="code">HttpClient </span>class:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> GetFolder()
{
  HttpClient client = <span style="color: #0000ff">new</span> HttpClient(<span style="color: #006080">&quot;http://localhost:56789/root&quot;</span>);

  <span style="color: #008000">//you can invoke the GetAsync method on a worker thread</span>
  client.GetAsync(response =&gt;
    {
      VirtualFolder folder = response.Content.ReadAsDataContract&lt;VirtualFolder&gt;();
    });
}</pre>
</div>
<p>&#160;</p>
</p>
<p>Note that the callback action will be invoked on a worker thread, so you might have to switch back to the UI thread if you want to modify your UI.</p>
<p>&#160;</p>
<p>Oh yes: Use at your own risk <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>&#160;</p>
<p><a class="download" title="http://www.hardcodet.net/uploads/projects/silverlight/rest-starter-kit-sl.zip" href="http://www.hardcodet.net/uploads/projects/silverlight/rest-starter-kit-sl.zip">Download REST Starter Kit for Silverlight</a></p>
<p><font color="#ff0000" size="1"><strong>Current Version: 1.0.3, 2010.02.14</strong></font></p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2010/02/wcf-rest-starter-kit-for-silverlight/feed</wfw:commentRss>
			<slash:comments>16</slash:comments>
		
		
			</item>
		<item>
		<title>A GetResponse Extension for Synchronized Web Requests in Silverlight</title>
		<link>http://www.hardcodet.net/2010/02/blocking-httpwebrequest-getresponse-for-silverlight</link>
					<comments>http://www.hardcodet.net/2010/02/blocking-httpwebrequest-getresponse-for-silverlight#comments</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Mon, 08 Feb 2010 11:40:55 +0000</pubDate>
				<category><![CDATA[Silverlight]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/2010/02/blocking-httpwebrequest-getresponse-for-silverlight</guid>

					<description><![CDATA[A snippet that bring the blocking HttpWebRequest.GetResponse functionality back to Silverlight.]]></description>
										<content:encoded><![CDATA[<p>Unlike its CLR counter part, Silverlight’s <span class="code">HttpWebRequest </span>does not provide a synchronous <span class="code">GetResponse </span>method that allows to receive an HTTP response in a blocking operation. As a result, you are forced to use the asynchronous <span class="code">BeginGetResponse </span>method, and handle the results on a callback method.</p>
<p>This makes sense if the response is requested on the UI thread (otherwise, it would freeze the UI), but it might be a problem in certain scenarios (e.g. if you want to submit multiple requests in an orderly fashion).</p>
<p>However, you can get around the issue by using wait handles, which allow you to easily block a running operation. I encapsulated the required functionality in a simple extension method that brings <span class="code">GetResponse </span>method back into Silverlight.</p>
<p>The usage is simple – you just invoke the <span class="code">GetResponse()</span> extension method with an optional timeout. Here’s a sample that submits five synchronous HTTP requests:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> RunRequests()
{
  <span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = 0; i &lt; 5; i++)
  {
    Uri uri = <span style="color: #0000ff">new</span> Uri(<span style="color: #006080">&quot;http://localhost/users?user=&quot;</span> + i);
    HttpWebRequest request = 
      (HttpWebRequest)WebRequestCreator.ClientHttp.Create(uri);

    <span style="color: #008000">//get response as blocking operation which times out after 10 secs</span>
    HttpWebResponse response = request.GetResponse(10000);
  }
}</pre>
</div>
<p>&#160;</p>
<p><em><font color="#ff0000">You will run into timeout issues if you run execute this method on the UI thread because internally, the requested response accesses the UI thread (for whatever reasons). <u>Only</u> invoke this extension method on background threads!</font></em></p>
<p>&#160;</p>
<p>Here’s the implementation:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">class</span> RequestHelper
{
  <span style="color: #008000">/// &lt;summary&gt;</span>
  <span style="color: #008000">/// A blocking operation that does not continue until a response has been</span>
  <span style="color: #008000">/// received for a given &lt;see cref=&quot;HttpWebRequest&quot;/&gt;, or the request</span>
  <span style="color: #008000">/// timed out.</span>
  <span style="color: #008000">/// &lt;/summary&gt;</span>
  <span style="color: #008000">/// &lt;param name=&quot;request&quot;&gt;The request to be sent.&lt;/param&gt;</span>
  <span style="color: #008000">/// &lt;param name=&quot;timeout&quot;&gt;An optional timeout.&lt;/param&gt;</span>
  <span style="color: #008000">/// &lt;returns&gt;The response that was received for the request.&lt;/returns&gt;</span>
  <span style="color: #008000">/// &lt;exception cref=&quot;TimeoutException&quot;&gt;If the &lt;paramref name=&quot;timeout&quot;/&gt;</span>
  <span style="color: #008000">/// parameter was set, and no response was received within the specified</span>
  <span style="color: #008000">/// time.&lt;/exception&gt;</span>
  <span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> HttpWebResponse GetResponse(<span style="color: #0000ff">this</span> HttpWebRequest request,
                                            <span style="color: #0000ff">int</span>? timeout)
  {
    <span style="color: #0000ff">if</span> (request == <span style="color: #0000ff">null</span>) <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> ArgumentNullException(<span style="color: #006080">&quot;request&quot;</span>);

    <span style="color: #0000ff">if</span> (System.Windows.Deployment.Current.Dispatcher.CheckAccess())
    {
      <span style="color: #0000ff">const</span> <span style="color: #0000ff">string</span> msg = <span style="color: #006080">&quot;Invoking this method on the UI thread is forbidden.&quot;</span>;
      <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> InvalidOperationException(msg);
    }

    AutoResetEvent waitHandle = <span style="color: #0000ff">new</span> AutoResetEvent(<span style="color: #0000ff">false</span>);
    HttpWebResponse response = <span style="color: #0000ff">null</span>;
    Exception exception = <span style="color: #0000ff">null</span>;

    AsyncCallback callback = ar =&gt;
       {
         <span style="color: #0000ff">try</span>
         {
           <span style="color: #008000">//get the response</span>
           response = (HttpWebResponse)request.EndGetResponse(ar);
         }
         <span style="color: #0000ff">catch</span>(Exception e)
         {
           exception = e;
         }
         <span style="color: #0000ff">finally</span>
         {
           <span style="color: #008000">//setting the handle unblocks the loop below</span>
           waitHandle.Set(); 
         }
       };


    <span style="color: #008000">//request response async</span>
    var asyncResult = request.BeginGetResponse(callback, <span style="color: #0000ff">null</span>);
    <span style="color: #0000ff">if</span> (asyncResult.CompletedSynchronously) <span style="color: #0000ff">return</span> response;

    <span style="color: #0000ff">bool</span> hasSignal = waitHandle.WaitOne(timeout ?? Timeout.Infinite);
    <span style="color: #0000ff">if</span> (!hasSignal)
    {
      <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> TimeoutException(<span style="color: #006080">&quot;No response received in time.&quot;</span>);
    }

    <span style="color: #008000">//bubble exception that occurred on worker thread</span>
    <span style="color: #0000ff">if</span> (exception != <span style="color: #0000ff">null</span>) <span style="color: #0000ff">throw</span> exception;

    <span style="color: #0000ff">return</span> response;
  }
}</pre>
</div>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2010/02/blocking-httpwebrequest-getresponse-for-silverlight/feed</wfw:commentRss>
			<slash:comments>14</slash:comments>
		
		
			</item>
		<item>
		<title>A Simplistic Random String Generation Snippet</title>
		<link>http://www.hardcodet.net/2010/01/simple-random-strings</link>
					<comments>http://www.hardcodet.net/2010/01/simple-random-strings#comments</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Mon, 25 Jan 2010 12:27:00 +0000</pubDate>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Random]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/2010/01/simple-random-strings</guid>

					<description><![CDATA[This is just a little snippet that generates a random string, containing both upper and lower case characters and special chars, so there’s a range of 93 possible characters, taken from the UTF-8 character table. I thought I’d post it as the snippets I’ve seen after a quick search usually just generate strings with characters [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>This is just a little snippet that generates a random string, containing both upper and lower case characters and special chars, so there’s a range of 93 possible characters, taken from the <a href="http://www.utf8-chartable.de/">UTF-8 character table</a>. I thought I’d post it as the snippets I’ve seen after a quick search usually just generate strings with characters ranging from ‘A’ to ‘Z’, or do not work with properly initialized seeds.</p>
<p>Note that this method uses a static int field (<span class="code">seedCounter</span>) when in comes to creating a random seed. This counter is incremented in a thread safe manner every time the method is being invoked. This simple trick is a simple workaround to the notoriously unreliable <span class="code">Random </span>class, and effectively prevents double seeds (and thus: duplicate “random strings”) if the <span class="code">GetRandomString </span>method is being invoked several times immediately. As an alternative, you could also use a static <span class="code">Random </span>field, which would only have to be initialized once. My implementation has the smaller footprint (and integer variable), while a <span class="code">Random </span>field would perform much better (currently, every invocation calculates a seed and creates a new <span class="code">Random </span>instance). The better choice depends on the context I guess:</p>
<p>&#160;</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">/// &lt;summary&gt;</span>
<span style="color: #008000">/// A counter that is being incremented with every invocation of</span>
<span style="color: #008000">/// &lt;see cref=&quot;GetRandomString&quot;/&gt;.</span>
<span style="color: #008000">/// &lt;/summary&gt;</span>
<span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">int</span> seedCounter = (<span style="color: #0000ff">int</span>)DateTime.Now.Ticks;


<span style="color: #008000">/// &lt;summary&gt;</span>
<span style="color: #008000">/// Generates a random string of a given length, which consists</span>
<span style="color: #008000">/// of characters taken from the UTF-8 table (0x21 - 0x7e).</span>
<span style="color: #008000">/// &lt;/summary&gt;</span>
<span style="color: #008000">/// &lt;param name=&quot;length&quot;&gt;The length of the random string.&lt;/param&gt;</span>
<span style="color: #008000">/// &lt;returns&gt;Random characters.&lt;/returns&gt;</span>
<span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">string</span> GetRandomString(<span style="color: #0000ff">int</span> length)
{
  <span style="color: #0000ff">const</span> <span style="color: #0000ff">int</span> lower = 0x21;
  <span style="color: #0000ff">const</span> <span style="color: #0000ff">int</span> upper = 0x7e;

  StringBuilder builder = <span style="color: #0000ff">new</span> StringBuilder();

  <span style="color: #008000">//increment thread-safe</span>
  seedCounter = Interlocked.Increment(<span style="color: #0000ff">ref</span> seedCounter);

  <span style="color: #008000">//create random with the seed (make sure it's not int.MinValue)</span>
  Random rnd = <span style="color: #0000ff">new</span> Random(seedCounter %<span style="color: #0000ff">int</span>.MinValue);

  <span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = 0; i &lt; length; i++)
  {
    builder.Append((<span style="color: #0000ff">char</span>) rnd.Next(lower, upper));
  }

  <span style="color: #0000ff">return</span> builder.ToString();
}</pre>
</div>
<p>&#160;</p>
<p>Accordingly, invoking the method like this:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">string</span> random = GetRandomString(10);</pre>
</div>
<p>&#160;</p>
<p>&#8230;generates you a string comparable to this one: <span class="code">2#,R`6&gt;Cz{</span></p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2010/01/simple-random-strings/feed</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Lightweight Task Scheduling Library for .NET / Silverlight</title>
		<link>http://www.hardcodet.net/2010/01/lightweight-task-slash-job-scheduling-with-silverlight-support</link>
					<comments>http://www.hardcodet.net/2010/01/lightweight-task-slash-job-scheduling-with-silverlight-support#comments</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Sat, 09 Jan 2010 20:35:59 +0000</pubDate>
				<category><![CDATA[CodeProject]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[VFS]]></category>
		<category><![CDATA[Scheduling]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/?p=727</guid>

					<description><![CDATA[Presents a lightweight task scheduling library for .NET 3.5 / Silverlight.]]></description>
										<content:encoded><![CDATA[<p>I’m currently working on <a href="http://vfs.codeplex.com">VFS</a>, a virtual file system. For running transfers, VFS internally maintains locks that do have expiration time. Accordingly, I found myself in need for a job scheduling mechanism in order to properly release expired locks. I looked around for a few <a href="http://quartznet.sourceforge.net/tutorial/index.html">alternatives</a>, but eventually ended up writing my own lightweight version.</p>
<p>Features:</p>
<ul>
<li>Simple scheduling and callback mechanisms </li>
<li>Silverlight compatible </li>
<li>Lightweight </li>
<li>Fluent API </li>
<li>Detection of system time changes with optional rescheduling </li>
<li>Optional forwarding of exceptions during job execution </li>
<li>Open Source (Ms-PL) </li>
</ul>
<p>&#160;</p>
<p><a title="Download Project" href="http://www.hardcodet.net/uploads/projects/scheduling/hardcodet.scheduling.zip"></a><a class="download" title="Download Project" href="http://www.hardcodet.net/uploads/projects/scheduling/hardcodet.scheduling.zip">Download library and sample</a></p>
<p><font color="#ff0000" size="1"><strong>Current Version: 1.0.2, 2010.01.12</strong></font></a></p>
<p>&#160;</p>
<h4>What Does it Do?</h4>
<p>Basically, the library allows you to create a job, and submit that job to a scheduler, along with a callback action. This callback action is invoked as soon (or every time) the job is due.</p>
<p>Before going into the details, here’s a first code snippet that creates a simple <span class="code">Job </span>that is supposed to run repeatedly (every 1.5 seconds) for a minute. Once the job is created, it is submitted to a <span class="code">Scheduler </span>instance which processes the job and makes sure the submitted callback action is being invoked every time the job is due:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">private</span> Scheduler scheduler = <span style="color: #0000ff">new</span> Scheduler();

<span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> RunOnce()
{
  <span style="color: #008000">//define a start / end time</span>
  DateTime startTime = DateTime.Now.AddSeconds(5);
  DateTime endTime   = startTime.AddSeconds(60);

  <span style="color: #008000">//configure the job</span>
  Job consoleJob = <span style="color: #0000ff">new</span> Job();
  consoleJob.Run.From(startTime)
                .Every.Seconds(1.5)
                .Until(endTime);

  <span style="color: #008000">//submit the job with the callback to be invoked</span>
  scheduler.SubmitJob(consoleJob, j =&gt; Console.Out.WriteLine(<span style="color: #006080">&quot;hello world&quot;</span>));
}</pre>
</div>
<p>&#160;</p>
<h4>Silverlight</h4>
<p>The project provides class libraries for .NET 3.5 and Silverlight 3, along with a Silverlight sample application that shows how to add scheduling functionality to your SL application with just a few lines of code. </p>
<p>While long-term scheduling isn’t probably something you need to do in a Silverlight application, the scheduler simplifies the management of periodic jobs, such as polling a server for updates. Below is a snippet from the Silverlight sample application. This job starts immediately, and runs indefinitely with an interval of 2 seconds:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> CreateJob2()
{
  <span style="color: #008000">//create job</span>
  Job&lt;<span style="color: #0000ff">int</span>&gt; job = <span style="color: #0000ff">new</span> Job&lt;<span style="color: #0000ff">int</span>&gt;(<span style="color: #006080">&quot;Job 2&quot;</span>);
  job.Data = 0;
  job.Run.Every.Seconds(2);

  <span style="color: #008000">//submit to scheduler</span>
  scheduler.SubmitJob(job, LogJobExecution);
}


<span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> LogJobExecution(Job&lt;<span style="color: #0000ff">int</span>&gt; job, <span style="color: #0000ff">int</span> data)
{
  <span style="color: #008000">//updates user interface</span>
}</pre>
</div>
<p>&#160;</p>
<p><img loading="lazy" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2010/01/image5.png" width="352" height="292" /></p>
<p>&#160;</p>
<h2>Jobs</h2>
<p>&#160;</p>
<p>A job is a simple configuration item for the scheduler. There’s two built-in job types: <span class="code">Job </span>and <span class="code">Job&lt;T&gt;</span>. The only difference between the two is that the latter provides a <span class="code">Data </span>property which allows you to attach state information directly to the job and have it delivered back to you when the job runs.</p>
<p><span id="more-727"></span></p>
<p>&#160;<img loading="lazy" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2010/02/image.png" width="180" height="445" /> </p>
<p>&#160;</p>
<h3>Creating Jobs</h3>
<p>Creating a job is pretty easy, and can be configured through a fluent interface (optional, you can also set the properties the traditional way). Jobs may run once, several times, or indefinitely – you can configure intervals, an optional expiration time, or a maximum number of executions. Here’s a few configuration samples:</p>
<p>&#160;</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">//run the job every second until we manually cancel it</span>
Job job = <span style="color: #0000ff">new</span> Job();
job.Run.Every.Seconds(1);</pre>
</div>
<p>&#160;</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">//create a job with an attached FileInfo</span>
Job&lt;FileInfo&gt; job = <span style="color: #0000ff">new</span> Job&lt;FileInfo&gt;();
job.Data = <span style="color: #0000ff">new</span> FileInfo(<span style="color: #006080">@&quot;C:readme.txt&quot;</span>);

<span style="color: #008000">//run the job 5 times every 1.5 seconds, start immediately</span>
TimeSpan interval = TimeSpan.FromSeconds(1.5);
job.Run.Every.TimeSpan(interval).Times(5);</pre>
</div>
<p>&#160;</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">//create a simple job</span>
Job job = <span style="color: #0000ff">new</span> Job();

<span style="color: #008000">//run the job every 1.5 seconds until it expires</span>
DateTime expiration = DateTime.Now.AddMinutes(5);
job.Run.Every.Seconds(1.5).Until(expiration);</pre>
</div>
<p>&#160;</p>
<h2>The Scheduler Class</h2>
<p>&#160;</p>
<p>Jobs are being submitted to the <span class="code">Scheduler </span>class, which provides a very simple API. Most methods should be pretty self-explanatory, and they are well documented.</p>
<p><img loading="lazy" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2010/01/image7.png" width="220" height="367" /> </p>
<p>&#160;</p>
<h3>Callback Actions</h3>
<p>If you add a <span class="code">Job </span>to the <span class="code">Scheduler </span>through one of the <span class="code">SubmitJob </span>overloads, you have to submit a callback action that is being invoked whenever the job runs. Depending on whether you use <span class="code">Job </span>or <span class="code">Job&lt;T&gt;</span>, a different callback delegate may be used:</p>
<p>&#160;</p>
<table border="0" cellspacing="0" cellpadding="2" width="300">
<tbody>
<tr>
<td valign="top" width="150"><em>Job Class</em></td>
<td valign="top" width="150"><em>Callback Action</em></td>
</tr>
<tr>
<td valign="top" width="150">Job</td>
<td valign="top" width="150">Action&lt;Job&gt;</td>
</tr>
<tr>
<td valign="top" width="150">Job&lt;T&gt;</td>
<td valign="top" width="150">Action&lt;Job&lt;T&gt;, T&gt;</td>
</tr>
</tbody>
</table>
<p>&#160;</p>
<p>Here’s a sample that uses two different callback methods:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">class</span> Program
{
  <span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> Scheduler scheduler = <span style="color: #0000ff">new</span> Scheduler();

  <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> Main(<span style="color: #0000ff">string</span>[] args)
  {
    Job simple = <span style="color: #0000ff">new</span> Job(<span style="color: #006080">&quot;simple&quot;</span>);
    simple.Run.From(DateTime.Now.AddSeconds(3)).Once();
    
    Job&lt;<span style="color: #0000ff">int</span>&gt; generic = <span style="color: #0000ff">new</span> Job&lt;<span style="color: #0000ff">int</span>&gt;(<span style="color: #006080">&quot;generic&quot;</span>) {Data = 123};
    generic.StartAt(DateTime.Now.AddSeconds(1)).Run.Once();

    scheduler.SubmitJob(simple, HandleSimpleJob);
    scheduler.SubmitJob(generic, HandleGenericJob);

    Console.ReadLine();
  }

  <span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> HandleGenericJob(Job job, <span style="color: #0000ff">int</span> data)
  {
    Console.Out.WriteLine(<span style="color: #006080">&quot;Job '{0}' submitted data: {1}&quot;</span>, job.Id, data);
  }

  <span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> HandleSimpleJob(Job job)
  {
    Console.Out.WriteLine(<span style="color: #006080">&quot;Simple job '{0}' was executed.&quot;</span>, job.Id);
  }
}</pre>
</div>
<p>&#160;</p>
<p>The sample above produces the following output on the console:</p>
<p><img loading="lazy" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2010/01/image3.png" width="381" height="179" /> </p>
<p>&#160;</p>
<h3>Cancelling or Pausing a Job</h3>
<p>If you want to cancel or pause a job, you can do this either via the <span class="code">Scheduler </span>class, or directly on the <span class="code">Job </span>instance that is submitted to you whenever the job runs. Note that canceling the job is a terminal operation – a canceled job cannot be resumed.</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> MyJobCallbackAction(Job job)
{
  <span style="color: #008000">//stops execution but keeps the job alive</span>
  job.Pause();

  <span style="color: #008000">//resumes operation of a paused job</span>
  job.Resume();

  <span style="color: #008000">//terminates the job</span>
  job.Cancel();
}</pre>
</div>
<p>&#160;</p>
<p>Actually, doing these operations directly via the <span class="code">Job </span>class is the preferred mechanism – if you use the scheduler’s methods, the scheduler needs to lock its internal list and search for the job itself, which costs you processing power.</p>
<p>&#160;</p>
<h3>Exception Handling</h3>
<p>An exception that occurs during the execution of a job does not affect the scheduler – all jobs are being executed on worker threads taken from the .NET thread pool. However, in order not to miss any exceptions, you can instruct the <span class="code">Scheduler </span>class to supervise executing jobs, and forward any unhandled exceptions to a single exception handling routine. All you need to do is registering a callback action to the <span class="code">JobExceptionHandler </span>of the <span class="code">Scheduler </span>class:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">private</span> Scheduler scheduler;

<span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> InitScheduler()
{
  scheduler = <span style="color: #0000ff">new</span> Scheduler();
  scheduler.JobExceptionHandler = LogJobException;
}

<span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> LogJobException(Job job, Exception exception)
{
  <span style="color: #0000ff">string</span> msg = <span style="color: #006080">&quot;Exception occurred while executing job {0}: {1}&quot;</span>;
  msg = String.Format(msg, job.JobId, exception.ToString());
  MyLogger.LogError(msg);
}</pre>
</div>
<p>&#160;</p>
<h2>Performance</h2>
<p>&#160;</p>
<p>The library could surely be tweaked, but it performs pretty well. Running 10000 jobs, each with an interval of 100 ms (that’s around 100 jobs per millisecond) keeps the CPU busy (at around 25% on my machine), but neither eats away your memory nor freezes the PC. Bigger intervals aren’t a problem at all because the scheduler is sleeping most of the time.</p>
<p>&#160;</p>
<h2>Reacting to System Time Change Events</h2>
<p>&#160;</p>
<p>Assume the following:</p>
<ul>
<li>The current time is 21:00, your job is scheduled to run at 22:00 </li>
<li>The user changes the computer’s time to 21:30 </li>
</ul>
<p>Now, depending on your needs, you might want the scheduler to adjust itself based on two strategies:</p>
<ul>
<li><font color="#ff0000">A</font>: If you want the job to run at a fixed time (22:00), you expect the job to run in 30 minutes. <em>This is the scheduler’s default behavior.</em> </li>
<li><font color="#ff0000">B</font>: If you want the job to run based on relative times, you still expect the job to run in an hour, so the execution time would have to be change to 22:30. </li>
</ul>
<p>In order not to miss such an event, the scheduler performs a quick self test with a fixed configurable interval from time to time &#8211; even if no jobs are up for execution. Per default, the scheduler’s <span class="code">SelfTestInterval</span> property is set to two minutes, but this can be configured should you need more (or less) accurate re-scheduling.</p>
<p>If you want the scheduler to just readjust its internal schedule and keep fixed times (<font color="#ff0000">A</font>), you don’t have to do anything. However, if you want the scheduler to reschedule its jobs if a system time change was detected (<font color="#ff0000">B</font>), you can do by setting the <span class="code">SystemTimeChangeRescheduling </span>property of the <span class="code">Scheduler </span>class, which takes an enum value of type <span class="code">ReschedulingStrategy</span>:</p>
<p>&#160;<img loading="lazy" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2010/01/image4.png" width="307" height="138" /> </p>
<p>As you can see, you can choose not to reschedule at all (default), only reschedule the next execution time (the next time the job runs), or even shift the expiration time of your jobs.</p>
<h4>Fixed vs. Relative Rescheduling Depending on Jobs</h4>
<p>What if you have a few jobs that should run on a fixed time, while others should be rescheduled?</p>
<p>I decided against making the API more complicated by allowing jobs to be individually configured. As an alternative, I’d suggest to just use two scheduler classes with individual configurations. You could even write a wrapper class that just maintains two schedulers, and forwards all job submissions to the correct one. Here’s a quick but working implementation:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> MyScheduler
{
  <span style="color: #0000ff">private</span> <span style="color: #0000ff">readonly</span> Scheduler fixedSchedules = <span style="color: #0000ff">new</span> Scheduler();
  <span style="color: #0000ff">private</span> <span style="color: #0000ff">readonly</span> Scheduler relativeSchedules = <span style="color: #0000ff">new</span> Scheduler();


  <span style="color: #0000ff">public</span> MyScheduler()
  {
    <span style="color: #008000">//configure relative rescheduling</span>
    var strategy = ReschedulingStrategy.RescheduleNextExecution;
    relativeSchedules.SystemTimeChangeRescheduling = strategy;
  }

  <span style="color: #008000">//This method just forwards submitted jobs to one of the schedulers</span>
  <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> SubmitJob(Job job, Action&lt;Job&gt; callback, <span style="color: #0000ff">bool</span> hasFixedSchedule)
  {
    <span style="color: #0000ff">if</span>(hasFixedSchedule)
    {
      fixedSchedules.SubmitJob(job, callback);
    }
    <span style="color: #0000ff">else</span>
    {
      relativeSchedules.SubmitJob(job, callback);
    }
  }
}</pre>
</div>
<p>&#160;</p>
<h2>Persisting Jobs</h2>
<p>&#160;</p>
<p>Persisting jobs is not part of the library, but could be done by subclassing the <span class="code">Scheduler </span>class. The class gives you protected access to all its internals, including its job list. <span class="code">Job </span>is a very simple component, so it should be fairly easy to store and reload all jobs.</p>
<p>However, from an architectural point of view, I’d probably not persist any jobs at all, but rather recreate them during initialization based on persisted business data. A job does execute in a given context, because of “something”. Let’s assume this “something” is a reminder flag in a calendar application:</p>
<ul>
<li>User sets a reminder on a calendar entry. </li>
<li>Calendar application updates database record of the calendar entry, then creates a job with the scheduler. </li>
<li>User turns off application – the scheduler and running jobs are being disposed. </li>
<li>User restarts application. </li>
<li>The application retrieves all reminders from the database and schedules jobs for them. </li>
</ul>
<p>This approach is simple, and clearly defines the responsibilities of the components in your application. It also minimizes dependencies on the scheduling system.</p>
<p>&#160;</p>
<h2>Implementation Notes</h2>
<p>&#160;</p>
</p>
<h3>Creating a Fluent Interface</h3>
<p>The library provides a fluent API that allows you to chain configuration settings:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">//job starts at a given start time, repeats until expiration time</span>
Job myJob = <span style="color: #0000ff">new</span> Job();
myJob.Run.From(startTime).Every.Seconds(1.5).Until(expiration);</pre>
</div>
<p>&#160;</p>
<p>The fluent API is optional – a job can also be configured via traditional properties setters. However, the corresponding declaration is more verbose:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">//job starts at a given start time, repeats until expiration time</span>
Job myJob = <span style="color: #0000ff">new</span> Job
              {
                Loops = <span style="color: #0000ff">null</span>,
                StartTime = startTime,
                Interval = TimeSpan.FromSeconds(1.5),
                ExpirationTime = expiration
              };</pre>
</div>
<p>&#160;</p>
<p>Basically, the implementation of the fluent API is very simple:</p>
<ul>
<li>The <span class="code">Run </span>property returns an instance of a helper class called <span class="code">JobSchedule</span>. This helper class provides methods such as <span class="code">From</span>, <span class="code">Until</span>, <span class="code">Every</span>, or <span class="code">Once</span>. </li>
<li>All methods of the <span class="code">JobSchedule </span>class have a return value of <span class="code">JobSchedule </span>again, which allows the developer to chain the operations as in the sample above. </li>
</ul>
<p>Below is a part of <span class="code">JobSchedule</span>’s implementation. You can see that the class receives an instance of type <span class="code">Job</span>, and just sets the properties on this class.</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> JobSchedule
{
  <span style="color: #0000ff">private</span> <span style="color: #0000ff">readonly</span> Job job;

  <span style="color: #008000">//created with the job that is being configured</span>
  <span style="color: #0000ff">public</span> JobSchedule(Job job)
  {
    <span style="color: #0000ff">this</span>.job = job;
  }


  <span style="color: #008000">//all operations just return the schedule itself again</span>
  <span style="color: #0000ff">public</span> JobSchedule From(DateTimeOffset startTime)
  {
    job.StartTime = startTime;
    <span style="color: #0000ff">return</span> <span style="color: #0000ff">this</span>;
  }

  ...

}</pre>
</div>
<p>&#160;</p>
<p>&#160;</p>
<h3>DateTime, DateTimeOffset, and SystemTime</h3>
<h4>SystemTime Pattern</h4>
<p>With a scheduler, everything is about time. However, time-related code is very hard to test, which is why the scheduler does not directly access the current system time, but makes use of <a href="http://ayende.com/Blog/archive/2008/07/07/Dealing-with-time-in-tests.aspx">Ayende’s SystemTime</a>. This is an awesome pattern, and I highly recommend using it whenever timestamps play an important role in code.</p>
<p>&#160;</p>
<h4>DateTimeOffset vs. DateTime</h4>
<p>You might have noticed that usually, the code works with <span class="code">DateTimeOffset </span>rather then the commonly known <span class="code">DateTime</span> struct. <span class="code">DateTimeOffset </span>is basically an alternative to <span class="code">DateTime</span>, but operates on UTC which makes it an ideal candidate for most time-related scenarios. You can read more about it at <a href="http://msdn.microsoft.com/en-us/library/system.datetimeoffset.aspx">MSDN</a> or at the <a href="http://blogs.msdn.com/bclteam/archive/2007/06/14/datetimeoffset-a-new-datetime-structure-in-net-3-5-justin-van-patten.aspx">BCL team blog</a>.</p>
<p>However, you can even still use <span class="code">DateTime </span>in your code if you feel more comfortable with it:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">Job job = <span style="color: #0000ff">new</span> Job();

DateTimeOffset expDate1 = DateTimeOffset.Now.AddHours(2);
DateTime       expDate2 = DateTime.Now.AddHours(2);

<span style="color: #008000">//the job takes both DateTimeOffset and DateTime values</span>
job.ExpirationTime = expDate1;
job.ExpirationTime = expDate2;</pre>
</div>
<p>&#160;</p>
<p>&#160;</p>
<h3>Job List, Timer and Pooled Execution</h3>
<h4>Job List</h4>
<p>Internally, the <span class="code">Scheduler </span>class uses a very simple mechanism: All jobs are being cached in a sorted list, which allows the scheduler to easily determine the next execution time. If a new job is being submitted, the scheduler only has to check whether the new job runs before the next scheduled job or not. If yes, the scheduler adjusts its next execution. If no, the job is just added to the end of the list, and a flag is set that reminds the scheduler to reorder the list once the next job was done. This approach has a big advantage: Even if many jobs are being submitted, reordering takes only place once the next job runs.</p>
<p>&#160;</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> SubmitJob(Job job, Action&lt;Job&gt; callback)
{
  <span style="color: #008000">//[validation omitted for brevity]</span>

  JobContext context = <span style="color: #0000ff">new</span> JobContext(job, callback);
  
  <span style="color: #0000ff">lock</span>(syncRoot)
  {
    <span style="color: #008000">//if this job is going to be the next one, we need to reconfigure</span>
    <span style="color: #008000">//the timer. Do not reschedule if the next execution is imminent</span>
    <span style="color: #0000ff">if</span> (NextExecution == <span style="color: #0000ff">null</span> || context.NextExecution &lt;= NextExecution.Value)
    {
      <span style="color: #008000">//insert at index 0 –&gt; makes sure the job runs first on next timer event</span>
      jobs.Insert(0, context);

      <span style="color: #008000">//only reschedule if the next execution is not imminent</span>
      <span style="color: #0000ff">if</span> (NextExecution == <span style="color: #0000ff">null</span> || NextExecution.Value.Subtract(SystemTime.Now())
                                                .TotalMilliseconds &gt; MinJobInterval)
      {
        <span style="color: #008000">//no sorting required, but we need to adjust the timer</span>
        Reschedule();
      }
    }
    <span style="color: #0000ff">else</span>
    {
      <span style="color: #008000">//add at end of the list and mark list as unsorted</span>
      <span style="color: #008000">//the job will be sorted and rescheduled on the next run (which is before</span>
      <span style="color: #008000">//this job's execution time)</span>
      jobs.Add(context);
      isSorted = <span style="color: #0000ff">false</span>;
    }
  }
}</pre>
</div>
<p>&#160;</p>
<p>&#160;</p>
<h4>Timer and Rescheduling</h4>
<p>In order to trigger the execution, a single <span class="code">Timer </span>is used to wake up the scheduler once jobs are due. The timer is set to one of those values:</p>
<ul>
<li>If the scheduler has no jobs at all, the timer is disabled. </li>
<li>If jobs are pending, the next interval is the execution time of the next pending job. </li>
<li>If the self test interval is lower than the execution time of the next job, the scheduler will run an evaluation at this time (which ensures that a changed system time does not cause the scheduler to oversleep). </li>
</ul>
<p>The whole timer logic is encapsulated in the <span class="code">Reschedule </span>method:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">/// &lt;summary&gt;</span>
<span style="color: #008000">/// Reconfigures the timer according to the</span>
<span style="color: #008000">/// next pending job execution time.</span>
<span style="color: #008000">/// &lt;/summary&gt;</span>
<span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> Reschedule()
{
  <span style="color: #0000ff">if</span>(jobs.Count == 0)
  {
    <span style="color: #008000">//disable the timer if we don't have any pending jobs</span>
    NextExecution = <span style="color: #0000ff">null</span>;
    timer.Change(Timeout.Infinite, Timeout.Infinite);
  }
  <span style="color: #0000ff">else</span>
  {
    <span style="color: #008000">//schedule next event</span>
    var executionTime = jobs[0].NextExecution;

    DateTimeOffset now = SystemTime.Now();
    TimeSpan delay = executionTime.Value.Subtract(now);

    <span style="color: #008000">//in case the next execution is already pending, add a safe delay</span>
    <span style="color: #0000ff">long</span> dueTime = Math.Max(MinJobInterval, (<span style="color: #0000ff">long</span>)delay.TotalMilliseconds);

    <span style="color: #008000">//run at least with the self testing interval</span>
    dueTime = Math.Min(dueTime, SelfTestInterval);

    NextExecution = SystemTime.Now().AddMilliseconds(dueTime);
    timer.Change(dueTime, Timeout.Infinite);
  }
}</pre>
</div>
<p>&#160;</p>
<h4>Job Execution</h4>
<p>“Executing” a job basically means invoking the callback action that was submitted along with the job. This always happens asynchronously through the .NET thread pool:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">/// &lt;summary&gt;</span>
<span style="color: #008000">/// Invokes the managed job's &lt;see cref=&quot;CallbackAction&quot;/&gt; through</span>
<span style="color: #008000">/// the thread pool, and updates the job's internal state.</span>
<span style="color: #008000">/// &lt;/summary&gt;</span>
<span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> ExecuteAsync()
{
  <span style="color: #008000">//only execute if the job is active</span>
  <span style="color: #0000ff">if</span> (...)
  {
    ThreadPool.QueueUserWorkItem(s =&gt; CallbackAction(ManagedJob));
  }

  UpdateState();
}</pre>
</div>
<p>&#160;</p>
<h2>Conclusion</h2>
<p>&#160;</p>
<p>This is a neat little helper library, and its small footprint makes it a viable alternative to handling timers yourself even for small applications. Happy coding <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2010/01/lightweight-task-slash-job-scheduling-with-silverlight-support/feed</wfw:commentRss>
			<slash:comments>35</slash:comments>
		
		
			</item>
		<item>
		<title>Announcing VFS, the Virtual File System</title>
		<link>http://www.hardcodet.net/2009/12/vfs-virtual-file-system-announcement</link>
					<comments>http://www.hardcodet.net/2009/12/vfs-virtual-file-system-announcement#comments</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Tue, 29 Dec 2009 10:00:52 +0000</pubDate>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[VFS]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/2009/12/vfs-virtual-file-system-announcement</guid>

					<description><![CDATA[I’ve been working on a new project of mine for a while now, and opened the project at CodePlex: VFS, the Virtual File System, is basically an abstraction to arbitrary hierarchical resources, which can be handled like a file system. VFS comes with a set of file system providers and clients (including Silverlight support), and [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I’ve been working on a new project of mine for a while now, and opened the project at CodePlex: <a title="VFS Project Home" href="http://vfs.codeplex.com">VFS</a>, the Virtual File System, is basically an abstraction to arbitrary hierarchical resources, which can be handled like a file system.</p>
<p>VFS comes with a set of file system providers and clients (including Silverlight support), and allows you to easily write your own providers (e.g. to expose the contents of a ZIP file on a remote server). Additional offerings are flexible security (e.g. to access your Azure blobs via VFS in order to plug-in a custom authorization scheme), auditing and reliable file transfers.</p>
<p>VFS is currently in early Alpha, but I’m working full steam ahead. Comments and wish lists are appreciated! For a more detailed introduction and a few code snippets, visit the project home:   <br /><a href="http://vfs.codeplex.com">http://vfs.codeplex.com</a></p>
<p>&#160;</p>
</p>
<p><a href="http://blog.hardcodet.net/wp-content/uploads/2009/12/vfs-provider-model.png"><img loading="lazy" style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="vfs_provider_model" border="0" alt="vfs_provider_model" src="http://blog.hardcodet.net/wp-content/uploads/2009/12/vfs-provider-model-thumb.png" width="552" height="307" /></a></p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2009/12/vfs-virtual-file-system-announcement/feed</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title>Convert WCF Service Exceptions into Faults using Lambdas</title>
		<link>http://www.hardcodet.net/2009/12/convert-service-exceptions-to-wcf-faults</link>
					<comments>http://www.hardcodet.net/2009/12/convert-service-exceptions-to-wcf-faults#comments</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Tue, 08 Dec 2009 14:25:02 +0000</pubDate>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[WCF]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/2009/12/convert-service-exceptions-to-wcf-faults</guid>

					<description><![CDATA[Shows a simple pattern that simplifies exception handling and the creation of FaultExceptions on WCF service methods.]]></description>
										<content:encoded><![CDATA[<p>Interoperability in WCF is a great thing, but it requires us to rethink our exception handling strategy: The simple paradigm of throwing exceptions whenever something goes wrong doesn’t cut it with distributed systems.</p>
<p>Thankfully, WCF allows us to communicate errors (or <em>faults</em>) through <a href="http://msdn.microsoft.com/en-us/library/cc304769.aspx" target="_blank">FaultExceptions</a>. We can just convert internal exceptions into a FaultException, and WCF will take care about everything else. However: This conversion strategy is tedious and error prone, especially if you want to do more sophisticated exception handling. Even a simplified example as the one below mainly consists of exception handling code:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">//Simplified example</span>
<span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> Foo(<span style="color: #0000ff">string</span> userName)
{
  <span style="color: #0000ff">try</span>
  {
     Bar.FooBar(userName);
  }
  <span style="color: #0000ff">catch</span>(ArgumentException e)
  {
    <span style="color: #008000">//convert exception into a WCF friendly FaultException</span>
    <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> FaultException(<span style="color: #006080">&quot;Info about specific error&quot;</span>);
  }
  <span style="color: #0000ff">catch</span>(Exception e)
  {
    <span style="color: #008000">//convert exception into a WCF friendly FaultException</span>
    <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> FaultException(<span style="color: #006080">&quot;Info about unspecific error&quot;</span>);
  }
}</pre>
</div>
<p>&#160;</p>
<p>I’m currently finding myself having to write a set of WCF services, and I didn’t want to go through try/catch blocks all the time just in order to wrap up the same exceptions over and over again. Accordingly, I wrote helper methods that do the exception handling for me.</p>
<ul>
<li><span class="code">SecureAction</span> is used by service methods that do not have a return value. </li>
<li><span class="code">SecureFunc&lt;T&gt;</span> is used by service methods that do have a return value. </li>
</ul>
<p>These helper methods allow me to easily delegate the exception handling from all my service methods, and if anything goes wrong, I can trust that the internal exception is safely converted into a <span class="code">FaultException</span>. Here’s is the rewritten <span class="code">Foo </span>method from above, now remarkably smaller:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> Foo(<span style="color: #0000ff">string</span> userName)
{
  <span style="color: #0000ff">return</span> SecureFunc(() =&gt; Bar.FooBar(userName));
}</pre>
</div>
<p>&#160;</p>
<p>Below is the (simplified) snippet with the helper methods. <strong>Do note that the above sample methods are just starting points.</strong> My productive helper methods provide a more sophisticated exception handling than shown above (they build detailed <em>FaultContracts</em> which are specific to my application) and come with a few overloads.</p>
<p>Furthermore, you might think about adding additional parameters to your helper methods (such as fault IDs) in order to customize the generated faults.</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> SecureAction(Action action)
{
  <span style="color: #0000ff">try</span>
  {
    action();
  }
  <span style="color: #0000ff">catch</span> (Exception e)
  {
    <span style="color: #008000">//productive code provides more specific</span>
    <span style="color: #008000">//exception handling, but you should get the idea...</span>
    <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> FaultException(e.Message);
  }
}

<span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> T SecureFunc&lt;T&gt;(Func&lt;T&gt; func)
{
  <span style="color: #0000ff">try</span>
  {
    <span style="color: #0000ff">return</span> func();
  }
  <span style="color: #0000ff">catch</span> (Exception e)
  {
    <span style="color: #008000">//productive code provides more specific</span>
    <span style="color: #008000">//exception handling, but you should get the idea...</span>
    <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> FaultException(e.Message);
  }
}</pre>
</div>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2009/12/convert-service-exceptions-to-wcf-faults/feed</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>NetDrives 1.0.2 Released</title>
		<link>http://www.hardcodet.net/2009/12/httpwwwhardcodetnet200909netdrives-update-102</link>
					<comments>http://www.hardcodet.net/2009/12/httpwwwhardcodetnet200909netdrives-update-102#respond</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Mon, 07 Dec 2009 17:09:21 +0000</pubDate>
				<category><![CDATA[NetDrives]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[WPF]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/2009/12/httpwwwhardcodetnet200909netdrives-update-102</guid>

					<description><![CDATA[I just released a minor update for NetDrives, which fixes an issue that caused settings not to be persisted correctly. NetDrives is a Windows utility that helps you manage your network shares and mapped network drives. &#160; &#160; Download and further infos: http://www.hardcodet.net/netdrives]]></description>
										<content:encoded><![CDATA[<p>I just released a minor update for NetDrives, which fixes an issue that caused settings not to be persisted correctly. NetDrives is a Windows utility that helps you manage your network shares and mapped network drives.</p>
<p>&#160;</p>
<p><img loading="lazy" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="NetDrives" border="0" alt="NetDrives" src="http://blog.hardcodet.net/wp-content/uploads/2009/12/notifyiconwin7.png" width="324" height="156" /> </p>
<p>&#160;</p>
<p>Download and further infos: <a href="http://www.hardcodet.net/netdrives">http://www.hardcodet.net/netdrives</a></p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2009/12/httpwwwhardcodetnet200909netdrives-update-102/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>SLF Hands-on Tutorial, Part 1</title>
		<link>http://www.hardcodet.net/2009/12/slf-tutorial-1</link>
					<comments>http://www.hardcodet.net/2009/12/slf-tutorial-1#comments</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Wed, 02 Dec 2009 14:43:00 +0000</pubDate>
				<category><![CDATA[SLF]]></category>
		<category><![CDATA[Logging]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/?p=664</guid>

					<description><![CDATA[Hands-on tutorial for SLF, the Simple Logging Façade.]]></description>
										<content:encoded><![CDATA[<p>&#160;<img loading="lazy" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="slf" border="0" alt="slf" src="http://blog.hardcodet.net/wp-content/uploads/2009/10/slf-thumb.png" width="450" height="55" />&#160;</p>
<p>This is an introductory tutorial on SLF, the Simple Logging Façade. This tutorial covers the basics, which will be all you’ll ever need in most projects. I’m planning on writing a second tutorial that will show custom factories and resolvers soon.</p>
<h2>Downloading SLF</h2>
<p>To get started, visit <a href="http://slf.codeplex.com">http://slf.codeplex.com</a> and download the latest release. Source code is available as a Visual Studio 2008 solution, but if you’re working with VS2005, there’s also precompiled binaries for .NET 2.0 available (.NET 1.0 or 1.1 is not supported).</p>
<h3>Sample Projects</h3>
<p>SLF comes with a lot of samples, all organized as independent projects that discuss a specific use case. As you will see, most scenarios only require a few lines of code. We are planning to extend this section over time, based on your feedback.</p>
<p>&#160;</p>
<p><a href="http://blog.hardcodet.net/wp-content/uploads/2009/10/image.png"><img loading="lazy" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2009/10/image-thumb.png" width="242" height="322" /></a></p>
<p>&#160;</p>
</p>
<p> <span id="more-664"></span>  </p>
<h2>ILogger</h2>
<p>The central interface in SLF is <span class="code">ILogger</span>. <span class="code">ILogger</span> provides a versatile API to log information to a specific logging framework. You could roughly say there’s three “categories” of loggers:</p>
<ol>
<li>A few simple implementations directly in the SLF core library (e.g. <span class="code">ConsoleLogger </span>or <span class="code">DelegateLogger</span>) that cover common scenarios. </li>
<li>Façades for logging frameworks that are currently supported (e.g. <a href="http://logging.apache.org/log4net/index.html">log4net</a>). A façade is usually an independent DLL. </li>
<li>Custom loggers that you implement yourself. You can do that very easily, usually by extending a simple base class. Creating fancy custom loggers will be covered in the second part of this tutorial. </li>
</ol>
<p><a href="http://blog.hardcodet.net/wp-content/uploads/2009/12/image.png"><img loading="lazy" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2009/12/image-thumb.png" width="259" height="260" /></a> </p>
<p>&#160;</p>
<p>Here’s a first snippet, that creates a <span class="code">ConsoleLogger</span>, which is part of the core library:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">ILogger logger = <span style="color: #0000ff">new</span> ConsoleLogger(); 
logger.Info(<span style="color: #006080">&quot;hello world&quot;</span>);</pre>
</div>
<p>&#160;</p>
<p>This produces the following output</p>
<p><a href="http://blog.hardcodet.net/wp-content/uploads/2009/10/image1.png"><img loading="lazy" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2009/10/image-thumb1.png" width="307" height="164" /></a></p>
<p>&#160;</p>
<p>However, rather than creating your loggers all over the place, you will usually use <span class="code">LoggerService </span>to obtain your logger(s):</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">ILogger logger = LoggerService.GetLogger(); 
logger.Info(<span style="color: #006080">&quot;hello world&quot;</span>);</pre>
</div>
<p>&#160;</p>
<p>Setting up logging with LoggerService is described in a bit further below.</p>
<h3>&#160;</h3>
<h4>Logging in Categories</h4>
<p><em>As a general guideline on how and when to use logging categories, I recommend Colin Eberhardt’s “<a title="The Art of Logging" href="http://www.codeproject.com/KB/trace/ArtOfLogging.aspx">The Art of Logging</a>”, which is an excellent introduction to logging in general.</em></p>
<p>SLF knows 5 logging categories (or log levels), which are covered through a set of methods that allow you to easily submit logging information.&#160; </p>
<table border="1" cellspacing="0" cellpadding="2" width="400">
<tbody>
<tr>
<td valign="top" width="200"><strong>Logging Level</strong></td>
<td valign="top" width="200"><strong>ILogger Methods</strong></td>
</tr>
<tr>
<td valign="top" width="200">Info</td>
<td valign="top" width="200">Info()</td>
</tr>
<tr>
<td valign="top" width="200">Warn</td>
<td valign="top" width="200">Warn()</td>
</tr>
<tr>
<td valign="top" width="200">Error</td>
<td valign="top" width="200">Error()</td>
</tr>
<tr>
<td valign="top" width="200">Fatal</td>
<td valign="top" width="200">Fatal()</td>
</tr>
<tr>
<td valign="top" width="200">Debug</td>
<td valign="top" width="200">Debug()</td>
</tr>
</tbody>
</table>
<p>Every one of these methods provides several overloads, which allow you to submit simple text, exceptions, or even format text on the fly. A few exemplary logging instructions:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">ILogger logger = <span style="color: #0000ff">new</span> ConsoleLogger();

logger.Info(<span style="color: #006080">&quot;Simple Message.&quot;</span>); 
logger.Info(<span style="color: #006080">&quot;User {0} logged in at {1}&quot;</span>, GetUserName(), DateTime.Now); 
logger.Warn(e, <span style="color: #006080">&quot;Message for uncritical exception.&quot;</span>); 
logger.Error(someException); 
logger.Fatal(e, <span style="color: #006080">&quot;Login exception for user {0}&quot;</span>, GetUserName());</pre>
</div>
<p>&#160;</p>
<h4>Logging a LogItem</h4>
<p>Apart from the the above mentioned <span class="code">Info()</span>, <span class="code">Warn()</span>, <span class="code">Error()</span>, <span class="code">Fatal() </span>and <span class="code">Debug()</span> methods, there’s also the <span class="code">Log </span>method, which expects an parameter of type <span class="code">LogItem</span>. <span class="code">LogItem</span> is a simple class that encapsulates information that belongs to a given log entry:</p>
<p>&#160;</p>
<p><a href="http://blog.hardcodet.net/wp-content/uploads/2009/12/image1.png"><img loading="lazy" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2009/12/image-thumb1.png" width="215" height="240" /></a> </p>
<p>&#160;</p>
<p>Working with <span class="code">LogItem</span> is not as straightforward as using the other methods, but it may be useful if you want to submit more detailed logging information. Here’s a sample that logs a warning along with an event ID:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> Login(User user) 
{ 
   <span style="color: #008000">//do the login </span>
   LoginResult result = ...


   <span style="color: #008000">//log an Info message with a title and an event ID </span>
   LogItem item = <span style="color: #0000ff">new</span> LogItem(); 
   item.LogLevel = LogLevel.Warn; 
   item.EventId = 201; 
   item.Title = <span style="color: #006080">&quot;Invalid login attempted by: &quot;</span> + user.Name; 
   item.Message = result.ToDetailedString(); 
    
   ILogger logger = ...
   logger.Log(item); 
}</pre>
</div>
<p>&#160;</p>
<p>&#160;</p>
<h2>Setting up Logging in Code</h2>
<p>&#160;</p>
<h3>Do it Yourself: Storing a Reference to ILogger</h3>
<p>Basically, the simplest possible implementation to use SLF is to just store an <span class="code">ILogger</span> instance somewhere and be on your way. The sample below uses the BitFactory logger façade, which internally forwards log messages to the <a href="http://dotnetlog.theobjectguy.com/">BitFactory</a> logging framework:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">class</span> MyApplication 
{
  <span style="color: #008000">//there’s a static convenience method that creates a logger for a given file </span>
  <span style="color: #0000ff">private</span> ILogger logger = BitFactoryLogger.CreateFileLogger(<span style="color: #006080">&quot;log.txt&quot;</span>);

  <span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> ILogger Logger 
  { 
    get { <span style="color: #0000ff">return</span> logger; }    
  }
}</pre>
</div>
<p>&#160;</p>
<p><em>However, we recommend to use <span class="code">LoggerService</span> instead:</em></p>
<h3>LoggerService</h3>
<p><span class="code">LoggerService </span>is a static repository you can use in different ways. It provides support for declarative configurations (taken from app.config), lets you just plug in a single logger, or completely customize and plug in advanced logger resolution strategies.</p>
<p>Lets have a look at a simplistic example: Create the above <span class="code">ConsoleLogger </span>and make it available through <span class="code">LoggerService</span>. Again, this is as simple as it gets:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">ILogger logger = <span style="color: #0000ff">new</span> ConsoleLogger(); 
LoggerService.SetLogger(logger);</pre>
</div>
<p>&#160;</p>
<p>With a logger plugged in like this, we can use <span class="code">LoggerService </span>from anywhere in our application to get a hold of the <span class="code">ConsoleLogger </span>we just plugged in:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">ILogger logger = LoggerService.GetLogger(); 
logger.Info(<span style="color: #006080">&quot;hello world&quot;</span>);</pre>
</div>
<p>&#160;</p>
<h4>Good to Know: LoggerService Never Returns Null </h4>
<p><span class="code">LoggerService </span>guarantees you to <em>always</em> return a valid <span class="code">ILogger</span> instance. If no logger is configured, it will just return you a <span class="code">NullLogger </span>instance. <span class="code">NullLogger </span>is a special implementation of the <span class="code">ILogger </span>interface, which just discards everything you throw at it. You could say that <span class="code">NullLogger </span>switches off logging without requiring any changes in your code.</p>
<p>&#160;</p>
<p>Thanks to <span class="code">NullLogger</span>, you never have to check for null references when retrieving a logger. Look at the snippet below: This code will not result in an exception, because <span class="code">GetLogger </span>will not return null, but a <span class="code">NullLogger </span>instance:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">//you can explicitly assign a null reference… </span>
LoggerService.SetLogger(<span style="color: #0000ff">null</span>); 

<span style="color: #008000">//…and the service will return you a NullLogger </span>
ILogger logger = LoggerService.GetLogger();

<span style="color: #008000">//NullLogger will just discard this message, so no real logging happens</span>
logger.Info(<span style="color: #006080">&quot;This message will be discarded&quot;</span>); </pre>
</div>
<p>&#160;</p>
<h2>Setting up Logging Declaratively (App.config)</h2>
<p>Per default, <span class="code">LoggerService </span>analyzes the application’s configuration file (<em>app.config</em>) in order to detect configured loggers. So if you want to go the declarative route, you don’t have to write a single line of code – it just works.</p>
<p>Here’s a sample <em>app.config</em> file that makes SLF write anything to the console through a <span class="code">ConsoleLogger</span>:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">&lt;?</span><span style="color: #800000">xml</span> <span style="color: #ff0000">version</span><span style="color: #0000ff">=&quot;1.0&quot;</span> <span style="color: #ff0000">encoding</span><span style="color: #0000ff">=&quot;utf-8&quot;</span> ?<span style="color: #0000ff">&gt;</span>
<span style="color: #0000ff">&lt;</span><span style="color: #800000">configuration</span><span style="color: #0000ff">&gt;</span>
  <span style="color: #0000ff">&lt;</span><span style="color: #800000">configSections</span><span style="color: #0000ff">&gt;</span>
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">section</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;slf&quot;</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;Slf.Config.SlfConfigurationSection, slf&quot;</span><span style="color: #0000ff">/&gt;</span>
  <span style="color: #0000ff">&lt;/</span><span style="color: #800000">configSections</span><span style="color: #0000ff">&gt;</span>

  <span style="color: #0000ff">&lt;</span><span style="color: #800000">slf</span><span style="color: #0000ff">&gt;</span>
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">factories</span><span style="color: #0000ff">&gt;</span>
      <span style="color: #008000">&lt;!-- log everything through the built-in ConsoleLogger --&gt;</span>
      <span style="color: #0000ff">&lt;</span><span style="color: #800000">factory</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;Slf.Factories.ConsoleLoggerFactory, SLF&quot;</span> <span style="color: #0000ff">/&gt;</span>
    <span style="color: #0000ff">&lt;/</span><span style="color: #800000">factories</span><span style="color: #0000ff">&gt;</span>
  <span style="color: #0000ff">&lt;/</span><span style="color: #800000">slf</span><span style="color: #0000ff">&gt;</span>

<span style="color: #0000ff">&lt;/</span><span style="color: #800000">configuration</span><span style="color: #0000ff">&gt;</span></pre>
</div>
<p>&#160;</p>
<p>Declarative configurations often make sense in more complex scenarios, especially if you use more powerful logging frameworks such as <a href="http://logging.apache.org/log4net/index.html">log4net</a>. Here’s a complete configuration file that makes SLF use log4net. This <em>app.config</em> file contains two sections:</p>
<ul>
<li>The <em>slf</em> section tells SLF to forward all logging data to log4net. </li>
<li>The <em>log4net</em> section is a standard log4net configuration (it has nothing to do with SLF). In this example, log4net is configured to write everything into a single log file. </li>
</ul>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">&lt;?</span><span style="color: #800000">xml</span> <span style="color: #ff0000">version</span><span style="color: #0000ff">=&quot;1.0&quot;</span> <span style="color: #ff0000">encoding</span><span style="color: #0000ff">=&quot;utf-8&quot;</span> ?<span style="color: #0000ff">&gt;</span>
<span style="color: #0000ff">&lt;</span><span style="color: #800000">configuration</span><span style="color: #0000ff">&gt;</span>
  <span style="color: #0000ff">&lt;</span><span style="color: #800000">configSections</span><span style="color: #0000ff">&gt;</span>
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">section</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;log4net&quot;</span>
             <span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;log4net.Config.Log4NetConfigurationSectionHandler,log4net&quot;</span><span style="color: #0000ff">/&gt;</span>
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">section</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;slf&quot;</span>
             <span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;Slf.Config.SlfConfigurationSection, slf&quot;</span><span style="color: #0000ff">/&gt;</span>
  <span style="color: #0000ff">&lt;/</span><span style="color: #800000">configSections</span><span style="color: #0000ff">&gt;</span>

  <span style="color: #0000ff">&lt;</span><span style="color: #800000">slf</span><span style="color: #0000ff">&gt;</span>
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">factories</span><span style="color: #0000ff">&gt;</span>
      <span style="color: #008000">&lt;!-- configure single log4net factory, which will get all logging output --&gt;</span>
      <span style="color: #0000ff">&lt;</span><span style="color: #800000">factory</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;SLF.Log4netFacade.Log4netLoggerFactory, SLF.Log4netFacade&quot;</span><span style="color: #0000ff">/&gt;</span>
    <span style="color: #0000ff">&lt;/</span><span style="color: #800000">factories</span><span style="color: #0000ff">&gt;</span>
  <span style="color: #0000ff">&lt;/</span><span style="color: #800000">slf</span><span style="color: #0000ff">&gt;</span>


  <span style="color: #008000">&lt;!-- configures log4net to write into a local file called &quot;log.txt&quot; --&gt;</span>
  <span style="color: #0000ff">&lt;</span><span style="color: #800000">log4net</span><span style="color: #0000ff">&gt;</span>
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">appender</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;MainAppender&quot;</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;log4net.Appender.FileAppender&quot;</span><span style="color: #0000ff">&gt;</span>
      <span style="color: #0000ff">&lt;</span><span style="color: #800000">param</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;File&quot;</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">=&quot;log.txt&quot;</span> <span style="color: #0000ff">/&gt;</span>
      <span style="color: #0000ff">&lt;</span><span style="color: #800000">param</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;AppendToFile&quot;</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">=&quot;true&quot;</span> <span style="color: #0000ff">/&gt;</span>
      <span style="color: #0000ff">&lt;</span><span style="color: #800000">layout</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;log4net.Layout.PatternLayout&quot;</span><span style="color: #0000ff">&gt;</span>
        <span style="color: #0000ff">&lt;</span><span style="color: #800000">conversionPattern</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">=&quot;%date - %message %newline&quot;</span> <span style="color: #0000ff">/&gt;</span>
      <span style="color: #0000ff">&lt;/</span><span style="color: #800000">layout</span><span style="color: #0000ff">&gt;</span>
    <span style="color: #0000ff">&lt;/</span><span style="color: #800000">appender</span><span style="color: #0000ff">&gt;</span>
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">root</span><span style="color: #0000ff">&gt;</span>
      <span style="color: #0000ff">&lt;</span><span style="color: #800000">level</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">=&quot;ALL&quot;</span> <span style="color: #0000ff">/&gt;</span>
      <span style="color: #0000ff">&lt;</span><span style="color: #800000">appender-ref</span> <span style="color: #ff0000">ref</span><span style="color: #0000ff">=&quot;MainAppender&quot;</span> <span style="color: #0000ff">/&gt;</span>
    <span style="color: #0000ff">&lt;/</span><span style="color: #800000">root</span><span style="color: #0000ff">&gt;</span>
  <span style="color: #0000ff">&lt;/</span><span style="color: #800000">log4net</span><span style="color: #0000ff">&gt;</span>

<span style="color: #0000ff">&lt;/</span><span style="color: #800000">configuration</span><span style="color: #0000ff">&gt;</span></pre>
</div>
<p>&#160;</p>
<p>If you configure SLF through <em>app.config</em>, you don’t have to write any code, because SLF will detect the configuration on its own. Accordingly, just get the logger through <span class="code">LoggerService </span>and log away:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">ILogger logger = LoggerService.GetLogger(); 
logger.Info(<span style="color: #006080">&quot;Application started at {0}&quot;</span>, DateTime.Now);</pre>
</div>
<p>&#160;</p>
<p><em>Do note that if you plug in a custom logger through <span class="code">LoggerService.SetLogger</span>, this will override any declaratively configured loggers. You can, however, always reset <span class="code">LoggerService </span>through the <span class="code">LoggerService.Reset </span>method.</em></p>
<p>&#160;</p>
<h2>Working With Loggers and Façades</h2>
<p>&#160;</p>
<h3>Using the Built-in Loggers</h3>
<p>SLF comes with a number of built-in loggers that implement <span class="code">ILogger</span>, which you can use to quickly add logging functionality to your application. There’s the usual suspects such as <span class="code">ConsoleLogger</span>, <span class="code">DebugLogger</span>, or <span class="code">TraceLogger</span>, as well as a few more fancy implementations (e.g. <span class="code">DelegateLogger </span>or <span class="code">DecoratorLogger</span>) and base classes you can use to quickly create your own logger implementations.</p>
<p>There’s a lot of samples that demonstrate the loggers and possibilities, all wrapped into individual projects. However, here’s a few samples:</p>
<p>&#160;</p>
<h4>Delegating Logging through DelegateLogger</h4>
<p><span class="code">DelegateLogger </span>is a simple logger that allows you to quickly plug in some custom logic through a delegate or lambda expression. Here’s dummy sample for a WinForms application, which just shows a message box for every item that is logged to SLF.</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">DelegateLogger logger = <span style="color: #0000ff">new</span> DelegateLogger(ShowMessage); 

<span style="color: #008000">//this message is being invoked by the logger </span>
<span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> ShowMessage(LogItem item) 
{ 
  MessageBox.Show(<span style="color: #006080">&quot;Logged Message: &quot;</span> + item.Message);
}</pre>
</div>
<p>&#160;</p>
<p>…or even shorter, with a Lambda Expression:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">var logger = <span style="color: #0000ff">new</span> DelegateLogger(item =&gt; MessageBox.Show(item.Message));</pre>
</div>
<p>&#160;</p>
<p>&#160;</p>
<h4>Combining Logged Output via CompositeLogger</h4>
<p><span class="code">CompositeLogger </span>is a logger that does not log on its own, but forwards all logging information to an arbitrary number of other loggers:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">CompositeLogger compositeLogger = <span style="color: #0000ff">new</span> CompositeLogger();

compositeLogger.Loggers.Add(<span style="color: #0000ff">new</span> ConsoleLogger); 
compositeLogger.Loggers.Add(<span style="color: #0000ff">new</span> TraceLogger); 
compositeLogger.Loggers.Add(<span style="color: #0000ff">new</span> DebugLogger);

compositeLogger.Info(<span style="color: #006080">&quot;Logging to all three loggers at once!&quot;</span>);</pre>
</div>
<p>&#160;</p>
<p>You can also submit the underlying loggers directly as constructor parameters:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">ILogger consoleLogger = <span style="color: #0000ff">new</span> ConsoleLogger(); 
ILogger traceLogger = <span style="color: #0000ff">new</span> TraceLogger(); 
ILogger debugLogger = <span style="color: #0000ff">new</span> DebugLogger();

ILogger composite = <span style="color: #0000ff">new</span> CompositeLogger(consoleLogger, traceLogger, debugLogger);</pre>
</div>
<p>&#160;</p>
<p>&#160;</p>
<h3>Formatting Logging Output</h3>
<p>The first snippet in this tutorial wrote “hello world” to the console, which looked like this:</p>
<p><a href="http://blog.hardcodet.net/wp-content/uploads/2009/10/image1.png"><img loading="lazy" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2009/10/image-thumb1.png" width="307" height="164" /></a></p>
<p>Now, a lot of loggers derive from <span class="code">FormattableLoggerBase.</span> This base class provides a <span class="code">Formatter </span>property, which takes an instance of <span class="code">ILogItemFormatter</span>. <span class="code">ILogItemFormatter </span>is a very simple interface, which has only one task: Converting a given <span class="code">LogItem </span>into a string.</p>
<p>Accordingly, if you wanted to change the format of the above message, you could just write a custom formatter and assign it to your logger. Here’s an alternative for a simple <span class="code">XmlFormatter</span>:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> XmlFormatter : ILogItemFormatter
{
  <span style="color: #0000ff">private</span> XmlSerializer serializer = <span style="color: #0000ff">new</span> XmlSerializer(<span style="color: #0000ff">typeof</span>(LogItem));

  <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> FormatItem(LogItem item)
  {
    StringWriter writer = <span style="color: #0000ff">new</span> StringWriter();
    serializer.Serialize(writer, item);
    <span style="color: #0000ff">return</span> writer.ToString();
  }
}</pre>
</div>
<p>&#160;</p>
<p>Accordingly, we can plug in this formatter into our <span class="code">ConsoleLogger </span>like this:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">IFormattableLogger logger = <span style="color: #0000ff">new</span> ConsoleLogger(); 
logger.Formatter = <span style="color: #0000ff">new</span> XmlFormatter(); 
logger.Info(<span style="color: #006080">&quot;hello world&quot;</span>);</pre>
</div>
<p>&#160;</p>
<p>The above snippet produces the following output, that renders a <span class="code">LogItem </span>as an XML element:</p>
<p><a href="http://blog.hardcodet.net/wp-content/uploads/2009/10/image4.png"><img loading="lazy" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2009/10/image-thumb4.png" width="473" height="186" /></a></p>
<p>&#160;</p>
<h3>Directing Trace Output To SLF</h3>
<p>If you have an existing codebase that logs through the <span class="code">Trace </span>class, and you would like to make use of SLF, you don’t necessarily have to change the existing code. The SLF core library contains the <span class="code">SlfTraceListener </span>class which just redirects trace messages to SLF.</p>
<p>SLF comes with a sample that shows how to declare <span class="code">SlfTraceListener </span>declaratively via <em>app.config</em>. But you can do this also programmatically:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> Main(<span style="color: #0000ff">string</span>[] args) 
{ 
  <span style="color: #008000">//add SLF listener to Trace </span>
  Trace.Listeners.Add(<span style="color: #0000ff">new</span> SlfTraceListener()); 

  <span style="color: #008000">//write to Trace – this message will be redirected to SLF </span>
  Trace.WriteLine(<span style="color: #006080">&quot;We are writing to Trace.&quot;</span>); 
}</pre>
</div>
<p>&#160;</p>
<p>&#160;</p>
<h3>Your own Logger: Extending the Logger Base Classes</h3>
<p>If you want to create your own <span class="code">ILogger</span> implementation, you can either create a new class that implements <span class="code">ILogger</span>, or extend either <span class="code">LoggerBase </span>or <span class="code">FormattableLoggerBase</span>.</p>
<p><span class="code">ILogger</span> is not a complex interface, but there’s a lot of boilerplate code to implement. So in most cases, it’s probably more convenient to extend one of the base classes. Both require you to override just one method:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> MyCustomLogger : LoggerBase 
{ 
  <span style="color: #0000ff">public</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> Log(LogItem item) 
  { 
     <span style="color: #008000">//your implementation goes here </span>
  } 
}</pre>
</div>
<p>&#160;</p>
<p>&#160;</p>
<h4>Sample: Implementing a ColoredConsoleLogger</h4>
<p>The class below is a custom console logger which writes colored output to the console, depending on the <span class="code">LogLevel</span> of the logged item. The class derives from <span class="code">FormattableLoggerBase </span>in order to allow you to plug in a custom message formatter.</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> ColoredConsoleLogger : FormattableLoggerBase
{
  <span style="color: #0000ff">public</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> Log(LogItem item)
  {
    <span style="color: #008000">//set console color depending on log level</span>
    <span style="color: #0000ff">switch</span> (item.LogLevel)
    {
      <span style="color: #0000ff">case</span> LogLevel.Info:
        Console.ForegroundColor = ConsoleColor.Green;
        <span style="color: #0000ff">break</span>;
      <span style="color: #0000ff">case</span> LogLevel.Warn:
        Console.ForegroundColor = ConsoleColor.Cyan;
        <span style="color: #0000ff">break</span>;
      <span style="color: #0000ff">case</span> LogLevel.Error:
        Console.ForegroundColor = ConsoleColor.Yellow;
        <span style="color: #0000ff">break</span>;
      <span style="color: #0000ff">case</span> LogLevel.Fatal:
        Console.ForegroundColor = ConsoleColor.Red;
        <span style="color: #0000ff">break</span>;
      <span style="color: #0000ff">default</span>:
        Console.ResetColor();
        <span style="color: #0000ff">break</span>;
    }

    <span style="color: #008000">//delegate string formatting to base class </span>
    <span style="color: #0000ff">string</span> text = FormatItem(item);

    <span style="color: #008000">//write the string to the console </span>
    Console.Out.WriteLine(text);
    Console.ResetColor();
  }
}</pre>
</div>
<p>&#160;</p>
<p>If you log through this <span class="code">ColoredConsoleLogger</span>, a logged <span class="code">Info </span>is displayed in green now:</p>
<p><a href="http://blog.hardcodet.net/wp-content/uploads/2009/10/image5.png"><img loading="lazy" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2009/10/image-thumb5.png" width="241" height="152" /></a></p>
<p>&#160;</p>
<h3>Working with Available SLF Façade Libraries</h3>
<p>SLF comes with a few façade libraries you can use to forward to a given logging frameworks. Currently, there is support for the following commonly known frameworks:</p>
<ul>
<li>log4net </li>
<li>NLog </li>
<li>Enterprise Library </li>
<li>BitFactory Framework </li>
</ul>
<p>…and if you would like to use SLF along with a framework that is not listed yet, writing your own façade is pretty easy!</p>
<p>We’ve provided samples and sample configurations for all these façades. Accordingly, you can just find the sample that suits you, and copy/paste the configuration code into your application.</p>
<h2>Named Loggers</h2>
<p>The “Named Loggers” feature allows you to define several loggers (programmatically or in code), and then access them through their names. You can even direct logging instructions to different logging frameworks based on logger names!</p>
<p>In order to get a named logger, just use the overload of <span class="code">LoggerService.GetLogger </span>that takes a string parameter:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">ILogger defaultLogger = LoggerService.GetLogger();
ILogger namedLogger   = LoggerService.GetLogger(<span style="color: #006080">&quot;LAB-DATA&quot;</span>);</pre>
</div>
<p>&#160;</p>
<p>Note that the default logger is basically a named logger with a special name (an empty string). The snippets below all return the default logger:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">ILogger defaultLogger = LoggerService.GetLogger(); 
ILogger defaultLogger = LoggerService.GetLogger(<span style="color: #006080">&quot;&quot;</span>);
ILogger defaultLogger = LoggerService.GetLogger(LoggerService.DefaultLoggerName);</pre>
</div>
<p>&#160;</p>
<p>The downloadable SLF solution contains sample applications that show how to configure loggers with different names both programmatically or via configuration files.</p>
<h3>The Hierarchical Lookup Process</h3>
<p>When requesting a named logger, you don’t have to submit a name that exactly matches the name of a configured logger. Instead, named loggers are organized in a hierarchical manner. As soon as a named logger is being requested, SLF will just resolve the closest match and return you a matching logger instance:</p>
<p><a href="http://blog.hardcodet.net/wp-content/uploads/2009/10/image6.png"><img loading="lazy" style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2009/10/image-thumb6.png" width="547" height="294" /></a>In the above sample, SLF was configured with a total of eight loggers. You can see, that the logger names form a hierarchy. With this setup in place, the closest match will be returned on every request.</p>
<p>Accordingly, <span class="code">LoggerService.GetLogger(&quot;Foo.AAA&quot;) </span>would return a logger of type <span class="code">Foo </span>(closest match). And <span class="code">LoggerService.GetLogger(&quot;Foo.XXX.AAA&quot;) </span>would return a logger of type <span class="code">Foo.XXX </span>(closest match again).</p>
<p>&#160;</p>
<p>Here’s some more samples, matching the above hierarchy:</p>
<table border="1" cellspacing="0" cellpadding="2" width="566">
<tbody>
<tr>
<td valign="top" width="139"><strong>Requested Logger Name</strong></td>
<td valign="top" width="262"><strong>Returned Logger Type</strong></td>
<td valign="top" width="163"><strong>Name of Returned Logger Instance</strong></td>
</tr>
<tr>
<td valign="top" width="139">&#160;</td>
<td valign="top" width="262">&#160;</td>
<td valign="top" width="163">&#160;</td>
</tr>
<tr>
<td valign="top" width="139">&quot;Foo&quot;</td>
<td valign="top" width="262">Type declared for &quot;Foo&quot;</td>
<td valign="top" width="163">&quot;Foo&quot;</td>
</tr>
<tr>
<td valign="top" width="139">&quot;Foo.XXX&quot;</td>
<td valign="top" width="262">Type declared for &quot;Foo.XXX&quot;</td>
<td valign="top" width="163">&quot;Foo.XXX&quot;</td>
</tr>
<tr>
<td valign="top" width="139">&quot;Foo.XXXXXX&quot;</td>
<td valign="top" width="262">Type declared for &quot;Foo.XXX&quot;</td>
<td valign="top" width="163">&quot;Foo.XXXXXX&quot;</td>
</tr>
<tr>
<td valign="top" width="139">&quot;Foo.X&quot;</td>
<td valign="top" width="262">Type declared for &quot;Foo&quot;</td>
<td valign="top" width="163">&quot;Foo.X&quot;</td>
</tr>
<tr>
<td valign="top" width="139">&quot;FooXXX&quot;</td>
<td valign="top" width="262">Type declared for &quot;Foo&quot;</td>
<td valign="top" width="163">&quot;FooXXX&quot;</td>
</tr>
<tr>
<td valign="top" width="139">&quot;Bar.XXX&quot;</td>
<td valign="top" width="262">Type declared for &quot;Bar.XXX&quot;</td>
<td valign="top" width="163">&quot;Bar.XXX&quot;</td>
</tr>
<tr>
<td valign="top" width="139">&quot;Bar.ZZZ&quot;</td>
<td valign="top" width="262">Type declared for &quot;Bar&quot;</td>
<td valign="top" width="163">&quot;Bar.ZZZ&quot;</td>
</tr>
<tr>
<td valign="top" width="139">&quot;XXX&quot;</td>
<td valign="top" width="262">Type declared for Default Logger</td>
<td valign="top" width="163">&quot;XXX&quot;</td>
</tr>
<tr>
<td valign="top" width="139">&quot;XXX.Foo&quot;</td>
<td valign="top" width="262">Type declared for Default Logger</td>
<td valign="top" width="163">&quot;XXX.Foo&quot;</td>
</tr>
<tr>
<td valign="top" width="139">&quot;TEST&quot;</td>
<td valign="top" width="262">Type declared for Default Logger</td>
<td valign="top" width="163">&quot;TEST&quot;</td>
</tr>
<tr>
<td valign="top" width="139">&quot;&quot;</td>
<td valign="top" width="262">Type declared for Default Logger</td>
<td valign="top" width="163">&quot;&quot;</td>
</tr>
<tr>
<td valign="top" width="139">null</td>
<td valign="top" width="262">Type declared for Default Logger</td>
<td valign="top" width="163">&quot;&quot;</td>
</tr>
</tbody>
</table>
<p>&#160;</p>
<h5>Fallback to Default&#160; Logger</h5>
<p>The lookup for a logger will always fall back to the default logger type if no matching named logger was found. This should not come as a surprise. After all, the default logger is just a logger with the name [<span class="code">String.Empty</span>].</p>
<p>And don’t forget – <span class="code">LoggerService </span><em>always</em> returns a valid logger instance and never a null reference. If no unnamed logger was configured at all, you would just receive an instance of <span class="code">NullLogger</span>.</p>
<p>&#160;</p>
<h5>Exceptions to Named Logger Resolving</h5>
<p>Hierarchical lookups work out of the box, but they are not guaranteed if you customize <span class="code">LoggerService</span>:</p>
<ul>
<li>If you inject a single <span class="code">ILogger </span>instance into <span class="code">LoggerService </span>via <span class="code">LoggerService.SetLogger</span>, all requests will of course return this specific logger instance, regardless of the requested logger name. </li>
<li>If you inject a custom resolver into <span class="code">LoggerService </span>by setting the <span class="code">LoggerService.FactoryResolver </span>property, you gain full control over the lookup and logger creation process. Accordingly, you can completely change this behavior.</li>
</ul>
<h3>Configuring Named Loggers in Code or Declaratively</h3>
<p>The sample projects show how to set up named loggers in code, or via the application configuration file (app.config).</p>
<p><a href="http://blog.hardcodet.net/wp-content/uploads/2009/12/image2.png"><img loading="lazy" style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2009/12/image-thumb2.png" width="244" height="224" /></a> </p>
<p>&#160;</p>
<h3>Filtering</h3>
<p>Currently, SLF provides not built-in filtering mechanism, but leaves that to the underlying logging frameworks. The reason for this is that we just wanted to provide a very lean interface to get started with.</p>
<p>However, we’ve already opened a topic on CodePlex’ discussion board, so please express your opinion. If we feel there is a demand for built-in filtering, we will provide the functionality in a matter of days:</p>
<p><a title="http://slf.codeplex.com/Thread/View.aspx?ThreadId=76857" href="http://slf.codeplex.com/Thread/View.aspx?ThreadId=76857">http://slf.codeplex.com/Thread/View.aspx?ThreadId=76857</a></p>
<p>&#160;</p>
<h2>Tutorial Part 2</h2>
<p>The next part of this tutorial will discuss Resolvers, Factories, and creating your own logging façades. It will cover simple scenarios (you can plug-in factories with a single line of code) and more complex resolution scenarios for those among you who happen to deal with challenging logging situations. Stay tuned <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2009/12/slf-tutorial-1/feed</wfw:commentRss>
			<slash:comments>8</slash:comments>
		
		
			</item>
		<item>
		<title>An Introduction to SLF, the Simple Logging Façade</title>
		<link>http://www.hardcodet.net/2009/12/slf-introduction</link>
					<comments>http://www.hardcodet.net/2009/12/slf-introduction#comments</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Wed, 02 Dec 2009 14:27:00 +0000</pubDate>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[SLF]]></category>
		<category><![CDATA[Logging]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/?p=671</guid>

					<description><![CDATA[An introduction to SLF, the Simple Logging Façade.]]></description>
										<content:encoded><![CDATA[<p><a href="http://blog.hardcodet.net/wp-content/uploads/2009/10/slf.png"><img loading="lazy" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="slf" border="0" alt="slf" src="http://blog.hardcodet.net/wp-content/uploads/2009/10/slf-thumb.png" width="450" height="55" /></a>&#160;</p>
<p><strong>Release days are good days – Colin Eberhardt and I are very happy to announce SLF 1.0!</strong></p>
<p><a title="SLF home page at CodePlex" href="http://slf.codeplex.com/">SLF</a> is a framework with a simple but ambitious mission: To provide <strong><em>every</em></strong> developer with the means to easily plug in logging functionality into her application. As such, it aims at two fundamental goals:</p>
<ol>
<li><strong>Simplicity</strong>: SLF allows you to plug in solid logging functionality into your application with literally one line of code, while providing you with an upgrade path to complex logging scenarios at any time. </li>
<li><strong>Flexibility</strong>: SLF provides you with a common interface that decouples the logging framework of your choice (e.g. <a href="http://logging.apache.org/log4net/index.html">log4net</a> or <a href="http://www.nlog-project.org/">NLog</a>)&#160; from your code. This eliminates dependencies on a given framework, thus allowing you to switch (or even combine!) frameworks at any time. Furthermore, SLF’s modular architecture allows you to plug-in custom logging strategies very easily. </li>
</ol>
<p> <span id="more-671"></span>  </p>
<h4>Features</h4>
<ul>
<li>Configurable through code or configuration files (<em>app.config</em>). </li>
<li>Support for named loggers with hierarchical fallback mechanisms. </li>
<li>Support for common logging frameworks such as <a href="http://logging.apache.org/log4net/index.html">log4net</a> out of the box. </li>
<li>Silverlight support. </li>
<li>Writing your own pluggable logging strategy is easy. </li>
<li>You can exchange the underlying logging mechanism at any time, even at runtime. </li>
<li>Extensible and modular architecture. Writing your own façade can be as simple as overriding one single method, but you can cover complex scenarios, should you have to. </li>
<li>Robust: In case of invalid configurations or logging instructions, SLF rather outputs debug warnings instead of crashing your application at runtime. </li>
<li>A ton of copy-and-paste ready samples for different use cases. </li>
<li>.NET 2.0 compatible binaries. </li>
</ul>
<h4>Related Links</h4>
<ul>
<li>SLF project page: <a href="http://slf.codeplex.com">http://slf.codeplex.com</a> </li>
<li><a href="http://www.codeproject.com/KB/trace/ArtOfLogging.aspx">The Art of Logging</a> – an excellent introduction to logging in general from SLF co-creator <a href="http://www.scottlogic.co.uk/blog/wpf/">Colin Eberhardt</a>. </li>
<li>SLF <a title="SLF Hands-on Tutorial" href="http://www.hardcodet.net/2009/12/slf-tutorial-1">Hands-on Tutorial</a>, Part 1 </li>
</ul>
<h2>How does SLF Work?</h2>
<p>Here’s a first snippet that shows how to get a logger at runtime via the static <span class="code">LoggerService </span>class. <span class="code">LoggerService </span>is basically a convenient – and optional – repository for your loggers:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">//get the default (unnamed) logger </span>
ILogger logger = LoggerService.GetLogger();

<span style="color: #008000">//log an information </span>
logger.Info(<span style="color: #006080">&quot;hello world&quot;</span>);</pre>
</div>
<p>&#160;</p>
<p>When working with SLF, you’re usually dealing with the <span class="code">ILogger </span>interface. There’s a few built-in implementations of this interface directly in the SLF core library (e.g. <span class="code">ConsoleLogger</span>), but in productive environments, your <span class="code">ILogger </span>implementation usually is a class that forwards logging instructions to a proprietary logging framework such as <a href="http://logging.apache.org/log4net/index.html">log4net</a>, or a custom logging facility you wrote yourself. Hence the name <em><strong>façade</strong></em>:</p>
<p>&#160;</p>
<p><a href="http://blog.hardcodet.net/wp-content/uploads/2009/10/image7.png"><img loading="lazy" style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2009/10/image-thumb7.png" width="500" height="400" /></a></p>
<p>&#160;</p>
<p>From your application’s point of view, there is no dependency on the underlying façade and logging framework – you are always logging through the <span class="code">ILogger </span>interface of the SLF core library. This allows you to easily exchange the underlying proprietary mechanism without having to change any of your code that performs the actual logging.</p>
<p><font size="1">SLF also allows you to directly control the logger resolution process (the process that eventually leads to an <span class="code">ILogger </span>instance). We will cover this in a later tutorial.</font></p>
<p>&#160;</p>
<h5>But why should we replace dependencies on logging framework X with dependencies on SLF?</h5>
<p>You probably won’t worry about that, as SLF really just forwards logging information, and can be easily adjusted. However: There’s a simple pattern to get rid of that dependency, too. If you download SLF, you will find a sample project that implements a wrapper for SLF itself:</p>
<p>&#160;</p>
<p><a href="http://blog.hardcodet.net/wp-content/uploads/2009/10/image8.png"><img loading="lazy" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2009/10/image-thumb8.png" width="290" height="110" /></a></p>
<p>&#160;</p>
<h2>SLF in a Fictitious Sample: The Lifecycle of an Application.</h2>
<p>I’ll try to outline the benefits of logging, and the role SLF can play in the context of a fictitious software project. We assume the following:</p>
<ul>
<li>The application will contain various modules (plug-ins). The modules will be developed individually by separate teams. </li>
<li>All modules should log important information. These modules log through SLF, so they have no idea about the underlying logging framework. </li>
<li>Parts of the logged data should be sent back to the development team as soon as the first beta versions have been deployed. </li>
</ul>
<p>&#160;</p>
<h3>Week 1: Setting Up Logging</h3>
<p>Developers have other things in mind than thinking about logging frameworks. They do, however, set SLF in place with two simple steps:</p>
<ol>
<li>Set a reference to the SLF core library. </li>
<li>Configure a logger within the main initialization routine of the application. For starters, all logged data is written to Visual Studio’s debugger by plugging a <span class="code">DebugLogger </span>instance into the global <span class="code">LoggerService</span>: </li>
</ol>
<p><font color="#ff0000">Actually, the first line of code in the application is related to logging:</font></p>
<div>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> InitApplication() 
{
  <span style="color: #008000">//make sure logging is in place </span>
  LoggerService.SetLogger(<span style="color: #0000ff">new</span> DebugLogger()); 
  
  [some other code] 
}</pre>
</div>
<ul></ul>
<ul>The application is now officially logging-enabled <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> </ul>
<ul><em>(btw: as an alternative, a one-liner in the application’s configuration file would have worked, too)</em></ul>
<ul></ul>
<h3>Week 2: Developing First Modules</h3>
<p>The first modules are being developed by individual teams. All module libraries maintain a reference to the SLF core library in order to log information. A typical method in a module looks like this:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> Foo() 
{ 
  <span style="color: #0000ff">try</span> 
  {  
    ...
  } 
  <span style="color: #0000ff">catch</span>(Exception e) 
  {  
    ILogger logger = LoggerService.GetLogger(); 
    logger.Fatal(e, <span style="color: #006080">&quot;Some explanation&quot;</span>); 
  }
}</pre>
</div>
<p>&#160;</p>
<p><em>Note that modules have no idea about the underlying logging strategy that was plugged into SLF (currently the <span class="code">DebugLogger</span> from Week 1). They just know how to request a logger (<span class="code">ILogger </span>interface) from <span class="code">LoggerService</span>. What kind of logger they are dealing with is of no interest to them.</em></p>
<p>&#160;</p>
<h3>Week 3: Writing Logged Data to a File</h3>
<p>There’s a lot of modules by now, which all direct logging information towards SLF. Currently, all this logged messages are being written to the debug window (as configured on Week 1). However, the developers would also like to have the data persisted in a file, while keeping the debug output at the same time.</p>
<p>&#160;</p>
<p>Accordingly, the initialization routine from Week 1 is slightly altered:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">//create two independent loggers </span>
ILogger debugLogger = <span style="color: #0000ff">new</span> DebugLogger(); 
ILogger fileLogger = BitFactoryLogger.CreateSingleFileLogger(<span style="color: #006080">&quot;log.txt&quot;</span>); 

<span style="color: #008000">//CompositeLogger will redirect all its logging data to the two loggers… </span>
ILogger composite = <span style="color: #0000ff">new</span> CompositeLogger(debugLogger, fileLogger); 
<span style="color: #008000">//…so plug it into LoggerService </span>
LoggerService.SetLogger(composite);</pre>
</div>
<p>&#160;</p>
<p>There’s now 3 loggers in play:</p>
<ul>
<li>The initial <span class="code">DebugLogger </span>that logs to the debug window. </li>
<li>The <em>BitFactory</em> façade was used to quickly set up logging to a file. The <em>BitFactory</em> façade is a library that comes with SLF (just like the <em>NLog</em> façade library or the <em>log4net</em> façade library) and makes use of the <a href="http://www.theobjectguy.com/dotnetlog/">BitFactory</a> logging framework. This SLF façade library is now referenced by the main application, but not the independent module libraries. </li>
<li><span class="code">CompositeLogger </span>(part of the core library) is then used as a channel that logs output to both the <span class="code">DebugLogger </span>and the new <span class="code">BitFactoryLogger</span>: </li>
</ul>
<p><em>These four lines of code changed the logging behavior of the whole application. Even if there are now literally hundreds of logging instructions in various modules, they don’t need to be changed at all. Everything will now be logged to both the file and the debugger.</em></p>
<p>&#160;</p>
<h3>Week 4: Switching to Declarative Configurations and log4net</h3>
<p>The integration team decides to plug in their logging framework of choice, which happens to be <a href="http://logging.apache.org/log4net/index.html">log4net</a>. Furthermore, they want to get rid of programmatic initialization, and switch to declarative configuration. This requires two steps:</p>
<ol>
<li>Configuring SLF and log4net in the application’s configuration file (<em>app.config</em>) </li>
<li><strong>Remove all the code (initialization of <span class="code">LoggerService</span>) from Weeks 1 and 3.</strong> </li>
</ol>
<ol>Here’s the app.config file:</ol>
<ol>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">&lt;?</span><span style="color: #800000">xml</span> <span style="color: #ff0000">version</span><span style="color: #0000ff">=&quot;1.0&quot;</span> <span style="color: #ff0000">encoding</span><span style="color: #0000ff">=&quot;utf-8&quot;</span> ?<span style="color: #0000ff">&gt;</span> 
<span style="color: #0000ff">&lt;</span><span style="color: #800000">configuration</span><span style="color: #0000ff">&gt;</span> 
  <span style="color: #0000ff">&lt;</span><span style="color: #800000">configSections</span><span style="color: #0000ff">&gt;</span> 
   <span style="color: #0000ff">&lt;</span><span style="color: #800000">section</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;slf&quot;</span>
            <span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;Slf.Config.SlfConfigurationSection, slf&quot;</span><span style="color: #0000ff">/&gt;</span> 

   <span style="color: #0000ff">&lt;</span><span style="color: #800000">section</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;log4net&quot;</span>
            <span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;log4net.Config.Log4NetConfigurationSectionHandler,log4net&quot;</span><span style="color: #0000ff">/&gt;</span> 
  <span style="color: #0000ff">&lt;/</span><span style="color: #800000">configSections</span><span style="color: #0000ff">&gt;</span>


  <span style="color: #0000ff">&lt;</span><span style="color: #800000">slf</span><span style="color: #0000ff">&gt;</span>
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">factories</span><span style="color: #0000ff">&gt;</span>
      <span style="color: #008000">&lt;!-- declare a log4net factory --&gt;</span>
      <span style="color: #0000ff">&lt;</span><span style="color: #800000">factory</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;l4n&quot;</span>
               <span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;SLF.Log4netFacade.Log4netLoggerFactory, SLF.Log4netFacade&quot;</span><span style="color: #0000ff">/&gt;</span> 
    <span style="color: #0000ff">&lt;/</span><span style="color: #800000">factories</span><span style="color: #0000ff">&gt;</span>

    <span style="color: #0000ff">&lt;</span><span style="color: #800000">loggers</span><span style="color: #0000ff">&gt;</span>
      <span style="color: #008000">&lt;!-- declare the default logger --&gt;</span>
      <span style="color: #0000ff">&lt;</span><span style="color: #800000">logger</span> <span style="color: #ff0000">factory</span><span style="color: #0000ff">=&quot;l4n&quot;</span> <span style="color: #0000ff">/&gt;</span>
    <span style="color: #0000ff">&lt;/</span><span style="color: #800000">loggers</span><span style="color: #0000ff">&gt;</span>

  <span style="color: #0000ff">&lt;/</span><span style="color: #800000">slf</span><span style="color: #0000ff">&gt;</span>


  <span style="color: #0000ff">&lt;</span><span style="color: #800000">log4net</span><span style="color: #0000ff">&gt;</span> 
    <span style="color: #008000">&lt;!-- standard log4net settings are here... --&gt;</span> 
   <span style="color: #0000ff">&lt;/</span><span style="color: #800000">log4net</span><span style="color: #0000ff">&gt;</span> 
<span style="color: #0000ff">&lt;/</span><span style="color: #800000">configuration</span><span style="color: #0000ff">&gt;</span></pre>
</p></div>
</ol>
<ol><em>Actually, the above SLF configuration could have been written shorter, but the verbose version is recommended for readability. This would be a shorter, but equivalent version of the <span class="code">slf </span>section:</em></ol>
<ol>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">&lt;</span><span style="color: #800000">slf</span><span style="color: #0000ff">&gt;</span>
  <span style="color: #0000ff">&lt;</span><span style="color: #800000">factories</span><span style="color: #0000ff">&gt;</span>
    <span style="color: #008000">&lt;!-- this default factory is used for every logging instruction --&gt;</span>
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">factory</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;SLF.Log4netFacade.Log4netLoggerFactory, SLF.Log4netFacade&quot;</span><span style="color: #0000ff">/&gt;</span> 
  <span style="color: #0000ff">&lt;/</span><span style="color: #800000">factories</span><span style="color: #0000ff">&gt;</span>
<span style="color: #0000ff">&lt;/</span><span style="color: #800000">slf</span><span style="color: #0000ff">&gt;</span></pre>
</p></div>
</ol>
<h3>Week 5: Working with Named Loggers</h3>
<p>One of the teams develops a module that logs very important data, and they would like to gather this data separately. It is therefore decided that this output will be logged through a <strong>named logger</strong> called <em>LABDATA</em>. This LABDATA logger should store this information separately.</p>
<p>Accordingly, a lot of logging instructions in this team’s module use SLF’s capability to work with named loggers:</p>
<p>&#160;</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> Foo(<span style="color: #0000ff">string</span> someValue) 
{ 
  <span style="color: #0000ff">try</span>
  {
    <span style="color: #008000">//get named logger to log this piece of information </span>
    ILogger labLogger = LoggerService.GetLogger(<span style="color: #006080">&quot;LABDATA&quot;</span>); 
    labLogger.Info(<span style="color: #006080">&quot;Foo was invoked with value {0}&quot;,</span> someValue); 

    ...
  }
  <span style="color: #0000ff">catch</span>(Exception e) 
  {
    <span style="color: #008000">//exceptions are still logged through default logger  </span>
    ILogger defaultLogger = LoggerService.GetLogger();  
    defaultLogger.Fatal(e, <span style="color: #006080">&quot;Some explanation&quot;</span>); 
  }
}</pre>
</div>
<p>&#160;</p>
<p>This code was written by an independent team, and they haven’t changed the configuration of the main application. Accordingly, the logged information will still be routed through the default logger, because a logger that matches the name “LABDATA” just isn’t available yet.</p>
<p>So currently, “LABDATA” output will be logged to the same file as all other logging information.</p>
<p><strong><em>But the important thing is: The mechanism is in place and SLF still works without errors!</em></strong></p>
<p>&#160;</p>
<h3>Week 6: Declaratively Configuring the “LABDATA” Logger</h3>
<p>During integration of the new module, SLF’s configuration is changed in order to support custom logging instructions for the LABDATA module.</p>
<p>Because log4net is used, which also supports named loggers out of the box, the SLF configuration does not need to be changed at all! Only the log4net section is being updated:</p>
<p>The adjustments in the application configuration file are specific to log4net:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">&lt;?</span><span style="color: #800000">xml</span> <span style="color: #ff0000">version</span><span style="color: #0000ff">=&quot;1.0&quot;</span> <span style="color: #ff0000">encoding</span><span style="color: #0000ff">=&quot;utf-8&quot;</span> ?<span style="color: #0000ff">&gt;</span> 
<span style="color: #0000ff">&lt;</span><span style="color: #800000">configuration</span><span style="color: #0000ff">&gt;</span> 
  <span style="color: #0000ff">&lt;</span><span style="color: #800000">configSections</span><span style="color: #0000ff">&gt;</span> 
   <span style="color: #0000ff">&lt;</span><span style="color: #800000">section</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;slf&quot;</span>
            <span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;Slf.Config.SlfConfigurationSection, slf&quot;</span><span style="color: #0000ff">/&gt;</span> 

   <span style="color: #0000ff">&lt;</span><span style="color: #800000">section</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;log4net&quot;</span>
            <span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;log4net.Config.Log4NetConfigurationSectionHandler,log4net&quot;</span><span style="color: #0000ff">/&gt;</span> 
  <span style="color: #0000ff">&lt;/</span><span style="color: #800000">configSections</span><span style="color: #0000ff">&gt;</span>


  <span style="color: #0000ff">&lt;</span><span style="color: #800000">slf</span><span style="color: #0000ff">&gt;</span>
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">factories</span><span style="color: #0000ff">&gt;</span>
      <span style="color: #008000">&lt;!-- declare a log4net factory --&gt;</span>
      <span style="color: #0000ff">&lt;</span><span style="color: #800000">factory</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;l4n&quot;</span>
               <span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;SLF.Log4netFacade.Log4netLoggerFactory, SLF.Log4netFacade&quot;</span><span style="color: #0000ff">/&gt;</span> 
    <span style="color: #0000ff">&lt;/</span><span style="color: #800000">factories</span><span style="color: #0000ff">&gt;</span>

    <span style="color: #0000ff">&lt;</span><span style="color: #800000">loggers</span><span style="color: #0000ff">&gt;</span>
      <span style="color: #008000">&lt;!-- declare the default logger --&gt;</span>
      <span style="color: #0000ff">&lt;</span><span style="color: #800000">logger</span> <span style="color: #ff0000">factory</span><span style="color: #0000ff">=&quot;l4n&quot;</span> <span style="color: #0000ff">/&gt;</span>
    <span style="color: #0000ff">&lt;/</span><span style="color: #800000">loggers</span><span style="color: #0000ff">&gt;</span>

  <span style="color: #0000ff">&lt;/</span><span style="color: #800000">slf</span><span style="color: #0000ff">&gt;</span>


<span style="color: #008000">&lt;!--</span>
<span style="color: #008000">  configures log4net with two loggers:</span>
<span style="color: #008000">  - A default logger, which logs to file &quot;log-common.txt&quot;</span>
<span style="color: #008000">  - A named logger (&quot;LABDATA&quot;), which logs to file &quot;log-labdata.txt&quot;</span>
<span style="color: #008000">--&gt;</span>
<span style="color: #0000ff">&lt;</span><span style="color: #800000">log4net</span><span style="color: #0000ff">&gt;</span>
  <span style="color: #0000ff">&lt;</span><span style="color: #800000">appender</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;CommonAppender&quot;</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;log4net.Appender.FileAppender&quot;</span><span style="color: #0000ff">&gt;</span>
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">param</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;File&quot;</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">=&quot;log-common.txt&quot;</span> <span style="color: #0000ff">/&gt;</span>
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">param</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;AppendToFile&quot;</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">=&quot;true&quot;</span> <span style="color: #0000ff">/&gt;</span>
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">layout</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;log4net.Layout.PatternLayout&quot;</span><span style="color: #0000ff">&gt;</span>
      <span style="color: #0000ff">&lt;</span><span style="color: #800000">conversionPattern</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">=&quot;%date - %message %newline&quot;</span> <span style="color: #0000ff">/&gt;</span>
    <span style="color: #0000ff">&lt;/</span><span style="color: #800000">layout</span><span style="color: #0000ff">&gt;</span>
  <span style="color: #0000ff">&lt;/</span><span style="color: #800000">appender</span><span style="color: #0000ff">&gt;</span>
  
  <span style="color: #0000ff">&lt;</span><span style="color: #800000">appender</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;LabDataAppender&quot;</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;log4net.Appender.FileAppender&quot;</span><span style="color: #0000ff">&gt;</span>
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">param</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;File&quot;</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">=&quot;log-labdata.txt&quot;</span> <span style="color: #0000ff">/&gt;</span>
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">param</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;AppendToFile&quot;</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">=&quot;true&quot;</span> <span style="color: #0000ff">/&gt;</span>
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">layout</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;log4net.Layout.PatternLayout&quot;</span><span style="color: #0000ff">&gt;</span>
      <span style="color: #0000ff">&lt;</span><span style="color: #800000">conversionPattern</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">=&quot;%date [%thread] %-5level - %message %newline&quot;</span> <span style="color: #0000ff">/&gt;</span>
    <span style="color: #0000ff">&lt;/</span><span style="color: #800000">layout</span><span style="color: #0000ff">&gt;</span>
  <span style="color: #0000ff">&lt;/</span><span style="color: #800000">appender</span><span style="color: #0000ff">&gt;</span>
  

  <span style="color: #0000ff">&lt;</span><span style="color: #800000">logger</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;&quot;</span><span style="color: #0000ff">&gt;</span>
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">appender-ref</span> <span style="color: #ff0000">ref</span><span style="color: #0000ff">=&quot;CommonAppender&quot;</span> <span style="color: #0000ff">/&gt;</span>
  <span style="color: #0000ff">&lt;/</span><span style="color: #800000">logger</span><span style="color: #0000ff">&gt;</span>
  
  <span style="color: #0000ff">&lt;</span><span style="color: #800000">logger</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;LABDATA&quot;</span><span style="color: #0000ff">&gt;</span>
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">appender-ref</span> <span style="color: #ff0000">ref</span><span style="color: #0000ff">=&quot;LabDataAppender&quot;</span> <span style="color: #0000ff">/&gt;</span>
  <span style="color: #0000ff">&lt;/</span><span style="color: #800000">logger</span><span style="color: #0000ff">&gt;</span>
<span style="color: #0000ff">&lt;/</span><span style="color: #800000">log4net</span><span style="color: #0000ff">&gt;</span>

<span style="color: #0000ff">&lt;/</span><span style="color: #800000">configuration</span><span style="color: #0000ff">&gt;</span></pre>
</div>
<p>&#160;</p>
<p>&#160;</p>
<h3>Week 7: Using Another Logging Framework for the LABDATA Loggers</h3>
<p>So far, the generated <em>LabData</em> logging file was manually sent to the development team of the new module, which proved to be tedious (somebody had to manually send a mail every day).</p>
<p>Accordingly, a team developed a simple custom logging façade for SLF. This façade uses WCF to send logged data directly to the team.</p>
<p>As a result, there are now two logging façades in play. We have a new situation:</p>
<ul>
<li>Regular logging data should be logged to a file via log4net (same as before). </li>
<li>Logging data for LABDATA should be handled by the new <span class="code">WcfLogger</span>. </li>
</ul>
<p>Fortunately, integration of the new façade library is easy! It can be plugged into SLF declaratively through the application’s configuration file:</p>
<ul>
<li>log4net configuration: The appender for the LABDATA logger is being removed. </li>
<li>SLF configuration: The new <span class="code">WcfLogger </span>is declared, and configured to handle all LABDATA output. SLF allows us to inject arbitrary configuration information into the declaration. For the WCF logger, this is address information and credentials. </li>
</ul>
<p>This is how <em>app.config</em> looks now:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">&lt;?</span><span style="color: #800000">xml</span> <span style="color: #ff0000">version</span><span style="color: #0000ff">=&quot;1.0&quot;</span> <span style="color: #ff0000">encoding</span><span style="color: #0000ff">=&quot;utf-8&quot;</span> ?<span style="color: #0000ff">&gt;</span> 
<span style="color: #0000ff">&lt;</span><span style="color: #800000">configuration</span><span style="color: #0000ff">&gt;</span> 
  <span style="color: #0000ff">&lt;</span><span style="color: #800000">configSections</span><span style="color: #0000ff">&gt;</span> 
   <span style="color: #0000ff">&lt;</span><span style="color: #800000">section</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;slf&quot;</span>
            <span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;Slf.Config.SlfConfigurationSection, slf&quot;</span><span style="color: #0000ff">/&gt;</span> 

   <span style="color: #0000ff">&lt;</span><span style="color: #800000">section</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;log4net&quot;</span>
            <span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;log4net.Config.Log4NetConfigurationSectionHandler,log4net&quot;</span><span style="color: #0000ff">/&gt;</span> 
  <span style="color: #0000ff">&lt;/</span><span style="color: #800000">configSections</span><span style="color: #0000ff">&gt;</span>


  <span style="color: #0000ff">&lt;</span><span style="color: #800000">slf</span><span style="color: #0000ff">&gt;</span>
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">factories</span><span style="color: #0000ff">&gt;</span>
      <span style="color: #008000">&lt;!-- declare a log4net factory --&gt;</span>
      <span style="color: #0000ff">&lt;</span><span style="color: #800000">factory</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;l4n&quot;</span>
               <span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;SLF.Log4netFacade.Log4netLoggerFactory, SLF.Log4netFacade&quot;</span><span style="color: #0000ff">/&gt;</span> 
      
      <span style="color: #008000">&lt;!-- the custom factory that logs to a WCF service. --&gt;</span>
      <span style="color: #0000ff">&lt;</span><span style="color: #800000">factory</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;wcf&quot;</span>
               <span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;Acme.Logging.WcfLogger, Acme.Logging.Slf2WcfFacade&quot;</span><span style="color: #0000ff">&gt;</span>
        <span style="color: #0000ff">&lt;</span><span style="color: #800000">factory-data</span><span style="color: #0000ff">&gt;</span>
          <span style="color: #008000">&lt;!-- this factory takes custom configuration settings --&gt;</span>
          <span style="color: #0000ff">&lt;</span><span style="color: #800000">service</span> <span style="color: #ff0000">address</span><span style="color: #0000ff">=&quot;http://www.acme.com:8080/ws/logs&quot;</span>
                   <span style="color: #ff0000">user</span><span style="color: #0000ff">=&quot;foo&quot;</span>
                   <span style="color: #ff0000">password</span><span style="color: #0000ff">=&quot;bar&quot;</span> <span style="color: #0000ff">/&gt;</span>
        <span style="color: #0000ff">&lt;/</span><span style="color: #800000">factory-data</span><span style="color: #0000ff">&gt;</span>
      <span style="color: #0000ff">&lt;/</span><span style="color: #800000">factory</span><span style="color: #0000ff">&gt;</span>
    <span style="color: #0000ff">&lt;/</span><span style="color: #800000">factories</span><span style="color: #0000ff">&gt;</span>

    <span style="color: #0000ff">&lt;</span><span style="color: #800000">loggers</span><span style="color: #0000ff">&gt;</span>
      <span style="color: #008000">&lt;!-- the default logger that logs via log4net --&gt;</span>
      <span style="color: #0000ff">&lt;</span><span style="color: #800000">logger</span> <span style="color: #ff0000">factory</span><span style="color: #0000ff">=&quot;l4n&quot;</span> <span style="color: #0000ff">/&gt;</span>
      
      <span style="color: #008000">&lt;!-- the named logger that uses the WCF façade --&gt;</span>
      <span style="color: #0000ff">&lt;</span><span style="color: #800000">logger</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;LABDATA&quot;</span> <span style="color: #ff0000">factory</span><span style="color: #0000ff">=&quot;wcf&quot;</span> <span style="color: #0000ff">/&gt;</span>
    <span style="color: #0000ff">&lt;/</span><span style="color: #800000">loggers</span><span style="color: #0000ff">&gt;</span>
  <span style="color: #0000ff">&lt;/</span><span style="color: #800000">slf</span><span style="color: #0000ff">&gt;</span>


  <span style="color: #008000">&lt;!-- log4net configuration for the common log file --&gt;</span>
  <span style="color: #0000ff">&lt;</span><span style="color: #800000">log4net</span><span style="color: #0000ff">&gt;</span>
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">appender</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;CommonAppender&quot;</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;log4net.Appender.FileAppender&quot;</span><span style="color: #0000ff">&gt;</span>
      <span style="color: #0000ff">&lt;</span><span style="color: #800000">param</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;File&quot;</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">=&quot;log-common.txt&quot;</span> <span style="color: #0000ff">/&gt;</span>
      <span style="color: #0000ff">&lt;</span><span style="color: #800000">param</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;AppendToFile&quot;</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">=&quot;true&quot;</span> <span style="color: #0000ff">/&gt;</span>
      <span style="color: #0000ff">&lt;</span><span style="color: #800000">layout</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;log4net.Layout.PatternLayout&quot;</span><span style="color: #0000ff">&gt;</span>
        <span style="color: #0000ff">&lt;</span><span style="color: #800000">conversionPattern</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">=&quot;%date - %message %newline&quot;</span> <span style="color: #0000ff">/&gt;</span>
      <span style="color: #0000ff">&lt;/</span><span style="color: #800000">layout</span><span style="color: #0000ff">&gt;</span>
    <span style="color: #0000ff">&lt;/</span><span style="color: #800000">appender</span><span style="color: #0000ff">&gt;</span>
    
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">root</span><span style="color: #0000ff">&gt;</span>
      <span style="color: #0000ff">&lt;</span><span style="color: #800000">appender-ref</span> <span style="color: #ff0000">ref</span><span style="color: #0000ff">=&quot;CommonAppender&quot;</span> <span style="color: #0000ff">/&gt;</span>
    <span style="color: #0000ff">&lt;/</span><span style="color: #800000">root</span><span style="color: #0000ff">&gt;</span> 
  <span style="color: #0000ff">&lt;/</span><span style="color: #800000">log4net</span><span style="color: #0000ff">&gt;</span>
  
<span style="color: #0000ff">&lt;/</span><span style="color: #800000">configuration</span><span style="color: #0000ff">&gt;</span></pre>
</div>
<p>&#160;</p>
<p><em>Again, only the configuration file was changed – the code in the modules was not touched at all.</em></p>
<p>&#160;</p>
<h3>Week 8 – Unit Testing Logging Instructions</h3>
<p>The developers of the LabData module notice they didn’t cover all code in their unit test: Actually, they don’t know whether their logging instruction are properly executed or not.</p>
<p>In order to unit test their module, they just replace the configured loggers at runtime: They plug in <span class="code">TestLogger </span>classes into <span class="code">LoggerService</span>.&#160; <span class="code">TestLogger</span> is a simple logger which just stores all logging input it receives.</p>
<p>This is how the initialization code of their unit test class looks like:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> Given_Foo_When_Submitting_Lab_Data
{
  <span style="color: #0000ff">private</span> TestLogger defaultLogger;
  <span style="color: #0000ff">private</span> TestLogger labDataLogger;

  [SetUp]
  <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> Init()
  {
    SimpleFactoryResolver resolver = <span style="color: #0000ff">new</span> SimpleFactoryResolver();
    resolver.Factory = <span style="color: #0000ff">new</span> TestLoggerFactory();
    LoggerService.FactoryResolver = resolver;

    <span style="color: #008000">//for convenience, already get the two test loggers that we will be used</span>
    defaultLogger = (TestLogger) LoggerService.GetLogger(<span style="color: #006080">&quot;&quot;</span>);
    labDataLogger = (TestLogger)LoggerService.GetLogger(<span style="color: #006080">&quot;LABDATA&quot;</span>);
  }
}</pre>
</div>
<p>&#160;</p>
<p>The above snippet installs a <span class="code">TestLoggerFactory</span>. This factory will return <span class="code">TestLogger </span>instances for every logger request that is made through <span class="code">LoggerService</span>. This allows to test whether input was logged through the correct loggers.</p>
<p>Here’s a sample unit test:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">[Test]
<span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> Submitting_Regular_Data_Should_Write_Info_To_Lab_Data_Logger()
{
  <span style="color: #0000ff">string</span> testData = <span style="color: #006080">&quot;asl39-23lsd9&quot;</span>;
  Foo.FooBar(testData);

  <span style="color: #008000">//invoking Foo.FooBar should have logged 1 info to the LABDATA logger</span>
  Assert.AreEqual(1, labDataLogger.LoggedItems.Count);

  <span style="color: #008000">//make sure data was logged correctly</span>
  LogItem item = labDataLogger.LoggedItems[0];
  Assert.AreEqual(LogLevel.Info, item.LogLevel);
  StringAssert.Contains(item.Message, testData);

  <span style="color: #008000">//make sure nothing was logged to the default logger</span>
  Assert.AreEqual(0, defaultLogger.Count);
}</pre>
</div>
<p>&#160;</p>
<p>&#160;</p>
<h2>Conclusion and Further Links</h2>
<p>I hope the above scenario gave you an impression about how easily you can set up and adjust your logging environment with SLF. For more information, please visit the <a href="http://slf.codeplex.com">project page</a>, check out the tutorials, or leave a feedback. Happy logging <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2009/12/slf-introduction/feed</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>WPF Disciples Resource Page Updated</title>
		<link>http://www.hardcodet.net/2009/10/wpf-disciples-resources-updated</link>
					<comments>http://www.hardcodet.net/2009/10/wpf-disciples-resources-updated#respond</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Thu, 15 Oct 2009 09:35:13 +0000</pubDate>
				<category><![CDATA[WPF]]></category>
		<category><![CDATA[Disciples]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/2009/10/wpf-disciples-resources-updated</guid>

					<description><![CDATA[Marlon updated the WPF Disciples resources page, which now lists a great selection of the group members’ contributions (including lots of MVVM goodness). Here’s the list: http://wpfdisciples.wordpress.com/resources/ &#160;]]></description>
										<content:encoded><![CDATA[<p><a href="http://marlongrech.wordpress.com/">Marlon</a> updated the WPF Disciples resources page, which now lists a great selection of the group members’ contributions (including lots of MVVM goodness). Here’s the list: </p>
<p><a href="http://wpfdisciples.wordpress.com/resources/">http://wpfdisciples.wordpress.com/resources/</a></p>
<p>&#160;</p>
<p><img title="WPF Disciples" alt="WPF Disciples Logo" src="/uploads/wpf-disciples.png" /></p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2009/10/wpf-disciples-resources-updated/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Windows Live Writer: Plug-ins to Format Content through CSS Classes</title>
		<link>http://www.hardcodet.net/2009/09/live-writer-plugins-to-format-content-through-css-classes</link>
					<comments>http://www.hardcodet.net/2009/09/live-writer-plugins-to-format-content-through-css-classes#comments</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Wed, 30 Sep 2009 20:12:15 +0000</pubDate>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Live Writer]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/?p=637</guid>

					<description><![CDATA[Presents two simple plug-ins that provide CSS formatting support for Windows Live Writer.]]></description>
										<content:encoded><![CDATA[<p>I like using CSS classes to format specific content of my blog posts, in order to keep my formatting centralized. I prefer HTML that looks like this over inline styles: </p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &#39;Courier New&#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none">If you invoke the <span style="color: #0000ff">&lt;</span><span style="color: #800000">span</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">=&quot;code&quot;</span><span style="color: #0000ff">&gt;</span>GetData<span style="color: #0000ff">&lt;/</span><span style="color: #800000">span</span><span style="color: #0000ff">&gt; </span>method, ...</pre>
<p></div>
<p>&#160;</p>
<p>Quickly inserting CSS directives is something you can’t easily do with <a href="http://windowslivewriter.spaces.live.com/">Windows Live Writer</a>. This started to annoy me while writing an article, so I came up with two simple plug-ins that do just that: Formatting selected text through CSS classes.</p>
<p>&#160;</p>
<p><span id="more-637"></span></p>
<p><em></em></p>
<h2>Plug-in 1: Quick-Insert a Predefined CSS Class</h2>
<p>This is a very simple plug-in that stores one (1) single CSS class name, and applies it to the selected text with a single click. This is a fastest possible way to format several junks of your post with the same CSS class.</p>
<p>The simple assignment comes has a price, however: It takes some more work to reconfigure the used CSS class. Therefore, it mainly makes sense if you have quite a lot of similar content to format at once. Otherwise, the second plug-in is probably the better choice.</p>
<p>&#160;</p>
<h3>Using the Plug-in</h3>
<p>Once the plug-in is installed (instructions at the end of the article), you’ll notice an additional entry on the side bar and the <em>Insert</em> menu of the tool bar, saying “<em>Quick CSS…</em>”:</p>
<p>&#160;</p>
<p><a href="http://blog.hardcodet.net/wp-content/uploads/2009/09/image1.png"><img loading="lazy" title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="203" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2009/09/image-thumb1.png" width="172" border="0" /></a> </p>
<p>All you have to do is selecting the portion of text you’d like to format, and click on the plug-in. The configured CSS class name will be immediately applied to the selected text.</p>
<p>&#160;</p>
<h3>First invocation / configuration</h3>
<p>The <em>first</em> time you click on the plug-in, there is no formatting happening. Instead, the plug-in displays its options dialog because no CSS class has been configured yet. This dialog allows you to quickly set the CSS class that should be applied:</p>
<p><a href="http://blog.hardcodet.net/wp-content/uploads/2009/09/image2.png"><img loading="lazy" title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="151" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2009/09/image-thumb2.png" width="240" border="0" /></a> </p>
<p>Subsequent clicks on the plug-in directly apply the class name you configured – this dialog is only opened automatically the first time.</p>
<p>&#160;</p>
<h4>Changing the Class Name</h4>
<p>You can change the name of the used CSS class at any time. This requires a bit of work though, as you’ll have to go through Live Writer’s options dialog:</p>
<p><a href="http://blog.hardcodet.net/wp-content/uploads/2009/09/image3.png"><img loading="lazy" title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="300" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2009/09/image-thumb3.png" width="300" border="0" /></a> </p>
<p>&#160;</p>
<h2>Plug-in 2: Selecting a CSS Class from a List of Class Names</h2>
<p>This is a more flexible plug-in. It takes two clicks to format your text with a given CSS class, but it maintains a configurable list of CSS class names, and allows you to quickly select the class name to be applied from a popup.</p>
<h3>Using the Plug-in</h3>
<p>Once the plug-in is installed (instructions below), you will find a new entry saying <em>“CSS Format</em>…” on the side bar and Live Writer’s <em>Insert</em> menu. Clicking the plug-in (which causes a short delay the first time) opens a popup that lists your CSS classes in alphabetic order. In order to apply a CSS class to the selected text, just double-click a class name:</p>
<p>&#160;</p>
<p><a href="http://blog.hardcodet.net/wp-content/uploads/2009/09/image4.png"><img loading="lazy" title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="349" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2009/09/image-thumb4.png" width="244" border="0" /></a> </p>
<p>&#160;</p>
<h4>Most Recently Used Items</h4>
<p>Note that if you have configured 10 or more CSS class names, the popup will display two lists, of which the upper list contains the 5 most recently used class names.</p>
<p>(I could make that feature configurable in a subsequent release, if requested.)</p>
<p>&#160;</p>
<p><a href="http://blog.hardcodet.net/wp-content/uploads/2009/09/image5.png"><img loading="lazy" title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="244" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2009/09/image-thumb5.png" width="166" border="0" /></a> </p>
<p>&#160;</p>
<h3>Configuring / Importing CSS Class Names</h3>
<p>The plug-in allows you to quickly configure class names through a custom configuration dialog, and also supports importing class names directly from a CSS Style Sheet. You can open the dialog through the Popup by clicking the “<em>Options</em>” button:</p>
<p>&#160;</p>
<p><a href="http://blog.hardcodet.net/wp-content/uploads/2009/09/image6.png"><img loading="lazy" title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="331" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2009/09/image-thumb6.png" width="304" border="0" /></a> </p>
<p>&#160;</p>
<h4>Style Sheet Import</h4>
<p>Clicking the <em>Import Style Sheet</em> button opens a file dialog that allows you to select a style sheet (probably the one you’re also using on your blog). Once selected, the plug-in imports all new class names from the style sheet.</p>
<p>&#160;</p>
<h2>Live Writer Bug: Reformatting Span-Tags</h2>
<p>It appears that Live Writer has a bug when it comes to reformatting already formatted text spans. There’s currently no simple fix for this bug, so keep this in mind:</p>
<p>Imagine you have a preformatted junk of text that looks like this:</p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &#39;Courier New&#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"><span style="color: #0000ff">&lt;</span><span style="color: #800000">span</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">=&quot;foo&quot;</span><span style="color: #0000ff">&gt;</span>hello<span style="color: #0000ff">&lt;/</span><span style="color: #800000">span</span><span style="color: #0000ff">&gt;</span></pre>
<p></div>
<p>Now, if you select the word “hello”, and try to assign it another CSS class (<span class="code">bar</span>), you’d expect the new markup to look like this:</p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &#39;Courier New&#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"><span style="color: #0000ff">&lt;</span><span style="color: #800000">span</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">=&quot;bar&quot;</span><span style="color: #0000ff">&gt;</span>hello<span style="color: #0000ff">&lt;/</span><span style="color: #800000">span</span><span style="color: #0000ff">&gt;</span></pre>
<p></div>
<p>Instead, Live Writer just keeps the old span, and wraps it into a second one.</p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &#39;Courier New&#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"><span style="color: #0000ff">&lt;</span><span style="color: #800000">span</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">=&quot;foo&quot;</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">span</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">=&quot;bar&quot;</span><span style="color: #0000ff">&gt;</span>world<span style="color: #0000ff">&lt;/</span><span style="color: #800000">span</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">span</span><span style="color: #0000ff">&gt;</span></pre>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </p></div>
<p>&#160;</p>
<h2>Download and Installation Instructions</h2>
<p>&#160;</p>
<h4>Download Links</h4>
<p>Plug-in 1: <a href="/uploads/projects/livewriter/Hardcodet.LiveWriter.QuickClassInsert.dll">Hardcodet.LiveWriter.QuickClassInsert.dll</a></p>
<p>Plug-in 2: <a href="/uploads/projects/livewriter/Hardcodet.LiveWriter.ApplyCss.dll">Hardcodet.LiveWriter.ApplyCss.dll</a><a href="/uploads/projects/livewriter/Hardcodet.LiveWriter.ApplyCss.dll"></a> </p>
<p><font size="1">The second plug-in <font color="#ff0000">requires Microsoft .NET Framework 3.5 SP1</font> (download <a href="http://go.microsoft.com/fwlink/?LinkId=76617">here</a>)</font></p>
<p>&#160;</p>
<h4>Installation</h4>
<p>In order to install a plug-in:</p>
<ol>
<li>Make sure Live Writer is not running </li>
<li>Copy the plug-in DLL into Live Writer’s <em>Plugins</em> folder. Usually, this is the following path: <em>C:Program FilesWindows Live WriterPlugins </em></li>
</ol>
<ol>&#160;</ol>
<h4>Source Code Download for Developers</h4>
<p>You can also download the source code of the plug-ins:</p>
<p>&#160;</p>
<p><a href="/uploads/projects/livewriter/css-plugins-for-live-writer.zip"></a><a class="download" href="/uploads/projects/livewriter/css-plugins-for-live-writer.zip">css-plugins-for-live-writer.zip</a></a></p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2009/09/live-writer-plugins-to-format-content-through-css-classes/feed</wfw:commentRss>
			<slash:comments>9</slash:comments>
		
		
			</item>
		<item>
		<title>Making WPF Popups Work in Windowless Applications</title>
		<link>http://www.hardcodet.net/2009/09/activating-wpf-popups-ensures-controls-are-enabled</link>
					<comments>http://www.hardcodet.net/2009/09/activating-wpf-popups-ensures-controls-are-enabled#comments</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Wed, 23 Sep 2009 10:08:24 +0000</pubDate>
				<category><![CDATA[WPF]]></category>
		<category><![CDATA[WPF Controls]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/2009/09/activating-wpf-popups-ensures-controls-are-enabled</guid>

					<description><![CDATA[I’ve first encountered this issue with my WPF NotifyIcon, and now again while writing a plug-in for Windows Live Writer: If you try to display a WPF popup without any Windows open (the Popup is the only UI component there is), certain controls such as TextBox, ListView, or ListBox don’t receive proper mouse and/or keyboard [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I’ve first encountered this issue with my WPF NotifyIcon, and now again while writing a plug-in for Windows Live Writer: If you try to display a WPF popup without any Windows open (the Popup is the only UI component there is), certain controls such as TextBox, ListView, or ListBox don’t receive proper mouse and/or keyboard input, and cannot be selected.</p>
<p>The reason for this issue is buried in the WPF framework, and how it interacts with Windows. Fellow WPF Disciple Andrew Smith pointed me in the right direction:</p>
<p>&#160;</p>
<blockquote>
<p>…because a Popup&#8217;s HWND has the WS_EX_NOACTIVATE so the WPF framework will not attempt to actually focus the associated hwnd (because its usually used with a window and you don&#8217;t want to deactivate the window when you focus something in the popup).</p>
</blockquote>
<p>&#160;</p>
<p>Accordingly, you’ll have to fiddle with Windows Interop to make things work. Here’s the snippet:</p>
<p>&#160;</p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &#39;Courier New&#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">class</span> WinApi
{
  <span style="color: #008000">/// &lt;summary&gt;</span>
  <span style="color: #008000">/// Gives focus to a given window.</span>
  <span style="color: #008000">/// &lt;/summary&gt;</span>
  [DllImport(<span style="color: #006080">&quot;USER32.DLL&quot;</span>)]
  <span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">extern</span> <span style="color: #0000ff">bool</span> SetForegroundWindow(IntPtr hWnd);


  <span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> ActivatePopup(Popup popup)
  {
    <span style="color: #008000">//try to get a handle on the popup itself (via its child)</span>
    HwndSource source = (HwndSource)PresentationSource.FromVisual(popup.Child);
    IntPtr handle = source.Handle;

    <span style="color: #008000">//activate the popup</span>
    SetForegroundWindow(handle);
  }
}</pre>
</div>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2009/09/activating-wpf-popups-ensures-controls-are-enabled/feed</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>WPF NotifyIcon – Bugfix and WinForms Support</title>
		<link>http://www.hardcodet.net/2009/09/wpf-notifyicon-bugfix-and-winforms-support</link>
					<comments>http://www.hardcodet.net/2009/09/wpf-notifyicon-bugfix-and-winforms-support#comments</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Tue, 22 Sep 2009 07:32:15 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/2009/09/wpf-notifyicon-bugfix-and-winforms-support</guid>

					<description><![CDATA[I released an update to my WPF NotifyIcon, which fixes two issues: Interactive Popups should now fully support all control types. The control can now be used in Windows Forms projects, if you need more functionality than the built-in component. The solution now comes with an additional WinForms sample project, which shows how to display [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I released an update to my WPF NotifyIcon, which fixes two issues:</p>
<ul>
<li>Interactive Popups should now fully support all control types. </li>
<li>The control can now be used in Windows Forms projects, if you need more functionality than the built-in component. </li>
</ul>
<p>The solution now comes with an additional WinForms sample project, which shows how to display a WPF user control as an interactive popup.</p>
<p> <a href="http://blog.hardcodet.net/wp-content/uploads/2009/09/image.png"><img loading="lazy" title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="155" alt="image" src="http://blog.hardcodet.net/wp-content/uploads/2009/09/image-thumb.png" width="214" border="0" /></a>   </p>
<ul></ul>
<p>&#160;</p>
<p>Download link and further information can be found on the control’s home page:    <br /><a href="http://www.hardcodet.net/wpf-notifyicon">http://www.hardcodet.net/wpf-notifyicon</a></p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2009/09/wpf-notifyicon-bugfix-and-winforms-support/feed</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>NetDrives 1.0.1 Fixes Settings Bug</title>
		<link>http://www.hardcodet.net/2009/09/netdrives-update-101</link>
					<comments>http://www.hardcodet.net/2009/09/netdrives-update-101#respond</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Tue, 22 Sep 2009 07:30:52 +0000</pubDate>
				<category><![CDATA[NetDrives]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/2009/09/netdrives-update-101</guid>

					<description><![CDATA[I updated NetDrives, which fixes a registry issue when it comes to saving the application settings. Functionality is still the same, though. Project Page: http://www.hardcodet.net/netdrives]]></description>
										<content:encoded><![CDATA[<p>I updated NetDrives, which fixes a registry issue when it comes to saving the application settings. Functionality is still the same, though.</p>
<p>Project Page: <a title="http://www.hardcodet.net/netdrives" href="http://www.hardcodet.net/netdrives">http://www.hardcodet.net/netdrives</a></p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2009/09/netdrives-update-101/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Snippet Time: Helper Libraries for C# / WPF</title>
		<link>http://www.hardcodet.net/2009/09/common-helper-libraries</link>
					<comments>http://www.hardcodet.net/2009/09/common-helper-libraries#respond</comments>
		
		<dc:creator><![CDATA[Philipp Sumi]]></dc:creator>
		<pubDate>Mon, 14 Sep 2009 19:23:35 +0000</pubDate>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[WPF]]></category>
		<category><![CDATA[Utils]]></category>
		<guid isPermaLink="false">http://www.hardcodet.net/?p=601</guid>

					<description><![CDATA[I just made a few minor updates to two libraries which assemble as set of helper classes for C# and WPF and thought: Why not share them? The libraries aren’t really intended to be used directly in your code, but you might find one or another helper method or snippet that might make a nice [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I just made a few minor updates to two libraries which assemble as set of helper classes for C# and WPF and thought: Why not share them? The libraries aren’t really intended to be used directly in your code, but you might find one or another helper method or snippet that might make a nice addition to your own toolbox <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>&#160;</p>
<p><a class="download" title="Hardcodet.Commons Library" href="/uploads/2009/09/Hardcodet.Commons.zip">Hardcodet.Commons</a> (C#, .NET 3.5)    </p>
<p>Common helper classes and snippets (simple base classes, file management, weak events, extension methods etc.)</p>
<p>&#160;</p>
<p><a class="download" title="Hardcodet.Commons Library for WPF" href="/uploads/2009/09/Hardcodet.Wpf.Commons.zip">Hardcodet.Wpf.Commons</a> (C#, .NET 3.5)    </p>
<p>Stuff I commonly use in WPF projects, such as checking for design time, base classes for commands and converters, data binding helpers and other stuff.</p>
<p>&#160;</p>
<p>I’ll keep these libraries up-to-date, version history will be posted here.</p>
<p>&#160;</p>
<p><strong>History:</strong></p>
<p><font face="Courier New">2009.09.14&#160; Initial blog release</font></p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.hardcodet.net/2009/09/common-helper-libraries/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
