<?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>Ryan Cromwell &#187; .Net</title>
	<atom:link href="http://blog.cromwellhaus.com/index.php/category/net/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.cromwellhaus.com</link>
	<description>Improving my craft...</description>
	<lastBuildDate>Tue, 07 Feb 2012 15:06:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Your Test Suite Sucks&#8230; do it again</title>
		<link>http://blog.cromwellhaus.com/2012/01/your-test-suite-sucks-do-it-again/</link>
		<comments>http://blog.cromwellhaus.com/2012/01/your-test-suite-sucks-do-it-again/#comments</comments>
		<pubDate>Wed, 04 Jan 2012 03:42:24 +0000</pubDate>
		<dc:creator>cromwellryan</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[Testing]]></category>

		<guid isPermaLink="false">http://blog.cromwellhaus.com/2012/01/your-test-suite-sucks-do-it-again/</guid>
		<description><![CDATA[A pretty smart dude I worked with once told this story of a team he was on.&#160; They spent a few days, maybe even a week, deploying their app.&#160; It was painful, obviously.&#160; They’re response: “That sucked.&#160; Let’s do it again tomorrow.” Most people try to avoid hard things or at least delay them until [...]]]></description>
			<content:encoded><![CDATA[<p>A <a href="https://twitter.com/#!/RbKeefer" target="_blank">pretty smart dude</a> I worked with once told this story of a team he was on.&#160; They spent a few days, maybe even a week, deploying their app.&#160; It was painful, obviously.&#160; They’re response: “That sucked.&#160; Let’s do it again tomorrow.”</p>
<p>Most people try to avoid hard things or at least delay them until they have a good reason, but some things, important things… we should do those more often.&#160; We need to practice the hard things.&#160; They in turn become less risky and less scary bookends to our prideful efforts.</p>
<p>Testing is one of those things.</p>
<p>A few months back there was a thread going on the <a href="http://scrum.org/" target="_blank">Scrum.org</a> <a href="http://www.scrum.org/professionalscrumdeveloper/" target="_blank">Professional Scrum Developer</a> Trainers list about topics to include in the future.&#160; Specifically this was in regards to <a href="http://www.scrum.org/professionalscrumdeveloper/" target="_blank">the .Net flavor</a> of the course, because we were getting updates about what was coming down the pipe in the tooling.&#160; My excitement in that course has always focused on testing and with Jason Zander announcing <a href="http://blogs.msdn.com/b/jasonz/archive/2011/05/16/announcing-alm-roadmap-in-visual-studio-vnext-at-teched.aspx" target="_blank">continuous testing</a> for all the major test runners in Visual Studio vNext that was my suggestion.</p>
<p><a href="https://twitter.com/#!/adamcogan" target="_blank">Adam Cogan</a>, a smart dude in his own right, followed up asking me to describe why I thought that was such a big deal.&#160; I sent a rather long reply that I found useful today while describing the <a href="http://blog.mountaingoatsoftware.com/the-forgotten-layer-of-the-test-automation-pyramid" target="_blank">testing pyramid</a> to coworker <a href="http://twitter.com/stevemgentile" target="_blank">Steve Gentile</a>.&#160; I thought I’d provide that reply here and get everyone’s thoughts:</p>
<blockquote><p>We give <a href="http://patrickwilsonwelsh.com/?p=32">passing</a> <a href="http://jonkruger.com/blog/2010/02/08/the-automated-testing-triangle/">credence</a> to the idea of fast tests that run often versus slow tests that we expand to include before checkin/commit or during automated build (gated).&#160; Unfortunately, the later becomes a catch all for the oops, just got lazy scenario.&#160; </p>
<p>I remember when I first got the automated testing bug.&#160; I wrote some tests (calling them unit tests) that integrated with a 3<sup>rd</sup> party tool, gave great coverage and awesome feedback.&#160; We knew within 5-10 minutes if a new 3<sup>rd</sup> party version could be released.&#160; Giant leap.&#160; The next step, though, was hidden.&#160; I would code for 20, 30, 90 minutes or more and then run my tests while I grabbed a <a href="http://www.speedway.com/FoodAndDrink/GourmetRecipes.aspx">cappuccino</a>.</p>
<p>My current passer-by, rock your world tip/tool is <a href="ncrunch.net">NCrunch</a> for .Net or <a href="https://github.com/guard/guard">Guard</a> for everyone else (we need this).&#160; Autotest.Net was the first try from James Avery, but it didn’t have any traction and was unstable at best.&#160; Most teams have tests, but they aren’t using them effectively.&#160;&#160; (Ok, <a href="http://nuget.org/">Nuget</a> and the <a href="http://docs.nuget.org/docs/workflows/using-nuget-without-committing-packages">no-commit pattern</a> is a <a href="http://twitter.com/#!/cromwellryan/status/99302447855566848">very close second</a>!)</p>
<p>I run a group call <a href="http://cincycleancoders.com/">Cincy Clean Coders</a>.&#160; We do katas, often as a whole group.&#160; The first <a href="http://codingdojo.org/cgi-bin/wiki.pl?RandoriKata">Randori</a> kata we did was eye opening for the audience.&#160; Someone started refactoring to solve a red test and another person threw a fit.&#160; “What are you doing?!&#160; You’re red!&#160; You can’t refactor when your red.”&#160; The driver didn’t intend to be refactoring, they were just solving the current red test in their mind.&#160; They didn’t realize they were mixing many steps into one.&#160; There is a mental burden to doing the simplest thing, running the tests, and only then refactoring.</p>
<p>Teams make a great jump when they automate their important tests.&#160; Nightly feedback from QTP, Test Pro, or Coded UI is a big step.&#160; Consciously mixing unit, integration and acceptance tests is amazing.&#160; Our current tools mandate the start of the feedback loop be a conscious decision.&#160; “So all those changes, wonder if things are still working?&#160; Let’s find out.”&#160; We don’t say it, but that’s how we act.</p>
<p>When your tests run every time you pause (NCrunch) or save a file (Guard) you come to expect feedback NOW.&#160; You skip even CTRL+R,Y until your “finished”, only to find you just did 3,5, 10 refactorings.&#160; Which one caused the problem?&#160; Or you write a test that calls a web service, taking .65 seconds.&#160; Pretty soon “fast” tests take 30-60 seconds (or more!) and your CI build takes 20 minutes.</p>
<p>Continuous testing is (IMO) the next step in shortening the feedback loop.&#160; You start organizing your tests more effectively (or at all).&#160; In good environments, I even use this as a chance to commit.&#160; I now have the luxury of completely ignoring the path I took to my current source situation.&#160; Get into a tizzy, reset/undo checkout.&#160; Committing 10-20 times in an hour isn’t uncommon here.&#160; Neither is branching half a dozen times.</p>
<p>In the PSD I can demo and talk to the importance of running tests often and having confidence, but a blaring red failure on the screen for that last edit really hits home.</p>
</blockquote>
<p>I want your test suite to be an invaluable tool.&#160; Continuous testing is one of those pit of success kind of things.&#160; We need more of those.&#160; But <a href="https://twitter.com/#!/hotgazpacho/status/154385763306438657" target="_blank">when signals pop up</a> solve the <a href="https://twitter.com/#!/hotgazpacho/status/154386804085227520" target="_blank">real problem</a>.&#160; Don’t delay the pain.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.cromwellhaus.com/2012/01/your-test-suite-sucks-do-it-again/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Determine Framework Version &amp; Profile in a #NuGet Install.ps1</title>
		<link>http://blog.cromwellhaus.com/2011/03/determine-framework-version-profile-in-a-nuget-install-ps1/</link>
		<comments>http://blog.cromwellhaus.com/2011/03/determine-framework-version-profile-in-a-nuget-install-ps1/#comments</comments>
		<pubDate>Fri, 25 Mar 2011 01:01:07 +0000</pubDate>
		<dc:creator>cromwellryan</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Nuget]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[WPF]]></category>

		<guid isPermaLink="false">http://blog.cromwellhaus.com/2011/03/determine-framework-version-profile-in-a-nuget-install-ps1/</guid>
		<description><![CDATA[[Updated: @davidfowl suggested using the FrameworkName rather than parsing myself.&#160; Thanks!] I’m working on the Caliburn.Micro Nuget package and one of the things that we need is to add a default Bootstrapper, ShellView, and ShellViewModel to your project.&#160; One awesome thing Rob Eisenberg has done is provide WPF, Silverlight and WP7 versions of Caliburn.Micro.&#160; Unfortunately, [...]]]></description>
			<content:encoded><![CDATA[<p><em>[Updated: </em><a href="http://twitter.com/davidfowl" target="_blank"><em>@davidfowl</em></a><em> suggested using the FrameworkName rather than parsing myself.&#160; Thanks!]</em></p>
<p>I’m working on the <a href="http://caliburnmicro.codeplex.com/" target="_blank">Caliburn.Micro</a> <a href="http://nuget.codeplex.com/" target="_blank">Nuget</a> package and one of the things that we need is to add a default Bootstrapper, ShellView, and ShellViewModel to your project.&#160; One awesome thing Rob Eisenberg has done is provide WPF, Silverlight and WP7 versions of <a href="http://caliburnmicro.codeplex.com/" target="_blank">Caliburn.Micro</a>.&#160; Unfortunately, the platforms are different enough that these three pieces we would like to add are different.</p>
<p>I say this is unfortunate only because <a href="http://nuget.codeplex.com/" target="_blank">Nuget</a> doesn’t support framework and profile specific content through conventions.&#160; That’s only <a href="http://nuget.codeplex.com/documentation?title=Creating%20a%20Package" target="_blank">available for binaries</a>.&#160; It does, however, provide hooks into the install process via PowerShell.&#160; </p>
<p>Maybe you see where I’m headed…</p>
<p>The hard part for me was figuring out the framework version of the project targeted.&#160; In the end, here’s how you can pull the TargetFrameworkMoniker in your install.ps1:</p>
<blockquote><p>param($rootPath, $toolsPath, $package, $project)</p>
<p>&#160; $moniker = $project.Properties.Item(&quot;TargetFrameworkMoniker&quot;).Value</p>
<p>&#160; $framework= new-object System.Runtime.Versioning.FrameworkName($moniker)</p>
<p>&#160; write-host &quot;Identifier: &quot; $framework.Identifier&#160; <br />&#160; write-host &quot;Version: &quot; $framework.Version       <br />&#160; write-host &quot;Profile: &quot; $framework.Profile</p>
<p># WPF4 will be NETFramework,Version=v4.0,Profile=Client      <br /># SL4 will be Silverlight,Version=v4.0       <br /># WP7 will be Silverlight,Version=v4.0,Profile=WindowsPhone</p>
</blockquote>
<p>Happy packaging!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.cromwellhaus.com/2011/03/determine-framework-version-profile-in-a-nuget-install-ps1/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Cincinnati Professional Scrum Developer .Net Course (Feb 21st)</title>
		<link>http://blog.cromwellhaus.com/2011/01/cincinnati-professional-scrum-developer-net-course-feb-21st/</link>
		<comments>http://blog.cromwellhaus.com/2011/01/cincinnati-professional-scrum-developer-net-course-feb-21st/#comments</comments>
		<pubDate>Tue, 04 Jan 2011 17:45:58 +0000</pubDate>
		<dc:creator>cromwellryan</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[Scrum]]></category>
		<category><![CDATA[Training]]></category>

		<guid isPermaLink="false">http://blog.cromwellhaus.com/index.php/2011/01/cincinnati-professional-scrum-developer-net-course-feb-21st/</guid>
		<description><![CDATA[[Correction: This is the first for the new year.&#160; This certainly is not the first ever.] I’m happy to announce that our first Professional Scrum Developer course of 2011 is scheduled for February 21st.&#160; This is a course which practices 5 days of craftsmanship, collaboration, and sustainable pace via the Scrum framework.&#160; Practice is the [...]]]></description>
			<content:encoded><![CDATA[<p><em>[Correction: This is the first for the new year.&#160; This certainly is not the first ever.]</em></p>
<p>I’m happy to announce that our first <a href="http://www.scrum.org/professionalscrumdeveloper/">Professional Scrum Developer</a> course of 2011 is scheduled for February 21st.&#160; This is a course which practices 5 days of craftsmanship, collaboration, and sustainable pace via the Scrum framework.&#160; Practice is the key to success and there is no better way to build a successful Agile team than to work together, continuously with a coach available to guide you through unfamiliar terrain.</p>
<p>Every team has it’s own happy path to a successful, self-organizing, self-managing Scrum team and it is not an easy one to navigate.&#160; During these 5 days we will experience brown-field product development using <em>Modern Engineering Practices</em> such as TDD, Continuous Integration, Refactoring, and more.&#160; Our case study is an ASP.Net MVC application.</p>
<p>Register for the course with <a href="http://www.maxtrain.com/classes/classInfo.aspx?id=MA-PSDev">MaxTrain.com</a> who graciously provides the facility and infrastructure.&#160; </p>
<p><a href="http://www.scrum.org/">Scrum.org</a>, founded by Ken Schwaber <a href="http://www.scrum.org/about/"><em>to improve the profession of software development so that developers love their work and our customers love working with developers</em></a><em>, </em>describes the Professional Scrum Developer course in detail.&#160; You’ll also find the course <a href="http://www.scrum.org/psd-net-syllabus/">syllabus</a> here.</p>
<p>Look forward to seeing you there.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.cromwellhaus.com/2011/01/cincinnati-professional-scrum-developer-net-course-feb-21st/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Greatest Overeager Design Decision: Assignment</title>
		<link>http://blog.cromwellhaus.com/2010/12/greatest-overeager-design-decision-assignment/</link>
		<comments>http://blog.cromwellhaus.com/2010/12/greatest-overeager-design-decision-assignment/#comments</comments>
		<pubDate>Fri, 17 Dec 2010 22:01:24 +0000</pubDate>
		<dc:creator>cromwellryan</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Craftsmanship]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[Testing]]></category>

		<guid isPermaLink="false">http://blog.cromwellhaus.com/index.php/2010/12/greatest-overeager-design-decision-assignment/</guid>
		<description><![CDATA[In a getting back to basics moment of mine, I started through the TDD Problems.&#160; I found myself on the Console Interaction problem and decided to take a step back from after refactoring.&#160; This is what I saw: var shape = _console.AskForShape(); var rectange = GetRectange(); _console.PrintArea(rectange.ComputeArea()); _console.PrintCircumference(rectange.ComputeCircumference()); ReSharper was hinting at it, but it [...]]]></description>
			<content:encoded><![CDATA[<p>In a getting back to basics moment of mine, I started through the <a href="http://sites.google.com/site/tddproblems/">TDD Problems</a>.&#160; I found myself on the <a href="http://sites.google.com/site/tddproblems/all-problems-1/Console-interaction">Console Interaction problem</a> and decided to take a step back from after refactoring.&#160; This is what I saw:</p>
<blockquote><p>var shape = _console.AskForShape();</p>
<p>var rectange = GetRectange();</p>
<p>_console.PrintArea(rectange.ComputeArea());     <br />_console.PrintCircumference(rectange.ComputeCircumference());</p>
</blockquote>
<p>ReSharper was hinting at it, but it should have screamed.&#160; Why do I need to hang on to shape?&#160; I can imagine my mindset at the time.&#160; I was worried about the inevitable <em>decision</em> I would have to make about 20 tests down the road.&#160; That little assignment was the beginning of my overeager, premature design.</p>
<p>Question your code.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.cromwellhaus.com/2010/12/greatest-overeager-design-decision-assignment/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Where did Alt.Net go?</title>
		<link>http://blog.cromwellhaus.com/2010/08/where-did-alt-net-go/</link>
		<comments>http://blog.cromwellhaus.com/2010/08/where-did-alt-net-go/#comments</comments>
		<pubDate>Wed, 11 Aug 2010 13:01:10 +0000</pubDate>
		<dc:creator>cromwellryan</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Community]]></category>

		<guid isPermaLink="false">http://blog.cromwellhaus.com/index.php/2010/08/where-did-alt-net-go/</guid>
		<description><![CDATA[These last few weeks have seen a flurry of emotions from the .Net community.&#160; It appears that a few product releases and a presumptive priority change for IronRuby have caused the world to come crashing down and passengers of the .Net ship to jump overboard.&#160; I’m glad I don’t work for these emotionally unstable individuals, [...]]]></description>
			<content:encoded><![CDATA[<p>These last few weeks have seen a flurry of emotions from the .Net community.&#160; It appears that a few product releases and a presumptive priority change for IronRuby have caused the world to come crashing down and passengers of the .Net ship to jump overboard.&#160; I’m glad I don’t work for these emotionally unstable individuals, because if we had any debate (I’m aggressive and loud) I’d be concerned they would run from the room crying or worse yet, quit (seems more likely from the rhetoric I hear).&#160; If this is what the Alt.Net community is made of then OSS in the world of .Net has absolutely no chance and the outside OSS world should fear their new recruits.</p>
<p>During the late ‘90s and early 2000s immense business systems where built on the powerhouse platform known as Microsoft Office.&#160; Having worked, well, at all, I’ve seen first hand the ugly, but quite impressive apps built by accountants and marketiers (mark it down, that’s my word) generating great revenues or savings for their companies.&#160; I have replied to requests to “make that an enterprise web app” with “that will fail miserably, keep using it.”&#160; The apps are a disaster waiting to happen themselves, but that’s why we have enterprise backup systems.&#160; It’s just not worth the IT Department’s time to rebuild Excel when it is perfectly suited for their purpose.</p>
<p>In come WebMatrix, LightSaber, I mean LightSwitch, and all the other “low-end” tools.&#160; These are obviously a trend that show Microsoft is abandoning the “high-end” developer (are we really that pompous that we consider ourselves “high-end”, get over yourself you geek.&#160; I bet they make more cash per feature than you).&#160; Or could it be that they are making up for the fact that the last great act of feature development shown by Microsoft to the “low-end”, revenue generating, feature shipping developer is the <em><u>Ribbon Bar</u></em>.&#160; I guess you could add SharePoint in there, but I won’t bate you.&#160; </p>
<p>Since 2002, we’ve seen 4 iterations of Silverlight, 4 versions of the Framework, WPF, WCF, the rise of PnP, 5 versions of Visual Studio, Azure, Hyper-V, Team Foundation Server (like it or not), and a dearth of other tools in the same time that <a href="http://en.wikipedia.org/wiki/Microsoft_Excel#Excel_2000">Excel has received</a>… drum role… the Ribbon.&#160; Yes there are nicer icons to represent values and you can make prettier tables or charts, but seriously they still use VBA!&#160; In that same time period we’ve seen 2, count them, 2 releases of&#160; the platform on which many businesses survive.</p>
<p>So yes, Microsoft has thrown the Excel and Access productivity worker (not lowend developer) a bone.&#160; They’ve made it easier for you to say, “Sorry, I don’t do Master-Details forms.&#160; Here’s WebMatrix, call me when you want to ship.”&#160; Get over it, start an OSS project or, if you liked it so much, help the IronRuby team build that platform up.&#160; Whatever you do, stop whining and do something.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.cromwellhaus.com/2010/08/where-did-alt-net-go/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>ReSharper Test Runner and MSTest Projects</title>
		<link>http://blog.cromwellhaus.com/2010/07/resharper-test-runner-and-mstest-projects/</link>
		<comments>http://blog.cromwellhaus.com/2010/07/resharper-test-runner-and-mstest-projects/#comments</comments>
		<pubDate>Wed, 21 Jul 2010 13:17:08 +0000</pubDate>
		<dc:creator>cromwellryan</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false">http://blog.cromwellhaus.com/index.php/2010/07/resharper-test-runner-and-mstest-projects/</guid>
		<description><![CDATA[One of my biggest irritants with the Unit Testing ecosystem is that each runner does things a little different. Gallio has helped solve this to some extent, but even that hasn’t solved all the problems that come with content or resource file deployments, coverage settings, etc.&#160; Gallio’s goal is noble if not arrogant, become the [...]]]></description>
			<content:encoded><![CDATA[<p>One of my biggest irritants with the Unit Testing ecosystem is that each runner does things a little different. <a href="http://gallio.org/">Gallio</a> has helped solve this to some extent, but even that hasn’t solved all the problems that come with content or resource file deployments, coverage settings, etc.&#160; Gallio’s goal is noble if not arrogant, become the <em>Runner to Rule Them All.</em>&#160; </p>
<p>Unlikely.<em>&#160; </em></p>
<p><a href="http://www.jetbrains.com/resharper/index.html">ReSharper</a>, on the other hand, has taken the Switzerland approach and tries to be true to each testing frameworks settings and run modes.&#160; It has a gap in regards to MSTest at this point, though.&#160; (Who uses MSTest you say?&#160; Lots of people.&#160; You wanted unit testing to become common place, remember?&#160; Stop complaining.)&#160; ReSharper gives you this nasty warning when running your MSTests with Code Coverage enabled.</p>
<p><a href="http://blog.cromwellhaus.com/wp-content/uploads/2010/07/image.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" class="wlDisabledImage" title="image" border="0" alt="image" src="http://blog.cromwellhaus.com/wp-content/uploads/2010/07/image_thumb.png" width="281" height="169" /></a></p>
<p>See MSTest is actually pretty sweet when it comes to data capture.&#160; It might not be blazing fast, but it lets you capture an awful lot of information in different situations.&#160; In order to support those different situations nicely there is this file type called Test Settings (*.testsettings).&#160; <a href="http://blog.cromwellhaus.com/wp-content/uploads/2010/07/image1.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" class="wlDisabledImage" title="image" border="0" alt="image" align="right" src="http://blog.cromwellhaus.com/wp-content/uploads/2010/07/image_thumb1.png" width="244" height="182" /></a>Test Settings files live in your solution folder and you can have a bunch of them.&#160; In fact, Visual Studio 2010 gives you two by default: Local.testsettings and TraceAndTestImpact.testsettings.&#160; </p>
<p>Local.testsettings doesn’t capture anything by default, but one of the first thing everyone tends to look for when running tests is <a href="http://en.wikipedia.org/wiki/Code_coverage">code coverage</a>.&#160; Since Local.testsettings are their default and people don’t realize you can change your active test settings they open Local.testsettings, choose Data and Diagnostics and check Code Coverage (and probably other things that sound interesting).</p>
<p><a href="http://blog.cromwellhaus.com/wp-content/uploads/2010/07/image2.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" class="wlDisabledImage" title="Enabling Code Coverage in Data and Diagnostics of Local.testsettings" border="0" alt="Enable Code Coverage in Data and Diagnostics of Local.testsettings" src="http://blog.cromwellhaus.com/wp-content/uploads/2010/07/image_thumb2.png" width="244" height="221" /></a></p>
<p>Now you’ve eliminated Resharper as a Test Runner.&#160; But you don’t have too!&#160; Remember how I said you can have a bunch of those .testsettings files and eluded to the fact that one can be made <em>Active.</em>&#160; Here’s what you’re going to do:</p>
<ol>
<li>Right click the Solution Items folder (don’t put them in a different solution folder, VS doesn’t like that, sorry).</li>
<li>Click Add –&gt; New Item </li>
<li>Under Installed Templates (VS 2010) select Test Settings.</li>
<li>Name the new file ReSharper.testsettings (or whatever makes you happy really) and click ok.</li>
</ol>
<p>The Test Settings editor dialog will come up, but you don’t need to change a thing if you don’t want or need.&#160; Data and Diagnostics will be empty which is good for ReSharper.&#160; At this point, you can go to the Test menu option, open Select Active Test Settings and choose your new settings (ReSharper.testsettings in our example).</p>
<p>That’s it, use ReSharper all you like.&#160; There are some other nice things that ReSharper will do for you in regards to abiding by deployment options for content files and things like that, but we’ll save that for a different day.&#160; <a href="http://screencast.com/t/NWQwYWVj" target="_blank">Here’s a quick video</a> that highlights everything I’ve outlined here.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.cromwellhaus.com/2010/07/resharper-test-runner-and-mstest-projects/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Strategy Pattern with Castle Windsor</title>
		<link>http://blog.cromwellhaus.com/2009/10/strategy-pattern-with-castle-windsor/</link>
		<comments>http://blog.cromwellhaus.com/2009/10/strategy-pattern-with-castle-windsor/#comments</comments>
		<pubDate>Fri, 30 Oct 2009 19:37:56 +0000</pubDate>
		<dc:creator>cromwellryan</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[IoC]]></category>
		<category><![CDATA[Windsor]]></category>

		<guid isPermaLink="false">http://blog.cromwellhaus.com/index.php/2009/10/strategy-pattern-with-castle-windsor/</guid>
		<description><![CDATA[One of the tangent patterns associated with isolation or Single Responsibility is the Strategy Pattern.  I use Castle Windsor as my IoC of choice and I had hoped there was some black magic built in to make the Strategy Pattern dead simple.  Turns out there is and there isn’t. What is the Strategy Pattern The [...]]]></description>
			<content:encoded><![CDATA[<p>One of the tangent patterns associated with isolation or <a href="http://en.wikipedia.org/wiki/Single_responsibility_principle" target="_blank">Single Responsibility</a> is the <a href="http://en.wikipedia.org/wiki/Strategy_pattern" target="_blank">Strategy Pattern</a>.  I use <a href="http://www.castleproject.org/container/index.html" target="_blank">Castle Windsor</a> as my <a href="http://en.wikipedia.org/wiki/Inversion_of_control" target="_blank">IoC</a> of choice and I had hoped there was some black magic built in to make the Strategy Pattern dead simple.  Turns out there is and there isn’t.</p>
<p><strong>What is the Strategy Pattern</strong></p>
<p><span style="color: #2e2e2e;">The strategy pattern is a way of isolating what would often be found in a case statement.  The bland example being calculating Sales tax on an Order.  Each state and/or country has its own tax calculation and rather than</span></p>
<div style="line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text; border: gray 1px solid; padding: 4px;">
<div style="line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> Process(Order order) {</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   2:</span>     <span style="color: #0000ff">switch</span>(order.Country) {</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   3:</span>         <span style="color: #0000ff">case</span> <span style="color: #006080">"USA"</span>:</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   4:</span>             order.Total = order.Subtotal * .07;</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   5:</span>             <span style="color: #0000ff">break</span>;</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   6:</span>         <span style="color: #0000ff">case</span> <span style="color: #006080">"Canada"</span>:</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   7:</span>             order.Total = order.Subtotal * .0985;</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   8:</span>             <span style="color: #0000ff">break</span>;</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   9:</span>     }</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">  10:</span> </pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">  11:</span>     <span style="color: #008000">// ...</span></pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">  12:</span> }</pre>
</div>
</div>
<p>you should be breaking each calculation out into different ITaxStrategy implementations and consuming them like so:</p>
<div style="line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text; border: gray 1px solid; padding: 4px;">
<div style="line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> Process(Order order) {</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   2:</span>     var strategy = _taxStrategyFactory.GetStrategyForOrder(order);</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   3:</span> </pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   4:</span>     var salesTax = strategy.CalculateSalesTax(order);</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   5:</span> </pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   6:</span>     order.SalesTax = salesTax;</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   7:</span>     order.Total = order.SubTotal + order.SalesTax;</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   8:</span> }</pre>
</div>
</div>
<p>The question remains, how to eliminate the conditional logic in TaxStrategyFactory determining <em>which</em> strategy is chosen.  The solution is to set up a convention for discovering the available strategies and delegating the criteria to the Strategy itself.</p>
<p><strong>Discovery</strong></p>
<p><span style="color: #2e2e2e;">The concept here is that we don’t have to “hook up” any new Tax Strategy to our Processing mechanism, we just “publish” new ones in a known way and they are picked up simply based on their existence.  This is often referred to as <a href="http://en.wikipedia.org/wiki/Convention_over_configuration" target="_blank">Convention Over Configuration</a>.  We accomplish this with Castle Windsor with the <a href="http://using.castleproject.org/display/IoC/Fluent+Registration+API" target="_blank">Fluent Registration API</a>:</span></p>
<div style="line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text; border: gray 1px solid; padding: 4px;">
<div style="line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   1:</span> container</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   2:</span>     .Register(AllTypes</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   3:</span>                   .FromAssembly(Assembly.GetExecutingAssembly())</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   4:</span>                   .Where(x =&gt; x.Name.EndsWith(<span style="color: #006080">"Strategy"</span>))</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   5:</span>                   .WithService.FirstInterface());</pre>
</div>
</div>
<p>This will register all classes found in the executing assembly which have the suffix “Strategy” as implementing the ITaxStrategy interface.  The second half of convention based discovery is consuming the ITaxStrategy implementations.  We can want to get all of these into the TaxStrategyFactory via a constructor array dependency:</p>
<div style="line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text; border: gray 1px solid; padding: 4px;">
<div style="line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">public</span> TaxStrategyFactory(<span style="color: #0000ff">params</span> ITaxStrategy[] taxStrategies)</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   2:</span> {</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   3:</span>     _taxStrategies = taxStrategies;</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   4:</span> }</pre>
</div>
</div>
<p>Unfortunately, Windsor doesn’t support arrays as dependencies by default.  Windsor has the concept of Resolvers (a strategy implementation itself) and we are going to have to tell it about the ArrayResolver which knows how to, err, resolve array dependencies:</p>
<div style="line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text; border: gray 1px solid; padding: 4px;">
<div style="line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   1:</span> container</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   2:</span>     .Kernel.Resolver.AddSubResolver(<span style="color: #0000ff">new</span> ArrayResolver(container.Kernel));</pre>
</div>
</div>
<p>Cool, so put these all together in our registration code and we get:</p>
<div style="line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text; border: gray 1px solid; padding: 4px;">
<div style="line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   1:</span> container</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   2:</span>     .Register(Component</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   3:</span>                   .For&lt;IOrderProcessor&gt;()</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   4:</span>                   .ImplementedBy&lt;OrderProcessor&gt;())</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   5:</span>     .Register(Component</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   6:</span>                   .For&lt;ITaxStrategyFactory&gt;()</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   7:</span>                   .ImplementedBy&lt;TaxStrategyFactory&gt;())</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   8:</span>     .Register(AllTypes</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   9:</span>                   .FromAssembly(Assembly.GetExecutingAssembly())</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">  10:</span>                   .Where(x =&gt; x.Name.EndsWith(<span style="color: #006080">"Strategy"</span>))</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">  11:</span>                   .WithService.FirstInterface());</pre>
</div>
</div>
<p>At this point we can kick of the true discovery chain of events through:</p>
<div style="line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text; border: gray 1px solid; padding: 4px;">
<div style="line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   1:</span> var processor = container.Resolve&lt;IOrderProcessor&gt;();</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   2:</span> </pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   3:</span> processor.Process(order);</pre>
</div>
</div>
<p><strong>Delegating Criteria</strong></p>
<p>So in OrderProcessor.Process we are asked the TaxStrategyFactory for the applicable ITaxStrategy implementation:</p>
<div style="line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text; border: gray 1px solid; padding: 4px;">
<div style="line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   1:</span> var strategy = _taxStrategyFactory.GetStrategyForOrder(order);</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   2:</span> </pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   3:</span> var salesTax = strategy.CalculateSalesTax(order);</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   4:</span> </pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   5:</span> //...</pre>
</div>
</div>
<p>  The question is, how did the factory determine which of the boundless implementations applies?  That’s the job of each ITaxStrategy itself.  Here’s the implementation of our factory:</p>
<div style="line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text; border: gray 1px solid; padding: 4px;">
<div style="line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">class</span> TaxStrategyFactory : ITaxStrategyFactory</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   2:</span> {</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   3:</span>     <span style="color: #0000ff">private</span> <span style="color: #0000ff">readonly</span> ITaxStrategy[] _taxStrategies;</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   4:</span> </pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">public</span> TaxStrategyFactory(<span style="color: #0000ff">params</span> ITaxStrategy[] taxStrategies)</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   6:</span>     {</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   7:</span>         _taxStrategies = taxStrategies;</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   8:</span>     }</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   9:</span> </pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">  10:</span>     <span style="color: #0000ff">public</span> ITaxStrategy GetStrategyForOrder(Order order)</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">  11:</span>     {</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">  12:</span>         <span style="color: #0000ff">return</span> _taxStrategies.FirstOrDefault(x =&gt; x.IsApplicable(order));</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">  13:</span>     }</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">  14:</span> }</pre>
</div>
</div>
<p>Notice how the TaxStrategyFactory depends on all of the ITaxStrategy implementations.  It then uses the ITaxStrategy.IsApplicable(Order) method as criteria for a FirstOrDefault call.  Here’s an example TaxStrategy for any Order with country “USA”:</p>
<div style="line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text; border: gray 1px solid; padding: 4px;">
<div style="line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> USTaxStrategy : ITaxStrategy</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   2:</span>     {</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   3:</span>         <span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">readonly</span> IDictionary&lt;<span style="color: #0000ff">string</span>, <span style="color: #0000ff">double</span>&gt; TaxRates = <span style="color: #0000ff">new</span> Dictionary&lt;<span style="color: #0000ff">string</span>, <span style="color: #0000ff">double</span>&gt;()</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   4:</span>                                                                    {</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   5:</span>                                                                        {<span style="color: #006080">"OH"</span>, 7.0},</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   6:</span>                                                                        {<span style="color: #006080">"MI"</span>, 6.25},</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   7:</span>                                                                    };</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   8:</span>         <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> CalculateSalesTax(Order order)</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">   9:</span>         {</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">  10:</span>             var rate = TaxRates[order.State];</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">  11:</span> </pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">  12:</span>             <span style="color: #0000ff">return</span> (order.SubTotal * (rate / 100));</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">  13:</span>         }</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">  14:</span> </pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">  15:</span>         <span style="color: #0000ff">public</span> <span style="color: #0000ff">bool</span> IsApplicable(Order order)</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">  16:</span>         {</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">  17:</span>             <span style="color: #0000ff">return</span> order.Country == <span style="color: #006080">"USA"</span>;</pre>
<pre style="line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">  18:</span>         }</pre>
<pre style="line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: consolas, &quot;Courier New&quot;, courier, monospace; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span style="color: #606060">  19:</span>     }</pre>
</div>
</div>
<p><span style="color: #242626;"> </span></p>
<p><span style="color: #242626;">You can download the sample project that goes along with this <a href="http://code.cromwellhaus.com/WindsorStrategySample.zip" target="_self">here</a>.</span></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.cromwellhaus.com/2009/10/strategy-pattern-with-castle-windsor/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Property Undo/Redo Support</title>
		<link>http://blog.cromwellhaus.com/2009/07/property-undo-redo-support/</link>
		<comments>http://blog.cromwellhaus.com/2009/07/property-undo-redo-support/#comments</comments>
		<pubDate>Sat, 04 Jul 2009 19:06:03 +0000</pubDate>
		<dc:creator>cromwellryan</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[WPF]]></category>

		<guid isPermaLink="false">/blogs/ryanc/archive/2009/07/04/property-undo-redo-support.aspx</guid>
		<description><![CDATA[Undo/Redo support is one of those golden features that really differentiate a client app from many web apps.&#160; There have been a number of methods/techniques to provide this support that I’ve run across from brute force, to the memento pattern, but none that lit any fire for me. Here’s my answer to the problem using [...]]]></description>
			<content:encoded><![CDATA[<p>Undo/Redo support is one of those golden features that really differentiate a client app from many web apps.&#160; There have been a number of methods/techniques to provide this support that I’ve run across from brute force, to the <a href="http://www.codeproject.com/KB/cs/generic_undo_redo.aspx" target="_blank">memento pattern</a>, but none that lit any fire for me.</p>
<p>Here’s my answer to the problem using Anonymous methods and my first real attempt at creating (versus using) a Fluent Api.</p>
<p>The most common scenario for Undo/Redu support is form completion.&#160; In your Domain or View Model this is often tied to Two Way bound properties.&#160; Take the simple Person class:</p>
<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
<div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> Person</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">    <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> Name { get; set; }</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">    <span style="color: #0000ff">public</span> DateTime BirthDate { get; set; }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre>
</p></div>
</div>
<p>The question is how to provide undo/redo support for a form (WPF often in my case) bound to a Person.&#160; First, I create a ViewModel or Presenter for the Person class:</p>
<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
<div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> PersonViewModel : ViewModelBase</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">    <span style="color: #0000ff">private</span> <span style="color: #0000ff">readonly</span> Person _person;</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">&#160;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">    <span style="color: #0000ff">public</span> PersonViewModel(Person person)</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">    {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">        _person = person;</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">    }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">&#160;</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">    <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> Name</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">    {</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">        get { <span style="color: #0000ff">return</span> _person.Name; }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">        set</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">        {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">            _person.Name = <span style="color: #0000ff">value</span>;</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">            OnPropertyChanged(<span style="color: #006080">&quot;Name&quot;</span>);</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">        }</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">    }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">&#160;</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">    <span style="color: #0000ff">public</span> DateTime BirthDate</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">    {</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">        get { <span style="color: #0000ff">return</span> _person.BirthDate; }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">        set</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">        {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">            _person.BirthDate = <span style="color: #0000ff">value</span>;</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">            OnPropertyChanged(<span style="color: #006080">&quot;BirthDate&quot;</span>);</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">            OnPropertyChanged(<span style="color: #006080">&quot;Age&quot;</span>);</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">        }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">    }</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">&#160;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">    <span style="color: #0000ff">public</span> <span style="color: #0000ff">int</span> Age</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">    {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">        get</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">        {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">            var now = DateTime.Now;</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">            var age = now.Year - _person.BirthDate.Year;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">&#160;</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">            <span style="color: #0000ff">if</span> (now &lt; _person.BirthDate.AddYears(age))</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">                age--;</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">&#160;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">            <span style="color: #0000ff">return</span> age;</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">        }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">    }</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre>
</p></div>
</div>
<p>Notice that we have a calculated property Age based on the BirthDate.&#160; Any time we change BirthDate we want to make sure to notify that the Age is also changed, obviously.&#160; </p>
<p>Here is the Fluent way to register Undo/Redo support for our PersonViewModel.Name property:</p>
<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
<div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> Name</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span> {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span>     get { <span style="color: #0000ff">return</span> _person.Name; }</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span>     set</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     {</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>         var oldName = _person.Name;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>&#160; </pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span>         _undoRedoManager</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   9:</span>             .WithUndo(() =&gt; _person.Name = oldName)</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  10:</span>             .RepeatAfterBoth(() =&gt; OnPropertyChanged(<span style="color: #006080">&quot;Name&quot;</span>))</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  11:</span>             .Do(() =&gt; _person.Name = <span style="color: #0000ff">value</span>);</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  12:</span>     }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  13:</span> }</pre>
</p></div>
</div>
<p>Cool, but what is that doing?&#160; Well, it’s pretty simply.&#160; We are simply maintaining two queues; An Undo and a Redo queue.&#160; Here is the longer syntax, without the Fluent helper Api that makes that a little clearer:</p>
<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
<div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> Name</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">    get { <span style="color: #0000ff">return</span> _person.Name; }</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">    set</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">    {</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">        var oldName = _person.Name;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">&#160;</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">        _undoRedoManager.Push(() =&gt;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">                                  {</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">                                      _person.Name = oldName;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">                                      OnPropertyChanged(<span style="color: #006080">&quot;Name&quot;</span>);</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">                                  },</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">                                  () =&gt;</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">                                  {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">                                      _person.Name = <span style="color: #0000ff">value</span>;</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">                                      OnPropertyChanged(<span style="color: #006080">&quot;Name&quot;</span>);</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">                                  });</pre>
<pre style="border-bottom-style: none; 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: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">    }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre>
</p></div>
</div>
<p>
</p>
<p>This may not seem like much more, but if your Repeat part is more than one line, it gets a bit fragile.&#160; Being able to specify the “After” stuff once is important.</p>
<p>From here you can use the IUndoRedoManager.CanUndo(), IUndoRedoManager.CanRedo(), IUndoRedoManager.Redo() methods to go back and forth.&#160; Hook this up to your favorite ICommand implementation and you have most of what you might need. </p>
<p>&#160;</p>
<p><a href="http://code.cromwellhaus.com/cromwell.undoredo.zip" target="_blank">Here is the full project</a> with a WPF Sample and a VB sample.&#160; The VB version is a little ugly since it doesn’t support anonymous methods without a return, but it works.</p>
<p>If you have suggestions (on the Fluent Api especially) let me know.&#160; I’d really like to hear them.</p></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.cromwellhaus.com/2009/07/property-undo-redo-support/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Why Plain Old LINQ is so powerful</title>
		<link>http://blog.cromwellhaus.com/2008/07/why-plain-old-linq-is-so-powerful/</link>
		<comments>http://blog.cromwellhaus.com/2008/07/why-plain-old-linq-is-so-powerful/#comments</comments>
		<pubDate>Thu, 31 Jul 2008 19:04:20 +0000</pubDate>
		<dc:creator>cromwellryan</dc:creator>
				<category><![CDATA[.Net]]></category>

		<guid isPermaLink="false">/blogs/ryanc/archive/2008/07/31/why-plain-old-linq-is-so-powerful.aspx</guid>
		<description><![CDATA[Ian Griffiths posted a great example of how powerful and cool LINQ is when used in everyday code (it&#8217;s not all about databases people). If you haven&#8217;t started to learn how to incorporate this awesome toolset into your daily coding life, you&#8217;re killing yourself.&#160; No excuses.]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.interact-sw.co.uk/iangblog/" target="_blank">Ian Griffiths</a> posted a <a href="http://www.interact-sw.co.uk/iangblog/2008/07/30/linq-box-aggregation" target="_blank">great example</a> of how powerful and cool LINQ is when used in everyday code (it&#8217;s not all about databases people).</p>
<p>If you haven&#8217;t started to learn how to incorporate this awesome toolset into your daily coding life, you&#8217;re killing yourself.&nbsp; No excuses.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.cromwellhaus.com/2008/07/why-plain-old-linq-is-so-powerful/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Roadblock to Mocking Unit Tests</title>
		<link>http://blog.cromwellhaus.com/2008/07/roadblock-to-mocking-unit-tests/</link>
		<comments>http://blog.cromwellhaus.com/2008/07/roadblock-to-mocking-unit-tests/#comments</comments>
		<pubDate>Tue, 15 Jul 2008 13:58:51 +0000</pubDate>
		<dc:creator>cromwellryan</dc:creator>
				<category><![CDATA[.Net]]></category>

		<guid isPermaLink="false">/blogs/ryanc/archive/2008/07/15/roadblock-to-mocking-unit-tests.aspx</guid>
		<description><![CDATA[I&#8217;ve been a faithful unit tester for a few years now.&#160; I may not do everything by the book (I think end-to-end unit tests are helpful), but I do get good coverage most of the time.&#160; That said, I&#8217;ve found myself unable to use any of the Mock frameworks out there, because I don&#8217;t use [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been a faithful unit tester for a few years now.&nbsp; I may not do everything by the book (I think end-to-end unit tests are helpful), but I do get good coverage most of the time.&nbsp; That said, I&#8217;ve found myself unable to use any of the Mock frameworks out there, because I don&#8217;t use your typical Dependency Injection pattern.&nbsp; That is, I don&#8217;t like &#8220;building up&#8221; very freaking instance with all the &#8220;Provider&#8221; or &#8220;Service&#8221; interfaces I&#8217;m might need in the possible life of a business object.&nbsp; Yes, if your Customer class is only going to create or save an Order, it feels OK, but my objects are busy dude, so I&#8217;d need the longest constructor of all time.</p>
<p>I prefer <a href="http://search.live.com/results.aspx?q=dependency+resolution+mock&amp;form=QBRE" target="_blank">Dependency Resolution</a>.&nbsp; I don&#8217;t use any fancy framework, I just use a good old, DI.Resolve&lt;IBusyBee&gt;() and go about my business.&nbsp; It works wonderfully, it&#8217;s light-weight (cause I don&#8217;t use configuration based DI frameworks), and it&#8217;s my baby.</p>
<p>That said, it&#8217;s also been the roadblock to my mocking foray.&nbsp; That was, until I &#8220;got it&#8221; today.&nbsp; Long story short, here&#8217;s how I roll:</p>
<p><strong>Create a Mock DI Container&#8230;</strong></p>
<pre class="code"><span style="color: #2b91af">Mock</span>&lt;<span style="color: #2b91af">IDIContainer</span>&gt; mockContainer = <span style="color: blue">new </span><span style="color: #2b91af">Mock</span>&lt;<span style="color: #2b91af">IDIContainer</span>&gt;();</pre>
<p><strong>Create the Injected Mock instances&#8230;</strong></p>
<p><span style="color: #2b91af">Mock</span>&lt;<span style="color: #2b91af">INotificationManager</span>&gt; mockNotifMgr = <span style="color: blue">new</span><span style="color: #2b91af">Mock</span>&lt;<span style="color: #2b91af">INotificationManager</span>&gt;();<br /><span style="color: #2b91af">Mock</span>&lt;<span style="color: #2b91af">IRepository</span>&gt; mockRepository = <span style="color: blue">new</span><span style="color: #2b91af">Mock</span>&lt;<span style="color: #2b91af">IRepository</span>&gt;();</p>
<p><strong>Tell the mock IDIContainer to return the mock instances when asked&#8230;</strong></p>
<pre class="code">mockContainer.Expect(c =&gt; c.Resolve&lt;<span style="color: #2b91af">INotificationManager</span>&gt;(<span style="color: blue">null</span>)).Returns(mockNotifMgr.Object);
mockContainer.Expect(c =&gt; c.Resolve&lt;<span style="color: #2b91af">IRepository</span>&gt;(<span style="color: blue">null</span>)).Returns(mockRepository.Object);
</pre>
<p><strong>Mock your heart out&#8230;</strong></p>
<pre class="code">mockNotifMgr.Expect(mgr =&gt; mgr.NotifyEmailConfirmation(<span style="color: #2b91af">It</span>.IsAny&lt;<span style="color: #2b91af">Member</span>&gt;())).AtMostOnce();
</pre>
<pre class="code"><span style="color: #2b91af">Member</span>.Register(<span style="color: #a31515">"username"</span>, <span style="color: #a31515">"firstname"</span>, <span style="color: #a31515">"lastname"</span>, <span style="color: #a31515">"ryan@myus.com"</span>);

mockContainer.VerifyAll();
mockNotifMgr.VerifyAll();
</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>I&#8217;m very happy to have finally jumped on the Moq bandwagon as it will certainly make some unit tests much easier to write.&nbsp; Maybe I&#8217;ll even do the test first part more faithfully now.&nbsp; </p>
<p>FYI, I use my own DI framework which is just a glorified HashTable.&nbsp; It works for me and it is quick.&nbsp; <a href="http://moq.googlecode.com/" target="_blank">Moq</a> has also become my Mock framework of choice for no good reason other than I downloaded it first.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.cromwellhaus.com/2008/07/roadblock-to-mocking-unit-tests/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
	</channel>
</rss>

