<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>codesomnia</title>
	
	<link>http://codesomnia.de</link>
	<description>~ coding at night ~</description>
	<lastBuildDate>Tue, 26 Jul 2011 21:29:25 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<feedburner:info uri="codesomnia" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="codesomnia.de/feed" /><feedburner:emailServiceId>codesomnia</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=codesomnia.de%2Ffeed" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=codesomnia.de%2Ffeed" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://feeds.my.aol.com/add.jsp?url=codesomnia.de%2Ffeed" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/codesomnia.de/feed" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=codesomnia.de%2Ffeed" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=codesomnia.de%2Ffeed" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=codesomnia.de%2Ffeed" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:feedFlare href="http://www.plusmo.com/add?url=codesomnia.de%2Ffeed" src="http://plusmo.com/res/graphics/fbplusmo.gif">Subscribe with Plusmo</feedburner:feedFlare><feedburner:feedFlare href="http://www.thefreedictionary.com/_/hp/AddRSS.aspx?codesomnia.de%2Ffeed" src="http://img.tfd.com/hp/addToTheFreeDictionary.gif">Subscribe with The Free Dictionary</feedburner:feedFlare><feedburner:feedFlare href="http://www.bitty.com/manual/?contenttype=rssfeed&amp;contentvalue=codesomnia.de%2Ffeed" src="http://www.bitty.com/img/bittychicklet_91x17.gif">Subscribe with Bitty Browser</feedburner:feedFlare><feedburner:feedFlare href="http://www.live.com/?add=codesomnia.de%2Ffeed" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><feedburner:feedFlare href="http://mix.excite.eu/add?feedurl=codesomnia.de%2Ffeed" src="http://image.excite.co.uk/mix/addtomix.gif">Subscribe with Excite MIX</feedburner:feedFlare><feedburner:feedFlare href="http://www.webwag.com/wwgthis.php?url=codesomnia.de%2Ffeed" src="http://www.webwag.com/images/wwgthis.gif">Subscribe with Webwag</feedburner:feedFlare><feedburner:feedFlare href="http://www.podcastready.com/oneclick_bookmark.php?url=codesomnia.de%2Ffeed" src="http://www.podcastready.com/images/podcastready_button.gif">Subscribe with Podcast Ready</feedburner:feedFlare><feedburner:feedFlare href="http://www.wikio.com/subscribe?url=codesomnia.de%2Ffeed" src="http://www.wikio.com/shared/img/add2wikio.gif">Subscribe with Wikio</feedburner:feedFlare><feedburner:feedFlare href="http://www.dailyrotation.com/index.php?feed=codesomnia.de%2Ffeed" src="http://www.dailyrotation.com/rss-dr2.gif">Subscribe with Daily Rotation</feedburner:feedFlare><item>
		<title>Sharing Resources in WPF/SL</title>
		<link>http://feedproxy.google.com/~r/codesomnia/~3/UZ3ylZMImCA/</link>
		<comments>http://codesomnia.de/2011/sharing-resources-in-wpfsl/#comments</comments>
		<pubDate>Fri, 24 Jun 2011 20:38:18 +0000</pubDate>
		<dc:creator>Kevin</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[WPF]]></category>

		<guid isPermaLink="false">http://codesomnia.de/?p=273</guid>
		<description><![CDATA[I just stumbled across the problem where I wanted to share a specific Path element between different Buttons as their Content. I declared the Path in a ResourceDictionary &#60;Path x:Key="MinusPath" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Data="{StaticResource MinusData}" Stretch="Fill" Stroke="Red" StrokeThickness="3" /&#62; and referenced &#8230; <a href="http://codesomnia.de/2011/sharing-resources-in-wpfsl/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I just stumbled across the problem where I wanted to share a specific Path element between different Buttons as their Content. I declared the Path in a ResourceDictionary</p>
<pre class="brush: xml; gutter: true; first-line: 1">    &lt;Path x:Key="MinusPath"
          HorizontalAlignment="Stretch"
          VerticalAlignment="Stretch"
          Data="{StaticResource MinusData}"
          Stretch="Fill"
          Stroke="Red"
          StrokeThickness="3" /&gt;</pre>
<p>and referenced the Path in each Button with</p>
<pre class="brush: xml; gutter: true; first-line: 1">&lt;Button Content="{StaticResource MinusPath}"/&gt;</pre>
<p>This works for exactly one Button but not for more. You will get a XamlParseException with an InvalidOperationException as its InnerException. The problem is that you need a new Instance of the Path for each Button.</p>
<p>It actually took me quite a bit until I googled a solution for the problem and the solution is shockingly simply. You just need to add x:Shared=&#8221;false&#8221; to the Path declaration</p>
<pre class="brush: xml; gutter: true; first-line: 1; highlight: [8]">    &lt;Path x:Key="MinusPath"
          HorizontalAlignment="Stretch"
          VerticalAlignment="Stretch"
          Data="{StaticResource MinusData}"
          Stretch="Fill"
          Stroke="Red"
          StrokeThickness="3"
          x:Shared="false" /&gt;</pre>
<p>Up to now I just didn&#8217;t know about this x:-Attribute because it is missing in Intellisense.</p>
<div id="flaresmith" class="feedflare"><script src="http://feeds.feedburner.com/~s/http://feeds.feedburner.com/codesomnia?i=http://codesomnia.de/2011/sharing-resources-in-wpfsl/" type="text/javascript" charset="utf-8"></script></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/codesomnia?a=UZ3ylZMImCA:pGTBTAvYYOw:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/codesomnia?i=UZ3ylZMImCA:pGTBTAvYYOw:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=UZ3ylZMImCA:pGTBTAvYYOw:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/codesomnia?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=UZ3ylZMImCA:pGTBTAvYYOw:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/codesomnia?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=UZ3ylZMImCA:pGTBTAvYYOw:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/codesomnia?i=UZ3ylZMImCA:pGTBTAvYYOw:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=UZ3ylZMImCA:pGTBTAvYYOw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/codesomnia?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/codesomnia/~4/UZ3ylZMImCA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codesomnia.de/2011/sharing-resources-in-wpfsl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://codesomnia.de/2011/sharing-resources-in-wpfsl/</feedburner:origLink></item>
		<item>
		<title>MVVM Dialogs with Caliburn.Micro</title>
		<link>http://feedproxy.google.com/~r/codesomnia/~3/vD9XXjT3Tt8/</link>
		<comments>http://codesomnia.de/2011/mvvm-dialogs-with-caliburn-micro/#comments</comments>
		<pubDate>Thu, 16 Jun 2011 19:23:14 +0000</pubDate>
		<dc:creator>Kevin</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Caliburn.Micro]]></category>
		<category><![CDATA[CMContrib]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[WPF]]></category>

		<guid isPermaLink="false">http://codesomnia.de/?p=246</guid>
		<description><![CDATA[Background In every applications life there comes a time when you need to show some kind of message to the user. Be it a question whether he really wants to delete something or a simple message that says that some &#8230; <a href="http://codesomnia.de/2011/mvvm-dialogs-with-caliburn-micro/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h2>Background</h2>
<p>In every applications life there comes a time when you need to show some kind of message to the user. Be it a question whether he really wants to delete something or a simple message that says that some operation was successfull. The most simple way to do that is the good ol&#8217; MessageBox.Show() with its zillion overloads.</p>
<pre class="brush: csharp; gutter: true; first-line: 1">MessageBox.Show("Foo", "Bar", MessageBoxButton.OKCancel);</pre>
<p>But in the shiny MVVM World , poluting your ViewModels with MessageBoxes is usually frowned upon since it breaks a lot of stuff, especially automated unit testing and theming.</p>
<p>You can find quite a lot solutions about how the &#8216;MVVMize&#8217; MesasgeBoxes and dialog screens in general. Most of them involve wrapping the MessageBox.Show() in some kind of IService, setting up some kind of event infrastructure and other funky stuff. Surprisingly, all of those solutions completely ignore the first M in MVVM, namely the Model, and none really tackles the problem at its heart.</p>
<p><span id="more-246"></span></p>
<h2>One Model to rule them all</h2>
<p>Well, let&#8217;s forget about all the View and ViewModel stuff for now. We will start by <strong>specifying </strong>what we actually want to achieve with a dialog.</p>
<blockquote><p><span style="font-size: 16px; font-family: Georgia, 'Bitstream Charter', serif; line-height: 24px;">We want to display some message concerning some topic and a list of possible Responses from which the user can choose one.</span></p></blockquote>
<p>So, let&#8217;s create a model with conforms to those specifications</p>
<pre class="brush: csharp; gutter: true; first-line: 1">public class Dialog&lt;TResponse&gt;
{
	public DialogType DialogType { get; set; }
	public string Subject { get; set; }
	public string Message { get; set; }

	public IEnumerable&lt;TResponse&gt; PossibleResponses { get; protected set; }
	public TResponse GivenResponse {get; set; }
	public bool IsResponseGiven { get; private set; }
}

public enum DialogType
{
	None,
	Question,
	Warning,
	Information,
	Error
}</pre>
<p>The DialogType in conjunction with the subject defines the topic and the rest is pretty much straightforward. We also need a IsResponseGiven Property so that we can distinguish between default and unset values because TResponse may or may not be a value type (and hence not nullable).</p>
<h2>One ViewModel to bind them</h2>
<p>The ViewModel is responsible for bringing the Responses in a bindable format and setting the response on the dialog when the user selects one. The ViewModel also handles the case where the user closes the window without giving any response at all.</p>
<p>For supporting default (the user presses &#8216;Enter&#8217;) and cancel (the user presses &#8216;Escape&#8217;) responses,  I will use a convention based approach, namely defining the first response in the list as the default response and the last response as the cancel response.</p>
<pre class="brush: csharp; gutter: true; first-line: 1">public class BindableResponse&lt;TResponse&gt;
{
	public TResponse Response { get; set; }
	public bool IsDefault { get; set; }
	public bool IsCancel { get; set; }
}</pre>
<pre class="brush: csharp; gutter: true; first-line: 1">public interface IDialogViewModel&lt;TResponse&gt;
{
	bool IsClosed { get; set; }
	Dialog&lt;TResponse&gt; Dialog { get; set; }
	IObservableCollection&lt;BindableResponse&lt;TResponse&gt;&gt; Responses { get; }
	void Respond(BindableResponse&lt;TResponse&gt; bindableResponse);
}</pre>
<p>The implementation is pretty straightforward and omitted for brevity but can be found <a href="https://codesomnia.kilnhg.com/Repo/Public/Contribs/CMContrib/File/src/CMContrib.SL/Interaction/DialogViewModel.cs?rev=tip" target="_blank">here</a>.</p>
<h2>One View to show them all</h2>
<p>I will present the WPF version of the view here because the SL version requires a workaround for the nonexisting IsDefault/IsCancel Properties of the Button. For those interested in the SL version, the source is <a href="https://codesomnia.kilnhg.com/Repo/Public/Contribs/CMContrib/File/src/CMContrib.SL/Interaction/DialogView.xaml?rev=tip" target="_blank">here</a>. I will also omit all irrelevant (styling) properties.</p>
<pre class="brush: xml; gutter: true; first-line: 1">&lt;Window x:Class="Caliburn.Micro.Contrib.Interaction.DialogView"
        Title="{Binding Dialog.Subject}"
        Contrib:DialogCloser.DialogResult="{Binding CanClose}"&gt;
    &lt;Window.Icon&gt;
        &lt;Binding Path="Dialog.DialogType"&gt;
            &lt;Binding.Converter&gt;
                &lt;Converter:DialogTypeToSystemIconConverter /&gt;
            &lt;/Binding.Converter&gt;
        &lt;/Binding&gt;
    &lt;/Window.Icon&gt;
    &lt;DockPanel Focusable="False" LastChildFill="True"&gt;
        &lt;ItemsControl x:Name="Responses"&gt;
            &lt;ItemsControl.ItemTemplate&gt;
                &lt;DataTemplate&gt;
                    &lt;Button Content="{Binding Response}"
                            IsCancel="{Binding IsCancel}"
                            IsDefault="{Binding IsDefault}"
                            Micro:Message.Attach="Respond($dataContext)" /&gt;
                &lt;/DataTemplate&gt;
            &lt;/ItemsControl.ItemTemplate&gt;
        &lt;/ItemsControl&gt;
        &lt;TextBlock Text="{Binding Dialog.Message}" /&gt;
    &lt;/DockPanel&gt;
&lt;/Window&gt;</pre>
<p>The most important part is where we bind the Responses to an ItemsControl (by using Caliburn.Micros Convention Binding Feature) and create a Button for each Response which will call the Respond() Method on the ViewModel with the bound Response as a parameter. The Subject of the Dialog is bound to the Title of the Window and the DialogType is <a href="https://codesomnia.kilnhg.com/Repo/Public/Contribs/CMContrib/File/src/CMContrib.WPF/Converter/DialogTypeToSystemIconConverter.cs" target="_blank">converted </a>to an Icon.</p>
<h2>And in the IResult wrap them</h2>
<blockquote><p>No Caliburn.Micro Extension with the corresponding IResult to use them !</p></blockquote>
<p>To actually show the dialog to the user, we would have to</p>
<p><span style="font-size: 16px; font-family: Georgia, 'Bitstream Charter', serif; line-height: 24px;"> </span></p>
<ol>
<li>Create the dialog</li>
<li>Import the IWindowManager in the ViewModel</li>
<li>Create the ViewModel and pass it the dialog</li>
<li>Invoke ShowDialog() on the IWindowManager with the ViewModel as a parameter</li>
</ol>
<p>Well, the first step cannot be encapsulated in an IResult, but 2-4 rest can easily be encapsulated.</p>
<pre class="brush: csharp; gutter: true; first-line: 1">public class DialogResult&lt;TResponse&gt; : IResult
{
	private Func&lt;IDialogViewModel&lt;TResponse&gt;&gt; _locateVM = () =&gt; new DialogViewModel&lt;TResponse&gt;();

	public DialogResult(Dialog&lt;TResponse&gt; dialog)
	{
		Dialog = dialog;
	}

	public Dialog&lt;TResponse&gt; Dialog { get; private set; }

	public void Execute(ActionExecutionContext context)
	{
		IDialogViewModel&lt;TResponse&gt; vm = _locateVM();
		vm.Dialog = Dialog;
		Micro.Execute.OnUIThread(() =&gt; IoC.Get&lt;IWindowManager&gt;().ShowDialog(vm));
	}

	public DialogResult&lt;TResponse&gt; In(IDialogViewModel&lt;TResponse&gt; dialogViewModel)
	{
		_locateVM = () =&gt; dialogViewModel;
		return this;
	}

	public DialogResult&lt;TResponse&gt; In&lt;TDialogViewModel&gt;()
		where TDialogViewModel : IDialogViewModel&lt;TResponse&gt;
	{
		_locateVM = () =&gt; IoC.Get&lt;TDialogViewModel&gt;();
		return this;
	}
}</pre>
<p>We do not only get reusable code, but also a nice way to change the implementation of IDialogViewModel&lt;&gt; for specific dialogs if we want to.</p>
<p>Last but not least we can write a small Extension Method to get even more readable code !</p>
<pre class="brush: csharp; gutter: true; first-line: 1">public static DialogResult&lt;TResponse&gt; AsResult&lt;TResponse&gt;(this Dialog&lt;TResponse&gt; dialog)
        {
            return new DialogResult&lt;TResponse&gt;(dialog);
        }</pre>
<p>And use it in the coroutine</p>
<pre class="brush: csharp; gutter: true; first-line: 1">public IEnumerable&lt;IResult&gt; Foo()
{
	var question = new Dialog&lt;Answer&gt;(DialogType.Question,
									  "Isn't this a nice way to create a Dialog Window?",
									  Answer.Yes,
									  Answer.No);

	yield return question.AsResult();

	if (question.GivenResponse == Answer.Yes)
		Console.WriteLine(" :] ");
	else
		Console.WriteLine(" :[ ");
}</pre>
<div id="flaresmith" class="feedflare"><script src="http://feeds.feedburner.com/~s/http://feeds.feedburner.com/codesomnia?i=http://codesomnia.de/2011/mvvm-dialogs-with-caliburn-micro/" type="text/javascript" charset="utf-8"></script></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/codesomnia?a=vD9XXjT3Tt8:8GNAWmAxP-M:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/codesomnia?i=vD9XXjT3Tt8:8GNAWmAxP-M:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=vD9XXjT3Tt8:8GNAWmAxP-M:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/codesomnia?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=vD9XXjT3Tt8:8GNAWmAxP-M:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/codesomnia?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=vD9XXjT3Tt8:8GNAWmAxP-M:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/codesomnia?i=vD9XXjT3Tt8:8GNAWmAxP-M:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=vD9XXjT3Tt8:8GNAWmAxP-M:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/codesomnia?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/codesomnia/~4/vD9XXjT3Tt8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codesomnia.de/2011/mvvm-dialogs-with-caliburn-micro/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		<feedburner:origLink>http://codesomnia.de/2011/mvvm-dialogs-with-caliburn-micro/</feedburner:origLink></item>
		<item>
		<title>Handling Errors in Caliburn.Micro’s IResult – Part II</title>
		<link>http://feedproxy.google.com/~r/codesomnia/~3/yuo6rG_q0Ts/</link>
		<comments>http://codesomnia.de/2011/handling-errors-in-caliburn-micro%e2%80%99s-iresult-%e2%80%93-part-ii/#comments</comments>
		<pubDate>Wed, 01 Jun 2011 11:30:39 +0000</pubDate>
		<dc:creator>Kevin</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Caliburn.Micro]]></category>
		<category><![CDATA[CMContrib]]></category>

		<guid isPermaLink="false">http://codesomnia.de/?p=225</guid>
		<description><![CDATA[Preface In my last post I gave two possible approaches and a preview of my final solution for handling errors in IResults. The syntax for my final solution was This means that whenever the result completes with an error of type &#8230; <a href="http://codesomnia.de/2011/handling-errors-in-caliburn-micro%e2%80%99s-iresult-%e2%80%93-part-ii/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h2>Preface</h2>
<p>In my <a href="http://codesomnia.de/2011/handling-errors-in-caliburn-micros-iresults-part-i/">last post</a> I gave two possible approaches and a preview of my final solution for handling errors in IResults. The syntax for my final solution was</p>
<pre class="brush: csharp; title: ; notranslate">
yield return new ProcessDataResult()
		.Rescue().With(coroutine: IORescue)
		.Rescue().With(coroutine: GeneralRescue);
</pre>
<p>This means that</p>
<ul>
<li>whenever the result completes with an error of type IOException, the IORescue coroutine is executed</li>
<li>whenever the result completes with any other error, the GeneralRescue coroutine is executed</li>
</ul>
<p>So the behaviour of the Rescue is similar to a try/catch block</p>
<pre class="brush: csharp; title: ; notranslate">
try {}
catch (IOException e) { //IORescue }
catch (Exception e) { //GeneralRescue }
</pre>
<p><span id="more-225"></span></p>
<h2>Decorators to the Rescue !</h2>
<p>Now, before we have a look at the implementation, you should make yourself familiar with the <a href="http://en.wikipedia.org/wiki/Decorator_pattern" target="_blank">Decorator Pattern</a> since we will use a <strong>Decorator </strong>to &#8216;extend&#8217; the behaviour of the Execute-Method of our <strong>Inner </strong>Result.</p>
<p>Well, let&#8217;s start with a base class for our decorators.</p>
<pre class="brush: csharp; title: ; notranslate">
internal class ResultDecoratorBase : IResult
{
	private readonly IResult _inner;

	protected ResultDecoratorBase(IResult inner)
	{
		if (inner == null) throw new ArgumentNullException(&quot;inner&quot;);

		_inner = inner;
	}

	public IResult Inner
	{
		get { return _inner; }
	}

	#region IResult Members

	public virtual void Execute(ActionExecutionContext context)
	{
		var wrapper = new SequentialResult(new SingleResultEnumerator(_inner));
		wrapper.Completed += InnerCompleted;

		wrapper.Execute(context);
	}

	public virtual event EventHandler Completed;

	#endregion

	protected virtual void OnCompleted(ResultCompletionEventArgs args)
	{
		if (Completed != null)
			Completed(this, args);
	}

	protected virtual void InnerCompleted(object sender, ResultCompletionEventArgs args)
	{
		(sender as IResult).Completed -= InnerCompleted;
	}
}
</pre>
<p>The base Decorator takes an arbitrary IResult and, when executed, wraps it in a SequentialResult (to get some benefits like build up by the IoC ) and executes it. The InnerCompleted()-Method is the hook for the inheriting Decorators to perform their logic.</p>
<h2>The Rescue Decorator</h2>
<p>The <strong>Rescue Decorator</strong> will be generic (for the type that we want to catch) and takes a Function in its constructor which taked an exception as an argument and returns the Rescue Coroutine. We can also specify if we always want to cancel the Result after the rescue was executed.</p>
<pre class="brush: csharp; title: ; notranslate">
/// &lt;summary&gt;
///   A result decorator which executes a coroutine when the inner result completes with an error
/// &lt;/summary&gt;
/// &lt;typeparam name = &quot;TException&quot;&gt;The type of the exception we want to perform the rescue on&lt;/typeparam&gt;
internal class RescueCoroutineDecorator&lt;TException&gt; : ResultDecoratorBase
	where TException : Exception
{
	private readonly bool _cancelResult;
	private readonly Func&lt;TException, IEnumerable&lt;IResult&gt;&gt; _rescue;

	public RescueCoroutineDecorator(IResult inner, Func&lt;TException, IEnumerable&lt;IResult&gt;&gt; rescue, bool cancelResult)
		: base(inner)
	{
		if (rescue == null) throw new ArgumentNullException(&quot;rescue&quot;);

		_rescue = rescue;
		_cancelResult = cancelResult;
	}
}
</pre>
<p>In the InnerCompleted()-Method we check if the Inner Result completed with an error of type TException and if so, execute the Rescue Coroutine. If not, we ignore the error and raise the Completed-Event with the same args.</p>
<pre class="brush: csharp; title: ; notranslate">
protected override void InnerCompleted(object sender, ResultCompletionEventArgs args)
{
	base.InnerCompleted(sender, args);

	if (args.Error is TException)
	{
		var error = (TException)args.Error;

		LogRescuedError(error);

		try
		{
			Rescue(error);
		}
		catch (Exception e)
		{
			Log.Error(e);
			OnCompleted(new ResultCompletionEventArgs { Error = e });
		}
	}
	else
	{
		OnCompleted(args);
	}
}

private void Rescue(TException exception)
{
	var rescueResult = new SequentialResult(_rescue(exception).GetEnumerator());
	rescueResult.Completed += RescueCompleted;

	rescueResult.Execute(_context);
}
</pre>
<p>Then, when the Rescue Coroutine completed, the Decorator will also complete. Since we execute the Rescue inside the execution of the Decorator we can also check if the Rescue completes successfully and react accordingly (like setting the error on the EventArgs or cancel it)</p>
<pre class="brush: csharp; title: ; notranslate">
private void RescueCompleted(object sender, ResultCompletionEventArgs args)
{
	(sender as IResult).Completed -= RescueCompleted;

	OnCompleted(new ResultCompletionEventArgs { Error = args.Error, WasCancelled = args.WasCancelled || CancelResult });
}
</pre>
<p>The full code for the Rescue Decorator can be found <a href="https://codesomnia.kilnhg.com/Repo/Public/Contribs/CMContrib/File/src/CMContrib.SL/Decorators/RescueCoroutineDecorator.cs?rev=tip" target="_blank">here</a>.</p>
<h2>Recap</h2>
<p>Well, with the Decorator Pattern it was possible to implement all the desired features in a nice and <a href="https://codesomnia.kilnhg.com/Repo/Public/Contribs/CMContrib/Files/test/CMContrib.Test?rev=tip" target="_blank">testable</a> way. Furthermore, we can use same principle for executing a coroutine <a href="https://codesomnia.kilnhg.com/Repo/Public/Contribs/CMContrib/File/src/CMContrib.SL/Decorators/ContinueCoroutineDecorator.cs?rev=tip" target="_blank">when the result is cancelled</a> or <a href="https://codesomnia.kilnhg.com/Repo/Public/Contribs/CMContrib/File/src/CMContrib.SL/Decorators/CatchCoroutineDecorator.cs?rev=tip" target="_blank">when an exception is thrown</a> inside the result.</p>
<div id="flaresmith" class="feedflare"><script src="http://feeds.feedburner.com/~s/http://feeds.feedburner.com/codesomnia?i=http://codesomnia.de/2011/handling-errors-in-caliburn-micro%e2%80%99s-iresult-%e2%80%93-part-ii/" type="text/javascript" charset="utf-8"></script></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/codesomnia?a=yuo6rG_q0Ts:E7gOp3I_how:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/codesomnia?i=yuo6rG_q0Ts:E7gOp3I_how:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=yuo6rG_q0Ts:E7gOp3I_how:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/codesomnia?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=yuo6rG_q0Ts:E7gOp3I_how:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/codesomnia?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=yuo6rG_q0Ts:E7gOp3I_how:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/codesomnia?i=yuo6rG_q0Ts:E7gOp3I_how:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=yuo6rG_q0Ts:E7gOp3I_how:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/codesomnia?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/codesomnia/~4/yuo6rG_q0Ts" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codesomnia.de/2011/handling-errors-in-caliburn-micro%e2%80%99s-iresult-%e2%80%93-part-ii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://codesomnia.de/2011/handling-errors-in-caliburn-micro%e2%80%99s-iresult-%e2%80%93-part-ii/</feedburner:origLink></item>
		<item>
		<title>Handling Errors in Caliburn.Micro’s IResult – Part I</title>
		<link>http://feedproxy.google.com/~r/codesomnia/~3/miMFzo7XM0g/</link>
		<comments>http://codesomnia.de/2011/handling-errors-in-caliburn-micros-iresults-part-i/#comments</comments>
		<pubDate>Tue, 31 May 2011 19:50:38 +0000</pubDate>
		<dc:creator>Kevin</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Caliburn.Micro]]></category>
		<category><![CDATA[CMContrib]]></category>

		<guid isPermaLink="false">http://codesomnia.de/?p=204</guid>
		<description><![CDATA[The Problem One of Caliburn.Micro&#8217;s nicest feature is, hands down, the concept of Actions. In that concept the IResult plays an important role, especially when using Coroutines. If you don&#8217;t know about them, you should definately read up on them &#8230; <a href="http://codesomnia.de/2011/handling-errors-in-caliburn-micros-iresults-part-i/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h2>The Problem</h2>
<p>One of Caliburn.Micro&#8217;s nicest feature is, hands down, the concept of <strong>Actions</strong>. In that concept the<strong> IResult</strong> plays an important role, especially when using <strong>Coroutines</strong>. If you don&#8217;t know about them, you should definately <a href="http://devlicio.us/blogs/rob_eisenberg/archive/2010/08/21/caliburn-micro-soup-to-nuts-part-5-iresult-and-coroutines.aspx" target="_blank">read up on them here first</a>.</p>
<p>So, let&#8217;s assume we are executing a Coroutine which first shows a loading screen to the user, then starts processing a lot of data and finally hides the loading screen once the processing is finished. Since the processing is also likely to fail for whatever reason we want to handle the error by executing a <strong>Rescue Coroutine</strong>.</p>
<pre class="brush: csharp; title: ; notranslate">
public IEnumerable ProcessData()
{
	yield return new BusyResult(&quot;Processing...&quot;);

	yield return new ProcessDataResult();

	yield return new NotBusyResult();
}
</pre>
<p>The implementation of those results is irrelevant since we want to have a look at how we can handle the error during the processing in a nice (reusable) way.</p>
<p><span id="more-204"></span></p>
<h2>The First Attempt</h2>
<p>Well, let&#8217;s see how we can handle it at all. The first approach is to ignore the built-in mechanism and expose an error property on the result which will then be checked during the execution of the Coroutine.</p>
<pre class="brush: csharp; title: ; notranslate">
public IEnumerable ProcessData()
{
	yield return new BusyResult(&quot;Processing...&quot;);

	var processDataResult = new ProcessDataResult();
	yield return processDataResult;

	if (processDataResult.Error != null)
	{
		// We could use Coroutine.BeginExecute(Rescue().GetEnumerator()); but than the context would be null
		foreach (var rescueResult in Rescue())
		{
			yield return rescueResult;
		}
		yield break;
	}
	else
	{
		yield return new NotBusyResult();
	}
}

public IEnumerable&lt;IResult&gt; Rescue()
{
	yield return new NotBusyResult();

	// more rescue stuff
}

public class ProcessDataResult : IResult
{
	public Exception Error { get; private set; }

	public void Execute(ActionExecutionContext context)
	{
		try
		{
			//process the data
		}
		catch (Exception e)
		{
			Error = e;
		}

		Completed(this, new ResultCompletionEventArgs());
	}

	public event EventHandler&lt;ResultCompletionEventArgs&gt; Completed;
}
</pre>
<p>Although this works, there are some <strong>problems </strong>with this approach.</p>
<ul>
<li>We need to add an error property to each result where an error is likely (which may not be always possible)</li>
<li>The syntax for executing the Rescue Coroutine is quite ugly and not easy to comprehend</li>
<li>The method itself gets exponentially more complex for every result which can fail</li>
<li>Calling different rescues for different error is tideous</li>
</ul>
<h2>The Better Attempt</h2>
<p>The second approach uses the built-in mechanism by raising the <strong>Completed Event</strong> with the Error roperty of the ResultCompletitionEventArgs set to the actual error.</p>
<pre class="brush: csharp; title: ; notranslate">
public IEnumerable&lt;IResult&gt; ProcessData()
{
	yield return new BusyResult(&quot;Processing...&quot;);

	var processDataResult = new ProcessDataResult();
	processDataResult.Completed += (sender, args) =&gt;
									   {
										   if (args.Error != null)
											   Coroutine.BeginExecute(Rescue().GetEnumerator());
									   };

	yield return processDataResult;

	yield return new NotBusyResult();
}

public IEnumerable&lt;IResult&gt; Rescue()
{
	yield return new NotBusyResult();

	// more rescue stuff
}

public class ProcessDataResult : IResult
{
	public void Execute(ActionExecutionContext context)
	{
		try
		{
			//process the data
		}
		catch (Exception e)
		{
			Completed(this, new ResultCompletionEventArgs { Error = e });
		}

		Completed(this, new ResultCompletionEventArgs());
	}

	public event EventHandler&lt;ResultCompletionEventArgs&gt; Completed;
}
</pre>
<p>With this approach we don&#8217;t need to add an extra property to our Result which is a huge gain but there are still some <strong>disadvantages</strong>.</p>
<ul>
<li>We &#8216;lose&#8217; the context in the Rescue Coroutine</li>
<li>Syntax still not optimal</li>
<li>Calling different rescues is still tedious</li>
</ul>
<h2>The Final Solution</h2>
<p>So, what we want is basically</p>
<ul>
<li>a nice syntax,</li>
<li>something that works for every implementation of IResult,</li>
<li>execute the Rescue Coroutine with the same context as the failing Coroutine,</li>
<li>and a way to handle different types of errors</li>
</ul>
<p>Whew, that&#8217;s quite a bit to ask for. Let&#8217;s have a look at the first two points. Since we want it to work on <strong>every implementation</strong> of IResult, we cannot use inheritance but how about an <strong>Extension Method</strong> for IResults together with some <strong>fluent syntax</strong>?</p>
<pre class="brush: csharp; title: ; notranslate">
public IEnumerable&lt;IResult&gt; ProcessData()
{
	yield return new BusyResult(&quot;Processing...&quot;);

	yield return new ProcessDataResult()
		.Rescue&lt;IOException&gt;().With(coroutine: IORescue)
		.Rescue().With(coroutine: GeneralRescue);

	yield return new NotBusyResult();
}

public IEnumerable&lt;IResult&gt; IORescue(IOException exception)
{
	yield return new NotBusyResult();

	// more rescue stuff
}

public IEnumerable&lt;IResult&gt; GeneralRescue(Exception exception)
{
	yield return new NotBusyResult();

	// more rescue stuff
}
</pre>
<p>That doesn&#8217;t look too bad, does it?</p>
<p>But since this post got really long, I will show the implementation of the solution in the next part. So you either wait for the next post or you can <a href="https://codesomnia.kilnhg.com/Repo/Public/Contribs/CMContrib/File/src/CMContrib.SL/ResultExtensions.cs" target="_blank">have a look at the code yourself </a></p>
<div id="flaresmith" class="feedflare"><script src="http://feeds.feedburner.com/~s/http://feeds.feedburner.com/codesomnia?i=http://codesomnia.de/2011/handling-errors-in-caliburn-micros-iresults-part-i/" type="text/javascript" charset="utf-8"></script></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/codesomnia?a=miMFzo7XM0g:veb2KSOrSn4:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/codesomnia?i=miMFzo7XM0g:veb2KSOrSn4:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=miMFzo7XM0g:veb2KSOrSn4:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/codesomnia?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=miMFzo7XM0g:veb2KSOrSn4:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/codesomnia?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=miMFzo7XM0g:veb2KSOrSn4:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/codesomnia?i=miMFzo7XM0g:veb2KSOrSn4:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=miMFzo7XM0g:veb2KSOrSn4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/codesomnia?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/codesomnia/~4/miMFzo7XM0g" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codesomnia.de/2011/handling-errors-in-caliburn-micros-iresults-part-i/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://codesomnia.de/2011/handling-errors-in-caliburn-micros-iresults-part-i/</feedburner:origLink></item>
		<item>
		<title>Caliburn.Micro feat. AvalonDock II: Save/Restore Layout</title>
		<link>http://feedproxy.google.com/~r/codesomnia/~3/EadQWKJdxSg/</link>
		<comments>http://codesomnia.de/2011/caliburn-micro-feat-avalondock-ii-saverestore-layout/#comments</comments>
		<pubDate>Tue, 15 Feb 2011 01:29:59 +0000</pubDate>
		<dc:creator>Kevin</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Caliburn.Micro]]></category>
		<category><![CDATA[WPF]]></category>

		<guid isPermaLink="false">http://codesomnia.de/?p=180</guid>
		<description><![CDATA[One of the most convient feature for the user is to save the layout of the different widgets in your app, especially if you can arrange them as nicely as with AvalonDock. Luckily, the DockingManager already supports this feature, so &#8230; <a href="http://codesomnia.de/2011/caliburn-micro-feat-avalondock-ii-saverestore-layout/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>One of the most convient feature for the user is to save the layout of the different widgets in your app, especially if you can arrange them as nicely as with AvalonDock. Luckily, the <em>DockingManager </em>already supports this feature, so basically all we have to do is store the list of all conducted items of the conductor and the widget layout in the filesystem when the app closes. When the app is started again we restore the list of conducted items and in doing so the dockable contents of the DockingManager (which must have the same name as before). Then we tell the DockingManager to restore the layout and we are done.</p>
<p><span id="more-180"></span><br />
So, we will start with an interface which defines some methods for saving/restoring the state of a class on startup/shutdown.</p>
<pre class="brush: csharp; title: ; notranslate">
public interface ICanResurrect
{
	bool CanResurrect { get; }

	void CreateTombstone();
	void Resurrect();
}
</pre>
<p>A tombstone is basically the file (or the row in a sql table, etc) in which you store all the information you need to &#8216;resurrect&#8217; the class on startup. For the implementation of this interface in the different classes (view, conductor, conducted items) i wrote an <em>ITombstoneService </em>which helps with the with storing the information on disk. I won&#8217;t go into implementation details of this interface because it is outside of the scope of this post but it is included in the demo project. Here&#8217;s the signature of the interface</p>
<pre class="brush: csharp; title: ; notranslate">
public interface ITombstoneService&lt;TTombstone&gt;
{
	string TombstoneDirectory { get; }

	void Create(string tombstoneName, TTombstone tombstone);
	TTombstone Load(string tombstoneName);
	bool Exists(string tombstoneName);
}
</pre>
<p>So, we will start with the view implementation this time. First, we will extend the <em>IAvalonDockView </em>interface.</p>
<pre class="brush: csharp; title: ; notranslate">
public interface IResurrectableAvalonDockView&lt;T&gt; : IAvalonDockView&lt;T&gt;, ICanResurrect
	where T : IHaveGuid
{
}

public interface IHaveGuid
{
	Guid Guid { get; set; }
}
</pre>
<p>You can change the restriction of T in your implementation to whatever you want, we just need a way the uniquely identify each view model and a guid is the easiest way to do this. We will implement the interface again in a seperate class and use that class in the view.</p>
<pre class="brush: csharp; title: ; notranslate">
public class ResurrectableAvalonDockViewImpl&lt;T&gt; : AvalonDockViewImpl&lt;T&gt;, IResurrectableAvalonDockView&lt;T&gt;
        where T : IHaveGuid
{
	private readonly ILog _log = LogManager.GetLog(typeof (ResurrectableAvalonDockViewImpl&lt;T&gt;));

	private readonly string _tombstoneName;
	private readonly ITombstoneService&lt;string&gt; _tombstoneService = new DemoTombstoneService();

	public ResurrectableAvalonDockViewImpl(DockingManager dockingManager, string tombstoneName)
		: base(dockingManager)
	{
		_tombstoneName = tombstoneName;
		dockingManager.Loaded += (s, e) =&gt; Resurrect();
	}

	#region IResurrectableAvalonDockView&lt;T&gt; Members

	public bool CanResurrect
	{
		get { return _tombstoneService.Exists(_tombstoneName); }
	}

	public void CreateTombstone()
	{
		using (var sw = new StringWriter())
		{
			_log.Info(&quot;Creating Tombstone {0}&quot;, _tombstoneName);

			DockingManager.SaveLayout(sw);

			string tombstoneContent = sw.GetStringBuilder().ToString();

			_tombstoneService.Create(_tombstoneName, tombstoneContent);
		}
	}

	public void Resurrect()
	{
		if (CanResurrect)
		{
			_log.Info(&quot;Resurrect from Tombstone {0}&quot;, _tombstoneName);

			string tombstoneContent = _tombstoneService.Load(_tombstoneName);
			using (var sr = new StringReader(tombstoneContent))
			{
				DockingManager.RestoreLayout(sr);
			}
		}
	}

	#endregion
}
</pre>
<p>Well, not so much to do here because we just need to create/load our tombstone and use it for the save/restore feature of the <em>DockingManager </em>after it has loaded.</p>
<p>Since the implementation of the conductor is a bit more complicated, i will split the code in three parts and discuss it one by one. We will start with the creation of the tombstone.</p>
<pre class="brush: csharp; title: ; notranslate">
public abstract class ResurrectableAvalonConductor&lt;T&gt; : AvalonConductor&lt;T&gt;, ICanResurrect
        where T : IHaveGuid
{
	public void CreateTombstone()
	{
		_log.Info(&quot;Creating Tombstone.&quot;);

		string[] itemDescriptions = GetTombstoneItems()
			.Select(x =&gt; string.Format(&quot;{0}{1}{2}&quot;, x.GetType().AssemblyQualifiedName, Seperator, x.Guid))
			.ToArray();

		string content = String.Join(Environment.NewLine, itemDescriptions);

		_tombstoneService.Create(TombstoneName, content);

		foreach (T item in Items)
		{
			if (item is ICanResurrect)
				(item as ICanResurrect).CreateTombstone();
		}
	}

	protected virtual IEnumerable&lt;T&gt; GetTombstoneItems()
	{
		// here you can filter out the items which should not be resurrected
		return Items;
	}
}
</pre>
<p>First, we select all the conducted items we want to store in the tombstone and save all the information we need for resurrection (type and guid) in a string. Then, we also call <em>CreateTombstone()</em> for each item which implements the <em>ICanResurrect </em>interface.</p>
<pre class="brush: csharp; title: ; notranslate">
public virtual void Resurrect()
{
	if (CanResurrect)
	{
		_log.Info(&quot;Resurrecting from Tombstone {0}&quot;, TombstoneName);
		string content = _tombstoneService.Load(TombstoneName);
		string[] lines = content
			.Split(new[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries);

		var itemDescriptions = lines
			.Select(x =&gt; x.Split(new[] {Seperator}, StringSplitOptions.None))
			.Select(x =&gt; new {AssemblyQualifiedName = x[0], Guid = new Guid(x[1])});

		foreach (var itemDescription in itemDescriptions)
		{
			Type itemType = Type.GetType(itemDescription.AssemblyQualifiedName);
			T item;
			if (TryResurrectItem(itemType, itemDescription.Guid, out item))
			{
				if (item is ICanResurrect)
				{
					(item as ICanResurrect).Resurrect();
				}
				_log.Info(&quot;Activating type from tombstone: {0} {1}&quot;,
						  itemDescription.AssemblyQualifiedName,
						  itemDescription.Guid);
				ActivateItem(item);
			}
		}
	}
}

protected virtual object ResurrectItem(Type type, Guid guid)
{
	object instance = Activator.CreateInstance(type);
	if (instance is IHaveGuid) (instance as IHaveGuid).Guid = guid;

	return instance;
}

private bool TryResurrectItem(Type type, Guid guid, out T item)
{
	object instance = ResurrectItem(type, guid);
	if (instance is T)
	{
		item = (T) instance;
		return true;
	}

	item = default(T);
	_log.Info(&quot;Wrong type in tombstone: {0}&quot;, type.AssemblyQualifiedName);
	return false;
}
</pre>
<p>In the <em>Resurrect() </em>method, we load the tombstone and parse its content . Each line contains the type and the guid of the item, so we store that data in an anonymous class for better readability. Then, we iterate over all items and try to resurrect them. If you want to use an IoC container for object creation, you should override the ResurrectItem() method. Also, we check for each item if it implements the <em>ICanResurrect </em>interface and if so, call its Resurrect() method. Finally, we activate the item.<br />
Last but not least, we need to know when to call the CreateTombstone() and Resurrect() method. The CreateTombstone() method must be called before we deactivate the items but after we checked if we can actually close the conductor. So we need to override the CanClose() method. Another way might be to implement a custom <em>ICloseStrategy&lt;T&gt;</em>.</p>
<pre class="brush: csharp; title: ; notranslate">
public override void CanClose(Action&lt;bool&gt; callback)
{
	CloseStrategy.Execute(Items,
						  (canClose, closable) =&gt;
						  {
							  if (canClose)
							  {
								  CreateTombstone();
								  if (View is ICanResurrect) (View as ICanResurrect).CreateTombstone();
							  }
							  closable.Apply(x =&gt; DeactivateItem(x, true));
							  callback(canClose);
						  });
}
</pre>
<p>The <em>Resurrect()</em> method will be called after the view has been created because <em>ActivateItem()</em> needs it.</p>
<pre class="brush: csharp; title: ; notranslate">
protected override void OnViewLoaded(object view)
{
	base.OnViewLoaded(view);
	Resurrect();
}
</pre>
<p>That&#8217;s it for the second (and last) part. I&#8217;ve again created a small demo project where you can see how you can use all those classes we just implemented. Download is <a href="http://cid-443f7180b02f0de2.office.live.com/self.aspx/.Public/codesomnia/prototypes/CaliburnWithAvalonDock%5E_PartII.7z" target="_blank">here</a></p>
<div id="flaresmith" class="feedflare"><script src="http://feeds.feedburner.com/~s/http://feeds.feedburner.com/codesomnia?i=http://codesomnia.de/2011/caliburn-micro-feat-avalondock-ii-saverestore-layout/" type="text/javascript" charset="utf-8"></script></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/codesomnia?a=EadQWKJdxSg:-89SjTUXRGY:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/codesomnia?i=EadQWKJdxSg:-89SjTUXRGY:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=EadQWKJdxSg:-89SjTUXRGY:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/codesomnia?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=EadQWKJdxSg:-89SjTUXRGY:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/codesomnia?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=EadQWKJdxSg:-89SjTUXRGY:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/codesomnia?i=EadQWKJdxSg:-89SjTUXRGY:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=EadQWKJdxSg:-89SjTUXRGY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/codesomnia?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/codesomnia/~4/EadQWKJdxSg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codesomnia.de/2011/caliburn-micro-feat-avalondock-ii-saverestore-layout/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://codesomnia.de/2011/caliburn-micro-feat-avalondock-ii-saverestore-layout/</feedburner:origLink></item>
		<item>
		<title>Caliburn.Micro feat. AvalonDock I: Conductor and View</title>
		<link>http://feedproxy.google.com/~r/codesomnia/~3/0XlkQoZ0Dew/</link>
		<comments>http://codesomnia.de/2011/caliburn-micro-feat-avalondock-i-conductor-and-view/#comments</comments>
		<pubDate>Sun, 13 Feb 2011 13:56:26 +0000</pubDate>
		<dc:creator>Kevin</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Caliburn.Micro]]></category>

		<guid isPermaLink="false">http://codesomnia.de/?p=151</guid>
		<description><![CDATA[AvalonDock is a fancy, open source tab control for WPF which i wanted to use in one of my clients projects because it supports save/restore layout. Unfortunately, binding the avalondock control to your view model isn&#8217;t as easy as it &#8230; <a href="http://codesomnia.de/2011/caliburn-micro-feat-avalondock-i-conductor-and-view/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>AvalonDock is a fancy, open source tab control for WPF which i wanted to use in one of my clients projects because it supports save/restore layout. Unfortunately, binding the avalondock control to your view model isn&#8217;t as easy as it is with the standard wpf tab control. Hence i googled a bit and found<a href="http://avalondock.codeplex.com/wikipage?title=AvalonDock%20Binding&amp;referringTitle=Documentation" target="_blank"> this article</a> in the AvalonDock documentation and a <a href="http://frankmao.com/2010/11/19/when-caliburn-micro-meets-avalondock/http://frankmao.com/2010/11/19/when-caliburn-micro-meets-avalondock/" target="_blank">blog entry</a> which deals with the problem but both didn&#8217;t really solve the problem. What i needed was a notification mechanism for the gui when the conductor changes (or closes) its ActiveItem and vice versa, i.e. a two-way binding.</p>
<p><span id="more-151"></span></p>
<p>So, how can we implement that. Well, my idea was to make the conductor aware of the view and implement an interface in the view which allows me to change/close the active item in the AvalonDock control and to register to the events when the user activates/closes a tab in the control. The interface i came up with is this:</p>
<pre class="brush: csharp; title: ; notranslate">
public interface IAvalonDockView&lt;T&gt;
{
	DockingManager DockingManager { get; }

	void Show(T item);
	void Close(T item);

	event EventHandler&lt;ContentActivatedEventArgs&lt;T&gt;&gt; ContentActivated;
	event EventHandler&lt;ContentClosingEventArgs&lt;T&gt;&gt; ContentClosing;
}

public class ContentActivatedEventArgs&lt;T&gt; : EventArgs
{
	public T Item;
}

public class ContentClosingEventArgs&lt;T&gt; : EventArgs
{
	public T Item;
	public bool Cancel;
}
</pre>
<p>I think it is pretty straightforward. One thing to note though is the cancel flag in the ContentClosingEventArgs which allows the conductor to cancel the closing of a tab item (f.e. when the viewmodels TryClose() method returns false). I choosed to not implement the interface directly in my view but in a seperate implementor class and the view basically acts as an adapter for the implementor.</p>
<pre class="brush: csharp; title: ; notranslate">
public class AvalonDockViewImpl&lt;T&gt; : IAvalonDockView&lt;T&gt;
{
	private readonly ILog _log = LogManager.GetLog(typeof (AvalonDockViewImpl&lt;T&gt;));

	/// &lt;summary&gt;
	/// Returns the name for the dockable content of the item. This name must be unique for each item if you want to use the save/restore layout feature!
	/// &lt;/summary&gt;
	/// &lt;param name=&quot;item&quot;&gt;&lt;/param&gt;
	/// &lt;returns&gt;&lt;/returns&gt;
	public Func&lt;T, string&gt; ResolveDockableContentName { get; set; }

	/// &lt;summary&gt;
	/// Returns the title for the dockable content of the item. This name must not be unique !
	/// &lt;/summary&gt;
	/// &lt;param name=&quot;item&quot;&gt;&lt;/param&gt;
	/// &lt;returns&gt;&lt;/returns&gt;
	public Func&lt;T, string&gt; ResolveDockableContentTitle { get; set; }

	public AvalonDockViewImpl(DockingManager dockingManager)
	{
		DockingManager = dockingManager;

		dockingManager.ActiveDocumentChanged += (s, e) =&gt;
													{
														var dc = dockingManager.ActiveDocument as DockableContent;
														OnDcActivated(dc);
													};

		ResolveDockableContentName = item =&gt; string.Format(&quot;Item{0}&quot;, item.GetHashCode().ToString());

		ResolveDockableContentTitle = item =&gt; item is IHaveDisplayName
												  ? (item as IHaveDisplayName).DisplayName
												  : typeof (T).Name;
	}

	#region IAvalonDockView&lt;T&gt; Members

	public DockingManager DockingManager { get; private set; }

	public void Show(T item)
	{
		_log.Info(&quot;Showing {0}&quot;, ResolveDockableContentName(item));
		object view = LocateViewFor(item);

		DockableContent dc = GetDockableContentFromView(view);

		if (dc == null)
		{
			_log.Info(&quot;No dockable content found for {0}. Creating a new one&quot;, ResolveDockableContentName(item));
			dc = CreateDockableContent(item);
			_log.Info(&quot;Created dockable content: {0}&quot;, dc.Name);
			dc.ShowAsDocument(DockingManager);
		}
		else
		{
			_log.Info(&quot;Dockable content {0} found for {1}&quot;, dc.Name, ResolveDockableContentName(item));
			dc.Activate();
			if (dc.State == DockableContentState.Hidden)
			{
				dc.Show();
			}
			if (dc.State == DockableContentState.DockableWindow)
			{
				((FloatingDockablePane) (dc.Parent)).FloatingWindow.Focus();
				((FloatingDockablePane) (dc.Parent)).FloatingWindow.Topmost = true;
			}
		}
	}

	public void Close(T item)
	{
		_log.Info(&quot;Showing {0}&quot;, item is IHaveDisplayName ? (item as IHaveDisplayName).DisplayName : typeof (T).Name);
		object view = LocateViewFor(item);

		DockableContent dc = GetDockableContentFromView(view);
		if (dc != null)
		{
			dc.Close(true);
		}
	}

	public event EventHandler&lt;ContentActivatedEventArgs&lt;T&gt;&gt; ContentActivated;
	public event EventHandler&lt;ContentClosingEventArgs&lt;T&gt;&gt; ContentClosing;

	#endregion

	private DockableContent GetDockableContentFromView(object view)
	{
		return DockingManager.DockableContents
			.SingleOrDefault(x =&gt; x.Content == view);
	}

	private DockableContent CreateDockableContent(T item)
	{
		object view = LocateViewFor(item);

		var dockableContent = new DockableContent
								  {
									  Content = view,
									  Name = ResolveDockableContentName(item),
									  Title = ResolveDockableContentTitle(item),
									  HideOnClose = false
								  };

		dockableContent.Closing += (s, e) =&gt;
									   {
										   var dc = (s as DockableContent);
										   _log.Info(&quot;Attempting to close dc {0}&quot;, dc.Name);

										   T vm = LocateViewModelFor(dc.Content);

										   bool cancel = false;
										   if (ContentClosing != null)
										   {
											   var closingEventArgs = new ContentClosingEventArgs&lt;T&gt;
																		  {
																			  Item = vm
																		  };
											   ContentClosing(this, closingEventArgs);
											   cancel = closingEventArgs.Cancel;
										   }

										   if (cancel)
										   {
											   _log.Info(&quot;Closing of dc {0} canceled&quot;, dc.Name);
										   }

										   e.Cancel |= cancel;
									   };

		dockableContent.Closed += (s, e) =&gt;
									  {
										  var dc = (s as DockableContent);
										  dc.Content = null;
									  };

		dockableContent.IsActiveContentChanged += (s, e) =&gt;
													  {
														  var dc = (s as DockableContent);
														  OnDcActivated(dc);
													  };

		return dockableContent;
	}

	private void OnDcActivated(DockableContent dc)
	{
		T vm = LocateViewModelFor(dc.Content);
		if (dc.IsActiveContent)
		{
			_log.Info(&quot;Changed active dc to {0}&quot;, dc.Name);
			if (ContentActivated != null)
			{
				ContentActivated(this, new ContentActivatedEventArgs&lt;T&gt; {Item = vm});
			}
		}
	}

	public static object LocateViewFor(T item)
	{
		UIElement view = ViewLocator.LocateForModel(item, null, null);

		ViewModelBinder.Bind(item, view, null);

		return view;
	}

	public static T LocateViewModelFor(object view)
	{
		object viewModel = ViewModelLocator.LocateForView(view);

		return (T) viewModel;
	}
}
</pre>
<p>The Show() method checks if there already exists a dockable content for the view and if so makes it the active tabitem or window. If there doesn&#8217;t exist a dockable content, one is created and activated. We also register to various events of the dockable content, notably to the closing event to cancel the closing of the dockable content if the view model permits it. The two Func&lt;T,string&gt; which resolve the title (what is shown in the tab header) and name (used for saving/restoring layouts) for the dockable content can be changed easily in the view. Note that the name of the dockable content must be unique if you want to use the save/restore layout feature and that you can bind to the title property if you need to. We will take a look at the layout feature in the second part. The Close() method looks for the dockable content which host the view and closes it. Easy stuff.</p>
<p>For the conductor, i decided to subclass the existsing Conductor&lt;T&gt;.Collection.OneActive since that is exactly the behavior i wanted. So i only had to override some methods, namely:</p>
<pre class="brush: csharp; title: ; notranslate">
public class AvalonConductor&lt;T&gt; : Conductor&lt;T&gt;.Collection.OneActive
{
	private IAvalonDockView&lt;T&gt; View { get; set; }

	protected override void ChangeActiveItem(T newItem, bool closePrevious)
	{
		T previous = ActiveItem;
		base.ChangeActiveItem(newItem, closePrevious);
		if (closePrevious &amp;&amp; !Equals(previous, ActiveItem))
		{
			View.Close(previous);
		}
	}

	public override void ActivateItem(T item)
	{
		bool updateView = !Equals(item, ActiveItem);
		base.ActivateItem(item);
		if (updateView) View.Show(ActiveItem);
	}

	protected override T DetermineNextItemToActivate(int lastIndex)
	{
		// this will be handled by the view
		return default(T);
	}

	protected override void OnViewLoaded(object view)
	{
		base.OnViewLoaded(view);
		var avalonDockView = view as IAvalonDockView&lt;T&gt;;
		if (avalonDockView != null)
		{
			View = avalonDockView;
			View.ContentActivated += (s, e) =&gt; ActivateItem(e.Item);

			View.ContentClosing += (s, e) =&gt;
							{
								DeactivateItem(e.Item, true);
								e.Cancel = Items.Contains(e.Item);
							};
		}
	}
}
</pre>
<p>When the view is loaded we register to its events and call the appropiate methods when the event is fired. And when the conductor activates/closes an item, we call the the corresponding method on the view. One thing to note is that the view actually determines the next active item if the current is closed so we just return null.</p>
<p>That&#8217;s it for the first part.  I also created a small demo project which can be downloaded <a href="http://cid-443f7180b02f0de2.office.live.com/self.aspx/.Public/codesomnia/prototypes/CaliburnWithAvalonDock%5E_Part1.7z" target="_blank">here</a></p>
<div id="flaresmith" class="feedflare"><script src="http://feeds.feedburner.com/~s/http://feeds.feedburner.com/codesomnia?i=http://codesomnia.de/2011/caliburn-micro-feat-avalondock-i-conductor-and-view/" type="text/javascript" charset="utf-8"></script></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/codesomnia?a=0XlkQoZ0Dew:Ry5v3-SFFAk:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/codesomnia?i=0XlkQoZ0Dew:Ry5v3-SFFAk:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=0XlkQoZ0Dew:Ry5v3-SFFAk:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/codesomnia?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=0XlkQoZ0Dew:Ry5v3-SFFAk:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/codesomnia?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=0XlkQoZ0Dew:Ry5v3-SFFAk:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/codesomnia?i=0XlkQoZ0Dew:Ry5v3-SFFAk:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=0XlkQoZ0Dew:Ry5v3-SFFAk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/codesomnia?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/codesomnia/~4/0XlkQoZ0Dew" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codesomnia.de/2011/caliburn-micro-feat-avalondock-i-conductor-and-view/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://codesomnia.de/2011/caliburn-micro-feat-avalondock-i-conductor-and-view/</feedburner:origLink></item>
		<item>
		<title>Automatic Auditing with NHibernate</title>
		<link>http://feedproxy.google.com/~r/codesomnia/~3/ZDoPYBwt700/</link>
		<comments>http://codesomnia.de/2010/automatic-audit-with-nhibernate/#comments</comments>
		<pubDate>Mon, 19 Jul 2010 13:10:16 +0000</pubDate>
		<dc:creator>Kevin</dc:creator>
				<category><![CDATA[Fluent NHibernate]]></category>
		<category><![CDATA[NHibernate]]></category>

		<guid isPermaLink="false">http://codesomnia.de/?p=31</guid>
		<description><![CDATA[Many business applications require that we track who created or changed an entity, etc. There are basically two ways to store the audit data . The first one is to store the audit data directly with your entity and the &#8230; <a href="http://codesomnia.de/2010/automatic-audit-with-nhibernate/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Many business applications require that we track who created or changed an entity, etc. There are basically two ways to store the audit data . The first one is to store the audit data directly with your entity and the other, more complex way is to create an audit log which stores all important changes to the entities. Since we are only interested in storing who created/modified an entity, we will use the first approach. Although you can find some implementations for this approach on the web, none of them meet all requirements i have.</p>
<p>The requirements are:</p>
<ul>
<li>Fine-grained control about what we want to audit for each entity type</li>
<li>Automatic (fluent) mapping of the audit properties</li>
<li>Setting the audit data automatically on each insert/update</li>
<li>Easily change how the username and date is retrieved</li>
</ul>
<p><span id="more-31"></span></p>
<p>We will start with two interfaces, <em>IAuditCreation and </em><em>IAuditLastModification</em>. The interfaces add the respective audit properties to our entities</p>
<pre class="brush: csharp; title: ; notranslate">
    public interface IAuditCreation
    {
        string CreatedBy { get; }
        DateTime? CreatedOn { get; }
    }

    public interface IAuditLastModification
    {
        string LastModifiedBy { get; }
        DateTime? LastModifiedOn { get; }
    }
</pre>
<p>The next step is to create an abstract base class for our fluent mappings. We get all interfaces from the type we want to map and if the type implements one of our audit interfaces, we simply map the fields provided by that interface.</p>
<pre class="brush: csharp; title: ; notranslate">
public class AuditMap&lt;TEntity&gt; : ClassMap&lt;TEntity&gt;
    {
        public AuditMap()
        {
            var interfaces = typeof(TEntity).GetInterfaces();
            if (interfaces.Contains(typeof(IAuditCreation)))
            {
                Map(x =&gt; (x as IAuditCreation).CreatedBy)
                    .Access.Property();
                Map(x =&gt; (x as IAuditCreation).CreatedOn)
                    .Access.Property();
            }
            if (interfaces.Contains(typeof(IAuditLastModification)))
            {
                Map(x =&gt; (x as IAuditLastModification).LastModifiedBy)
                    .Access.Property();
                Map(x =&gt; (x as IAuditLastModification).LastModifiedOn)
                    .Access.Property();
            }
        }
    }
</pre>
<p>With the mapping in place, we need a way to automatically set the property on our entity before each save or update. We will use the event / listener system introduced in NHibernate 2.0 for this task. First, we will create an <em>IAuditor</em> interface which provides functions for retrieving the username/date and for updating the properties on our entity. In case you ask yourself why we use the events as a parameter instead of the entity itself, then you should note that we must update the entity as well as the  entity state of the event. For more informations on the events, read <a href="http://ayende.com/Blog/archive/2009/04/29/nhibernate-ipreupdateeventlistener-amp-ipreinserteventlistener.aspx" target="_blank">this</a></p>
<pre class="brush: csharp; title: ; notranslate">
    public interface IAuditor
    {
        string Username { get; }
        DateTime Date { get; }

        void HandleInsert(PreInsertEvent @event);
        void HandleUpdate(PreUpdateEvent @event);
    }
</pre>
<p>My implementation of the interface looks like this. Note that the <em>Date</em> property should be evaluated each time it is called. If you just set it to DateTime.Now it will be the same for each subsequent call.</p>
<pre class="brush: csharp; collapse: true; light: false; title: ; toolbar: true; notranslate">
    public class DefaultAuditor : AuditorBase
    {
        protected Func&lt;string&gt; RetrieveUsername { get; set; }
        protected Func&lt;DateTime&gt; RetrieveDate { get; set; }

        public override string Username { get { return RetrieveUsername(); } }
        public override DateTime Date { get { return RetrieveDate(); } }

        public DefaultAuditor()
            : this(() =&gt; Environment.UserName, () =&gt; DateTime.Now)
        {

        }

        public DefaultAuditor(Func&lt;string&gt; retrieveUsername, Func&lt;DateTime&gt; retrieveDate)
        {
            RetrieveUsername = retrieveUsername;
            RetrieveDate = retrieveDate;
        }
    }

    public abstract class AuditorBase : IAuditor
    {
        public abstract string Username { get; }
        public abstract DateTime Date { get; }

        protected AuditorBase()
        {
        }

        public virtual void HandleInsert(PreInsertEvent @event)
        {
            var logCreation = @event.Entity as IAuditCreation;
            if (logCreation != null)
            {
                Set(@event,
                    &quot;CreatedBy&quot;,
                    Username);
                Set(@event,
                    &quot;CreatedOn&quot;,
                    Date);
            }

            HandleUpdate(new PreUpdateEvent(@event.Entity, @event.Id, @event.State, null, @event.Persister, null));
        }

        public virtual void HandleUpdate(PreUpdateEvent @event)
        {
            var lastModification = @event.Entity as IAuditLastModification;
            if (lastModification != null)
            {
                Set(@event,
                    &quot;LastModifiedBy&quot;,
                    Username);
                Set(@event,
                    &quot;LastModifiedOn&quot;,
                    Date);
            }
        }

        private void Set(PreUpdateEvent @event, string propertyName, object value)
        {
            SetEntity(@event.Entity, propertyName, value);
            SetState(@event.Persister.PropertyNames, @event.State, propertyName, value);
        }

        private void Set(PreInsertEvent @event, string propertyName, object value)
        {
            SetEntity(@event.Entity, propertyName, value);
            SetState(@event.Persister.PropertyNames, @event.State, propertyName, value);
        }

        private void SetState(string[] propertyNames, object[] state, string propertyName, object value)
        {
            int index = Array.IndexOf(propertyNames, propertyName);
            if (index != -1)
            {
                state[index] = value;
            }
        }

        private void SetEntity(object entity, string propertyName, object value)
        {
            var propertyInfo = entity.GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance);
            if (propertyInfo != null &amp;&amp; propertyInfo.CanWrite)
            {
                propertyInfo.SetValue(entity, value, null);
            }
        }
    }
</pre>
<p>Last but not least we need to provide an event listener which uses the <em>IAuditor</em></p>
<pre class="brush: csharp; title: ; notranslate">
    public class AuditorEventListener :
        IPreInsertEventListener,
        IPreUpdateEventListener
    {
        public IAuditor Auditor { get; private set; }

        public AuditorEventListener(IAuditor auditor)
        {
            Auditor = auditor;
        }

        public bool OnPreInsert(PreInsertEvent @event)
        {
            Auditor.HandleInsert(@event);

            return false;
        }

        public bool OnPreUpdate(PreUpdateEvent @event)
        {
            Auditor.HandleUpdate(@event);

            return false;
        }
    }
</pre>
<p>To register the listener with NHibernate, you must add this to your fluent configuration. You can, of course, replace the creation of the auditor with your IoC framework of choice, but for the sake of simplicity i created the auditor directly in the configuration. Also note, that you should not overwrite the event listeners with a new array because that would remove already registered listeners.</p>
<pre class="brush: csharp; title: ; notranslate">
Fluently.Configure()
                .Database(SQLiteConfiguration.Standard.InMemory()
                    .ShowSql())
                .Mappings(x =&gt; x.FluentMappings.Add&lt;CustomerMap&gt;())
                .ExposeConfiguration(c =&gt;
                {
                    var auditor = new DefaultAuditor();
                    var listener = new AuditorEventListener(auditor);

                    c.EventListeners.PreInsertEventListeners =
                        c.EventListeners.PreInsertEventListeners
                        .Concat(new[] { listener })
                        .ToArray();
                    c.EventListeners.PreUpdateEventListeners =
                        c.EventListeners.PreUpdateEventListeners
                        .Concat(new[] { listener })
                        .ToArray();
                });
</pre>
<p>That&#8217;s it. The whole solution, including unit test and a short console demo can be downloaded from my SkyDrive <a href="http://cid-443f7180b02f0de2.office.live.com/self.aspx/.Public/AutomaticAuditionWithNHibernate.rar">here</a>.</p>
<div id="flaresmith" class="feedflare"><script src="http://feeds.feedburner.com/~s/http://feeds.feedburner.com/codesomnia?i=http://codesomnia.de/2010/automatic-audit-with-nhibernate/" type="text/javascript" charset="utf-8"></script></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/codesomnia?a=ZDoPYBwt700:yPScRZ4dUlc:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/codesomnia?i=ZDoPYBwt700:yPScRZ4dUlc:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=ZDoPYBwt700:yPScRZ4dUlc:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/codesomnia?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=ZDoPYBwt700:yPScRZ4dUlc:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/codesomnia?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=ZDoPYBwt700:yPScRZ4dUlc:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/codesomnia?i=ZDoPYBwt700:yPScRZ4dUlc:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/codesomnia?a=ZDoPYBwt700:yPScRZ4dUlc:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/codesomnia?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/codesomnia/~4/ZDoPYBwt700" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codesomnia.de/2010/automatic-audit-with-nhibernate/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://codesomnia.de/2010/automatic-audit-with-nhibernate/</feedburner:origLink></item>
	</channel>
</rss>

