<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2837647869424561922</id><updated>2012-02-04T10:42:07.941-08:00</updated><category term='c#'/><category term='enum'/><category term='TDD'/><category term='DataAnnotations'/><category term='Validation'/><category term='security'/><category term='Moq'/><category term='Stackoverflow'/><category term='dataset'/><category term='F#'/><category term='Unit Testing'/><category term='WPF'/><category term='Programming'/><category term='.NET'/><title type='text'>Techno Fattie</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://technofattie.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://technofattie.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Josh</name><uri>http://www.blogger.com/profile/08438201529460997103</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_zrLYGpcNAqw/SMsZoOUBOhI/AAAAAAAAAQ0/v-9QdkwzIDg/S220/Josh.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>12</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2837647869424561922.post-3343464628569616478</id><published>2012-02-01T21:37:00.000-08:00</published><updated>2012-02-03T08:41:54.727-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><title type='text'>Whine Less... Code More</title><content type='html'>&lt;div class="tr_bq"&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;Developers are a whiny bunch.&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;Today I was reading one of &lt;a href="http://www.hanselman.com/blog/OneASPNETSneakPeekElegantWebFormsAndSnowballsInHell.aspx"&gt;Scott Hanselman's latest posts&lt;/a&gt; on some improvements being made in WebForms, and was pretty amazed at how generally whiny the comments were.&lt;br /&gt;&lt;br /&gt;You could read all the comments, but they can pretty much be broken down into 3 categories of whiny trolls.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The Hater&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: #fff2cc;"&gt;Dear Scott,&lt;br /&gt;&lt;br /&gt;You suck! WebForms sucks! Microsoft sucks! And pretty much every technology they produce is total garbage. I still program using the MS stack of course... cause you know... I'd rather complain than learn a new technology.&lt;/div&gt;&lt;br /&gt;&lt;b&gt;The Righteous One&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: #fff2cc;"&gt;Dear Scott,&lt;br /&gt;&lt;br /&gt;How can you even look at yourself in the mirror after writing such filthy code. I realize this is just a blog post... meant to be a simple&amp;nbsp;demonstration&amp;nbsp;of a new feature, but how dare you not follow all 5 of the SOLID principles, complete with a full suite of unit and integration tests (written first of course). You didn't even use an IoC!!!!&amp;nbsp;And you call yourself a programmer!&amp;nbsp;&lt;br /&gt;&lt;br /&gt;All .Net developers are pretty much worthless, incompetent boobs... except for me of course. I would write a better example myself, but I'm too busy telling people like you how crappy a programmer they are :P&lt;/div&gt;&lt;br /&gt;&lt;b&gt;The Hipster&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: #fff2cc;"&gt;Dear Scott,&lt;br /&gt;&lt;br /&gt;Whoa dude! WebForms is so primitive man. Only old people and corporate shills program in WebForms. Everybody knows that MVC is what all the cool kids are using. That internal corporate app I wrote is like... blowing minds... all five of them.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Besides, everybody knows that WebForms is way too much abstraction, and the ViewState, oh man was it terrible. I never knew what the ViewState was for, but I know it was bad! With MVC I can get down to bare metal baby! I still don't know what a Handler or Module is, and I never really touch the form collection or HttpContext... but it's so much less abstract than WebForms.&lt;/div&gt;&lt;br /&gt;So, to all you whiny programmers out there, I have a some people you should meet.&amp;nbsp;I know you know these people. You probably troll their blogs regularly.&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;div style="padding: 10px;"&gt;&lt;a href="http://www.objectmentor.com/omTeam/martin_r.html"&gt;Bob Martin&lt;/a&gt;, &lt;a href="http://www.objectmentor.com/omTeam/feathers_m.html"&gt;Michael Feathers&lt;/a&gt;, &lt;a href="http://www.objectmentor.com/omTeam/jeffries_r.html"&gt;Ron Jeffries&lt;/a&gt; and &lt;a href="http://martinfowler.com/"&gt;Martin Fowler&lt;/a&gt; were doing awesome things while you were still drinking from a sippy cup.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://david.heinemeierhansson.com/"&gt;David Heinemeier Hansson&lt;/a&gt;&amp;nbsp;liked Ruby and needed a web framework. &lt;a href="http://rubyonrails.org/"&gt;So he wrote one&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://wekeroad.com/"&gt;Rob Conery&lt;/a&gt; didn't like big heavy ORM's so &lt;a href="https://github.com/robconery/massive"&gt;he wrote a tiny one&lt;/a&gt;. He also created a startup using ASP.Net MVC... and then &lt;a href="http://www.infoq.com/articles/architecting-tekpub"&gt;rewrote it using RoR&lt;/a&gt; just because he could.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://haacked.com/"&gt;Phil Haack&lt;/a&gt; helped bring &lt;a href="http://haacked.com/tags/aspnetmvc/default.aspx"&gt;MVC&lt;/a&gt; to the world of ASP.Net&lt;br /&gt;&lt;br /&gt;&lt;a href="http://jeremydmiller.com/"&gt;Jeremy Miller&lt;/a&gt; and &lt;a href="http://ayende.com/blog"&gt;Oren Eini&lt;/a&gt; wake up in the morning and pee new frameworks that are awesome.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.joelonsoftware.com/"&gt;Joel Spolsky's&lt;/a&gt; company wrote an awesome &lt;a href="http://www.fogcreek.com/fogbugz/"&gt;bug tracker&lt;/a&gt; in classic asp. &lt;b&gt;ASP FOR GOODNESS SAKE!&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;a href="http://www.codinghorror.com/blog/"&gt;Jeff Atwood&lt;/a&gt; wrote &lt;a href="http://stackoverflow.com/"&gt;Stackoverflow &lt;/a&gt;when MVC was still in beta.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://damianedwards.wordpress.com/"&gt;Damien Edwards&lt;/a&gt; continues to rock out ASP.Net&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blogs.msdn.com/b/gblock/"&gt;Glenn Block&lt;/a&gt; is infusing &lt;a href="http://wcf.codeplex.com/wikipage?title=WCF%20HTTP"&gt;WCF with web enabled awesome sauce&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://ejohn.org/"&gt;John Resig&lt;/a&gt; made the entire web take &lt;a href="http://jquery.com/"&gt;Javascript seriously&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blog.stevensanderson.com/"&gt;Steve Sanderson&lt;/a&gt; brought MVVM to web apps using &lt;a href="http://knockoutjs.com/"&gt;Knockout.js&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://twitter.com/#!/davidfowl"&gt;David Fowler&lt;/a&gt; is making realtime web stupid easy with &lt;a href="https://github.com/SignalR/SignalR"&gt;SignalR&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And last but not least... &lt;a href="http://www.hanselman.com/blog/"&gt;Scott Hanselman&lt;/a&gt; was pimping ASP.Net and make it look good &lt;a href="http://www.hanselman.com/blog/IMGHeight394AltAPictureNamedSoapExtWizJPGHspace15Srchttpradioweblogscom0108971images2002101.aspx"&gt;back when it was still 1.0&lt;/a&gt;&lt;/div&gt;&lt;hr /&gt;&lt;br /&gt;So what do they all have in common?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: x-large;"&gt;They can't hear you over the sound of how awesome they are!&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;Not all of them work on the same technology stack, but all of them have been consistently awesome at what they do &lt;b&gt;regardless of the technology they were using.&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;Technologies do not make awesome applications. Awesome people make awesome applications.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Stop spending so much time and effort complaining and start doing something amazing... right now!&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #cc0000; font-size: x-large;"&gt;&lt;b&gt;Less Whine! More Awesome!&lt;/b&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2837647869424561922-3343464628569616478?l=technofattie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technofattie.blogspot.com/feeds/3343464628569616478/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://technofattie.blogspot.com/2012/02/whine-less-code-more.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default/3343464628569616478'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default/3343464628569616478'/><link rel='alternate' type='text/html' href='http://technofattie.blogspot.com/2012/02/whine-less-code-more.html' title='Whine Less... Code More'/><author><name>Josh</name><uri>http://www.blogger.com/profile/08438201529460997103</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_zrLYGpcNAqw/SMsZoOUBOhI/AAAAAAAAAQ0/v-9QdkwzIDg/S220/Josh.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2837647869424561922.post-8082294226596133496</id><published>2012-01-30T21:01:00.000-08:00</published><updated>2012-01-30T21:14:10.717-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Unit Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>It's The Principal...</title><content type='html'>In ancient times... at least according to web standards, I wrote a &lt;a href="http://technofattie.blogspot.com/2011/02/unit-testing-and-declarative-security.html""&gt;couple of posts&lt;/a&gt; about &lt;a href="http://technofattie.blogspot.com/2011/04/unit-testing-and-declarative-security.html"&gt;unit testing with declarative security attributes&lt;/a&gt;. It turns out that while using declarative security is pretty awesome, it's clear &lt;i&gt;nobody&lt;/i&gt;&amp;nbsp;was thinking about people doing TDD :(&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Getting around this was easy enough by simply overriding the &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.thread.currentprincipal.aspx"&gt;Principal&lt;/a&gt; using the built in &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.principal.genericprincipal.aspx"&gt;GenericPrincipal&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.principal.genericidentity.aspx"&gt;GenericIdentity&lt;/a&gt; classes. We even refactored the security setup code into the Initialize method for our unit tests. However, &lt;b&gt;we still had to think about security for every test class!&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;I can tell you right now that that is a big fat suck! I don't want to see &lt;i&gt;any&lt;/i&gt;&amp;nbsp;security related code in my unit test because &lt;b&gt;I'm not testing security right now!&lt;/b&gt;&amp;nbsp;What I really want is for my test to look like this and just work.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre class="c-sharp" name="code"&gt;[TestMethod]&lt;br /&gt;public void ShouldGetSuperSecretFromAgent()&lt;br /&gt;{&lt;br /&gt;    var agent = new SecretAgent();&lt;br /&gt;&lt;br /&gt;    //This line will esplode!!!&lt;br /&gt;    var secret = agent.GetSuperSecretStuff();&lt;br /&gt;&lt;br /&gt;    Assert.IsNotNull(secret);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Fortunately, we still have one last trick up our sleeve that we can use to solve our problem once and for all. Writing a custom implementation of &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.principal.iprincipal.aspx"&gt;IPrincipal&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.principal.iidentity.aspx"&gt;IIdentity&lt;/a&gt;. This is so braindead simple, that I'm not even going to explain it... just show you the code.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre class="c-sharp" name="code"&gt;&lt;br /&gt;public class StubPrincipal: IPrincipal, IIdentity&lt;br /&gt;{&lt;br /&gt;    public StubPrincipal(String name = "TestUser", Boolean isAuthenticated = true, String authenticationType = "Fake")&lt;br /&gt;    {&lt;br /&gt;        Name = name;&lt;br /&gt;        IsAuthenticated = isAuthenticated;&lt;br /&gt;        AuthenticationType = authenticationType;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    //IPrincipal Members&lt;br /&gt;    public IIdentity Identity&lt;br /&gt;    {&lt;br /&gt;        get { return this; }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public bool IsInRole(string role)&lt;br /&gt;    {&lt;br /&gt;        return true;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    //IIdentity Members&lt;br /&gt;    public string AuthenticationType { get; set; }&lt;br /&gt;&lt;br /&gt;    public bool IsAuthenticated { get; set; }&lt;br /&gt;&lt;br /&gt;    public string Name { get; set; }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This still leaves the business of wiring it all up. Since the whole point of this refactoring was to &lt;i&gt;not&lt;/i&gt;&amp;nbsp;have to worry about doing this for every test!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;All your base class are belong to us!&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;The simplest approach I can think of is to create a base class that will wire up your custom &lt;b&gt;StubPrincipal&lt;/b&gt; object in the constructor, and then derive all your test classes from it. Again, this is so braindead simple... just look at the code.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre class="c-sharp" name="code"&gt;&lt;br /&gt;public class SecurityEnabledTest&lt;br /&gt;{&lt;br /&gt;    protected StubPrincipal Principal = new StubPrincipal();&lt;br /&gt;&lt;br /&gt;    public SecurityEnabledTest()&lt;br /&gt;    {&lt;br /&gt;        Thread.CurrentPrincipal = Principal;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And now our goal above is reached with one tiny modification.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre class="c-sharp" name="code"&gt;&lt;br /&gt;[TestClass]&lt;br /&gt;public class SecretAgentBehavior_UsingBaseClass: SecurityEnabledTest&lt;br /&gt;{&lt;br /&gt;    [TestMethod]&lt;br /&gt;    [Description("Test relying on base class to set principal")]&lt;br /&gt;    public void ShouldGetSuperSecretFromAgent()&lt;br /&gt;    {&lt;br /&gt;        var agent = new SecretAgent();&lt;br /&gt;&lt;br /&gt;        //It works... WOOT!&lt;br /&gt;        var secret = agent.GetSuperSecretStuff();&lt;br /&gt;&lt;br /&gt;        Assert.IsNotNull(secret);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Voila! Now you can go on your merry little way and focus on the actual method behavior instead of the security meta-data.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;But Wait! There is even more awesome!&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;If you are thinking to yourself "Ok, that is great dude, but what if I actually want to test MY FREAKING SECURITY!"&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've got you covered. Here is a slightly &lt;a href="https://gist.github.com/1708922"&gt;more robust Principal object&lt;/a&gt; that will give you a lot more control over how it behaves, which should cover any testing scenario you can think of. It allows you to add roles, and has three modes of operation:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Always Return True&lt;/li&gt;&lt;li&gt;Whitelist&lt;/li&gt;&lt;ol&gt;&lt;li&gt;This is how a normal principal operates. If the role is in the list, then you get access.&lt;/li&gt;&lt;/ol&gt;&lt;li&gt;Blacklist&lt;/li&gt;&lt;ol&gt;&lt;li&gt;This works opposite to a normal principal. If the role is in the list, then you get denied access. This is useful for when there are multiple roles needed to perform an action (think nested calls), and you want to see how your code behaves when the user &lt;i&gt;doesn't&lt;/i&gt;&amp;nbsp;have one of them.&lt;/li&gt;&lt;/ol&gt;&lt;/ol&gt;&lt;div&gt;In the end I hope this helps unit testing efforts, and maybe demystifies the Principal/Identity objects a little bit. You can even use these same techniques to write your own custom security Principal for actual production uses. The concepts are identical.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Cheers,&lt;/div&gt;&lt;div&gt;Josh&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2837647869424561922-8082294226596133496?l=technofattie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technofattie.blogspot.com/feeds/8082294226596133496/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://technofattie.blogspot.com/2012/01/its-principal.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default/8082294226596133496'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default/8082294226596133496'/><link rel='alternate' type='text/html' href='http://technofattie.blogspot.com/2012/01/its-principal.html' title='It&apos;s The Principal...'/><author><name>Josh</name><uri>http://www.blogger.com/profile/08438201529460997103</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_zrLYGpcNAqw/SMsZoOUBOhI/AAAAAAAAAQ0/v-9QdkwzIDg/S220/Josh.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2837647869424561922.post-836837122773170670</id><published>2011-10-05T11:12:00.000-07:00</published><updated>2011-10-06T06:10:48.815-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DataAnnotations'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Validation'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Recursive Validation Using DataAnnotations</title><content type='html'>I saw a &lt;a href="http://stackoverflow.com/questions/7663501/dataannotations-recursively-validating-an-entire-object-graph"&gt;post on Stackoverflow&lt;/a&gt; today that piqued my interest.&lt;br /&gt;&lt;br /&gt;The title really says it all:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: white; font-family: 'Trebuchet MS', 'Liberation Sans', 'DejaVu Sans', sans-serif; line-height: 12px;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;h1 style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-family: 'Trebuchet MS', 'Liberation Sans', 'DejaVu Sans', sans-serif; font-weight: bold; margin-bottom: 7px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;span class="Apple-style-span" style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; cursor: pointer; font-size: small; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none; vertical-align: baseline;"&gt;&lt;a class="question-hyperlink" href="http://stackoverflow.com/questions/7663501/dataannotations-recursively-validating-an-entire-object-graph" style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; cursor: pointer; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none; vertical-align: baseline;"&gt;DataAnnotations: Recursively validating an entire object graph&lt;/a&gt;&lt;/span&gt;&lt;/h1&gt;&lt;br /&gt;Using the DataAnnotations to do validation on object can be extermely useful, but there are many limitations to the existing code base. One such limitations, as &lt;a href="http://stackoverflow.com/users/26414/neil-barnwell"&gt;Neil &lt;/a&gt;has discovered, is that the out of the box validator doesn't recursively apply validation.&lt;br /&gt;&lt;br /&gt;Indeed looking at the MSDN docs for &lt;a href="http://msdn.microsoft.com/en-us/library/dd411772.aspx"&gt;TryValidateObject&lt;/a&gt; state clearly that:&lt;br /&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="font-family: 'Segoe UI', Verdana, Arial; font-size: 13px;"&gt;This method evaluates each&amp;nbsp;&lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.validationattribute.aspx" style="color: #1364c4; text-decoration: none;"&gt;ValidationAttribute&lt;/a&gt;&amp;nbsp;instance that is attached to the object type. It also checks whether each property that is marked with&amp;nbsp;&lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.requiredattribute.aspx" style="color: #1364c4; text-decoration: none;"&gt;RequiredAttribute&lt;/a&gt;&amp;nbsp;is provided.&lt;span class="Apple-style-span" style="background-color: yellow;"&gt; It does not recursively validate&lt;/span&gt; the property values of the object.&lt;/span&gt;&lt;/blockquote&gt;&amp;nbsp;So how do we get around this? Well... there are several examples of people using reflection and LINQ to recurse over the individual properties and validate each one of them. Yuck!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;I'm a big fan of working with the framework&lt;/b&gt; if at all possible, so I decided to implement a quick solution that fits nicely into the DataAnnotations world.&lt;br /&gt;&lt;br /&gt;The idea is to simply tell the validation framework that you would like to do a little extra with some particular property. I want to be able to be able to &lt;i&gt;opt in&lt;/i&gt; certain properties to further validation if necessary. Something like this.&lt;br /&gt;&lt;br /&gt;&lt;pre class="c-sharp" name="code"&gt;public class Person {&lt;br /&gt;  [Required]&lt;br /&gt;  public String Name { get; set; }&lt;br /&gt;&lt;br /&gt;  [Required, ValidateObject]&lt;br /&gt;  public Address Address { get; set; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Address could have it's own set of validation attributes, and I want to also validate those along with my Person type. &lt;b&gt;Turns out this is pretty simple to do using existing framework components.&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;Let me just show you the code, and then I can explain what is going on.&lt;br /&gt;&lt;br /&gt;&lt;pre class="c-sharp" name="code"&gt;public class ValidateObjectAttribute: ValidationAttribute {&lt;br /&gt;   protected override ValidationResult IsValid(object value, ValidationContext validationContext) {&lt;br /&gt;      var results = new List&amp;lt;ValidationResult&amp;gt;();&lt;br /&gt;      var context = new ValidationContext(value, null, null);&lt;br /&gt;         &lt;br /&gt;      Validator.TryValidateObject(value, context, results, true);&lt;br /&gt;&lt;br /&gt;      if (results.Count != 0) {&lt;br /&gt;         var compositeResults = new CompositeValidationResult(String.Format("Validation for {0} failed!", validationContext.DisplayName));&lt;br /&gt;         results.ForEach(compositeResults.AddResult);&lt;br /&gt;&lt;br /&gt;         return compositeResults;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      return ValidationResult.Success;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class CompositeValidationResult: ValidationResult {&lt;br /&gt;   private readonly List&amp;lt;ValidationResult&amp;gt; _results = new List&amp;lt;ValidationResult&amp;gt;();&lt;br /&gt;&lt;br /&gt;   public IEnumerable&amp;lt;ValidationResult&amp;gt; Results {&lt;br /&gt;      get {&lt;br /&gt;         return _results;&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public CompositeValidationResult(string errorMessage) : base(errorMessage) {}&lt;br /&gt;   public CompositeValidationResult(string errorMessage, IEnumerable&amp;lt;string&amp;gt; memberNames) : base(errorMessage, memberNames) {}&lt;br /&gt;   protected CompositeValidationResult(ValidationResult validationResult) : base(validationResult) {}&lt;br /&gt;&lt;br /&gt;   public void AddResult(ValidationResult validationResult) {&lt;br /&gt;      _results.Add(validationResult);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/string&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The idea here is pretty simple. Any property decorated with the ValidateObjectAttribute will be validated as a whole, and the results aggregated together. The processing is as follows:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Create a new ValidationContext using the current value as the target&lt;/li&gt;&lt;li&gt;Attempt to validate that object, being sure to include all properties&lt;/li&gt;&lt;li&gt;If there are any ValidationResults, store them and return as a single aggregate failure&lt;/li&gt;&lt;li&gt;If there are no results, return ValidationResults.Success&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;Putting it all together, imagine for a minute that we had the following class structure:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;pre class="c-sharp" name="code"&gt;public class Person {&lt;br /&gt;  [Required]&lt;br /&gt;  public String Name { get; set; }&lt;br /&gt;&lt;br /&gt;  [Required, ValidateObject]&lt;br /&gt;  public Address Address { get; set; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class Address {&lt;br /&gt;  [Required]&lt;br /&gt;  public String Street1 { get; set; }&lt;br /&gt;&lt;br /&gt;  public String Street2 { get; set; }&lt;br /&gt;&lt;br /&gt;  [Required]&lt;br /&gt;  public String City { get; set; }&lt;br /&gt;&lt;br /&gt;  [Required]&lt;br /&gt;  public String State { get; set; }&lt;br /&gt;&lt;br /&gt;  [Required, ValidateObject]&lt;br /&gt;  public ZipCode Zip { get; set; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class ZipCode {&lt;br /&gt;  [Required]&lt;br /&gt;  public String PrimaryCode { get; set; }&lt;br /&gt;&lt;br /&gt;  public String SubCode { get; set; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We can simply make use of existing methods and validate the entire object graph. Also, making use of our CompositeValidationResult, we should be able to drill into each individual failure in context.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="c-sharp" name="code"&gt;static void Main(string[] args) {&lt;br /&gt;   var person = new Person {&lt;br /&gt;      Address = new Address {&lt;br /&gt;         City = "Awesome Town",&lt;br /&gt;         State = "TN",&lt;br /&gt;         Zip = new ZipCode()&lt;br /&gt;      },&lt;br /&gt;      Name = "Josh"&lt;br /&gt;   };&lt;br /&gt;&lt;br /&gt;   var context = new ValidationContext(person, null, null);&lt;br /&gt;   var results = new List&amp;lt;ValidationResult&amp;gt;();&lt;br /&gt;&lt;br /&gt;   Validator.TryValidateObject(person, context, results, true);&lt;br /&gt;&lt;br /&gt;   PrintResults(results, 0);&lt;br /&gt;&lt;br /&gt;   Console.ReadKey();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private static void PrintResults(IEnumerable&amp;lt;ValidationResult&amp;gt; results, Int32 indentationLevel) {&lt;br /&gt;   foreach (var validationResult in results) {&lt;br /&gt;      SetIndentation(indentationLevel);&lt;br /&gt;&lt;br /&gt;      Console.WriteLine(validationResult.ErrorMessage);&lt;br /&gt;      Console.WriteLine();&lt;br /&gt;&lt;br /&gt;      if (validationResult is CompositeValidationResult) {&lt;br /&gt;         PrintResults(((CompositeValidationResult)validationResult).Results, indentationLevel + 1);&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private static void SetIndentation(int indentationLevel) {&lt;br /&gt;   Console.CursorLeft = indentationLevel * 4;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Running the above should result in the following output:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-mJLDCk0nY4Y/Toycmc6xuWI/AAAAAAAABF8/M99mCHMfxWs/s1600/RecursiveValidation.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="163" src="http://1.bp.blogspot.com/-mJLDCk0nY4Y/Toycmc6xuWI/AAAAAAAABF8/M99mCHMfxWs/s400/RecursiveValidation.png" width="366" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Well, there you have it. A pretty simple solution that has the advantage of working alongside the Validation framework instead of against it!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2837647869424561922-836837122773170670?l=technofattie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technofattie.blogspot.com/feeds/836837122773170670/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://technofattie.blogspot.com/2011/10/recursive-validation-using.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default/836837122773170670'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default/836837122773170670'/><link rel='alternate' type='text/html' href='http://technofattie.blogspot.com/2011/10/recursive-validation-using.html' title='Recursive Validation Using DataAnnotations'/><author><name>Josh</name><uri>http://www.blogger.com/profile/08438201529460997103</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_zrLYGpcNAqw/SMsZoOUBOhI/AAAAAAAAAQ0/v-9QdkwzIDg/S220/Josh.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-mJLDCk0nY4Y/Toycmc6xuWI/AAAAAAAABF8/M99mCHMfxWs/s72-c/RecursiveValidation.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2837647869424561922.post-8402817700899698992</id><published>2011-09-23T12:26:00.000-07:00</published><updated>2011-10-06T06:11:02.918-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>Solving Ayende's Tax Woes</title><content type='html'>&lt;a href="http://ayende.com/blog/"&gt;Oren Eini&lt;/a&gt;&amp;nbsp;(a.k.a. Ayende Rahien)&amp;nbsp;is going through the joy that is &lt;a href="http://ayende.com/blog/102403/pet-projects-and-hiring-decisions"&gt;trying to find good developers&lt;/a&gt;. The other day he posted some sample code that an interviewee had turned in to a coding challenge. The &lt;a href="http://ayende.com/blog/102401/negative-hiring-decisions-part-i"&gt;results&lt;/a&gt; weren't pretty!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The problem involves calculating a persons taxes based on a set of tax brackets.&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;It makes a great interview question because the problem is short enough to get done in an hour or so, but tricky enough to require some thought. Here are the specs as &lt;a href="http://ayende.com/blog/108545/the-tax-calculation-challenge"&gt;posted by Ayende&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;b&gt;&lt;u&gt;Israel's Tax Brackets:&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: white; color: #333333; font-family: georgia, verdana, arial, sans-serif; font-size: 16px; line-height: 16px;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;table border="0" cellpadding="2" cellspacing="0" style="-webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-collapse: collapse; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 16px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; width: 400px;"&gt;&lt;tbody style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 16px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;tr style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 16px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;td style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 0.9em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;" valign="top" width="200"&gt;&lt;/td&gt;&lt;td style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 0.9em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;" valign="top" width="200"&gt;Tax Rate&lt;/td&gt;&lt;/tr&gt;&lt;tr style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 16px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;td style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 0.9em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;" valign="top" width="200"&gt;Up to 5,070&lt;/td&gt;&lt;td style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 0.9em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;" valign="top" width="200"&gt;10%&lt;/td&gt;&lt;/tr&gt;&lt;tr style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 16px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;td style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 0.9em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;" valign="top" width="200"&gt;5,071 up to 8,660&lt;/td&gt;&lt;td style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 0.9em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;" valign="top" width="200"&gt;14%&lt;/td&gt;&lt;/tr&gt;&lt;tr style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 16px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;td style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 0.9em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;" valign="top" width="200"&gt;8,661 up to 14,070&lt;/td&gt;&lt;td style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 0.9em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;" valign="top" width="200"&gt;23%&lt;/td&gt;&lt;/tr&gt;&lt;tr style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 16px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;td style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 0.9em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;" valign="top" width="200"&gt;14,071 up to 21,240&lt;/td&gt;&lt;td style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 0.9em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;" valign="top" width="200"&gt;30%&lt;/td&gt;&lt;/tr&gt;&lt;tr style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 16px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;td style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 0.9em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;" valign="top" width="200"&gt;21,241 up to 40,230&lt;/td&gt;&lt;td style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 0.9em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;" valign="top" width="200"&gt;33%&lt;/td&gt;&lt;/tr&gt;&lt;tr style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 16px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;td style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 0.9em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;" valign="top" width="200"&gt;Higher than 40,230&lt;/td&gt;&lt;td style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 0.9em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;" valign="top" width="200"&gt;45%&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;table border="0" cellpadding="2" cellspacing="0" style="-webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-collapse: collapse; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 16px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; width: 400px;"&gt;&lt;tbody style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 16px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span class="Apple-style-span" style="background-color: white; color: #333333; font-family: georgia, verdana, arial, sans-serif; font-size: 16px; line-height: 16px;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Acceptance Tests:&lt;/u&gt;&lt;/b&gt;&amp;nbsp;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;ul style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 16px; list-style-type: disc; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 40px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 16px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;5,000 –&amp;gt; 500&lt;/li&gt;&lt;/ul&gt;&lt;ul style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 16px; list-style-type: disc; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 40px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 16px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;5,800 –&amp;gt; 609.2&lt;/li&gt;&lt;/ul&gt;&lt;ul style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 16px; list-style-type: disc; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 40px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 16px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;9,000 –&amp;gt; 1087.8&lt;/li&gt;&lt;/ul&gt;&lt;ul style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 16px; list-style-type: disc; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 40px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 16px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;15,000 –&amp;gt; 2532.9&lt;/li&gt;&lt;/ul&gt;&lt;ul style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 16px; list-style-type: disc; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 40px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 16px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;50,000 –&amp;gt; 15,068.1&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;Having not yet read the other comments or solutions, I thought it would be fun to take a crack at writing my own solution to the problem.&lt;br /&gt;&lt;br /&gt;I am a huge proponent of unit testing, and more specifically &lt;b&gt;T&lt;/b&gt;est &lt;b&gt;D&lt;/b&gt;riven &lt;b&gt;D&lt;/b&gt;evelopment. Since we have a nice set of acceptance tests, it is pretty easy to get those into code.&lt;br /&gt;&lt;br /&gt;I started with the simplest of tests I could think of.&lt;br /&gt;&lt;br /&gt;&lt;pre class="c-sharp" name="code"&gt;[TestMethod]&lt;br /&gt;public void ShouldCalculateTotalTaxesToBeZero() {&lt;br /&gt;   var effectiveTax = new EffectiveTax();&lt;br /&gt;&lt;br /&gt;   var result = effectiveTax.CalculateTaxes(0);&lt;br /&gt;&lt;br /&gt;   Assert.AreEqual(0, result);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Which led me to create this simple implementation.&lt;br /&gt;&lt;br /&gt;&lt;pre class="c-sharp" name="code"&gt;public class EffectiveTax &lt;br /&gt;{      &lt;br /&gt;   public Decimal CalculateTaxes(Decimal grossIncome) &lt;br /&gt;   {&lt;br /&gt;      return 0;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Alright, so not very useful. But the tests pass!&lt;br /&gt;&lt;br /&gt;Now we need to be able to expand on this a bit and add a tax bracket in the mix.&amp;nbsp;A tax bracket has some lower-bound, and a rate.&amp;nbsp;We can write another pretty simple test for that.&lt;br /&gt;&lt;br /&gt;&lt;pre class="c-sharp" name="code"&gt;[TestMethod]&lt;br /&gt;public void ShouldCalculateTaxesUsingSingleTaxBracket() {&lt;br /&gt;   var effectiveTax = new EffectiveTax();&lt;br /&gt;   effectiveTax.AddTaxBracket(lowerBound: 0, taxRate: 0.1M);&lt;br /&gt;&lt;br /&gt;   Assert.AreEqual(0, effectiveTax.CalculateTaxes(0));&lt;br /&gt;   Assert.AreEqual(100, effectiveTax.CalculateTaxes(1000));&lt;br /&gt;   Assert.AreEqual(1000, effectiveTax.CalculateTaxes(10000));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;i&gt;(Note: The use of named parameters is to aid in the design process. Since I wrote the code before the method existed, the IDE can infer the parameter names and automatically generate a signature for me. Also, it helps to clarify what is going on in the test.)&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;We Add just enough code to get the tests passing, which is certainly more useful than the previous iteration, but far from complete. Some might object to my introducing a &lt;b&gt;TaxBracket&lt;/b&gt; type into the mix so early, but writing just enough code doesn't preclude one from writing clean code. The extra type helps to tidy things up, and makes future refactoring work easier with little extra work.&lt;br /&gt;&lt;br /&gt;&lt;pre class="c-sharp" name="code"&gt;public class EffectiveTax {&lt;br /&gt;&lt;br /&gt;   private TaxBracket _taxBracket;&lt;br /&gt;&lt;br /&gt;   public Decimal CalculateTaxes(Decimal grossIncome) {&lt;br /&gt;      return grossIncome * _taxBracket.TaxRate;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void AddTaxBracket(Decimal lowerBound, Decimal taxRate) {&lt;br /&gt;      _taxBracket = new TaxBracket {&lt;br /&gt;         LowerBound = lowerBound,&lt;br /&gt;         TaxRate = taxRate&lt;br /&gt;      };&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private class TaxBracket {&lt;br /&gt;      internal Decimal LowerBound { get; set; }&lt;br /&gt;      internal Decimal TaxRate { get; set; }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This rev is also incomplete since it doesn't take the lower-bound into account. So... we write another test case to cover that scenario.&lt;br /&gt;&lt;br /&gt;&lt;pre class="c-sharp" name="code"&gt;[TestMethod]&lt;br /&gt;public void ShouldCalculateOnlyTaxableIncome() {&lt;br /&gt;   var effectiveTax = new EffectiveTax();&lt;br /&gt;   effectiveTax.AddTaxBracket(lowerBound: 5000, taxRate: 0.1M);&lt;br /&gt;&lt;br /&gt;   Assert.AreEqual(0, effectiveTax.CalculateTaxes(0));&lt;br /&gt;   Assert.AreEqual(0, effectiveTax.CalculateTaxes(4999));&lt;br /&gt;   Assert.AreEqual(0, effectiveTax.CalculateTaxes(5000));&lt;br /&gt;   Assert.AreEqual(10, effectiveTax.CalculateTaxes(5100));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A minor change to the code, and now we can effectively handle a single flat tax, with an optional poverty line.&lt;br /&gt;&lt;br /&gt;&lt;pre class="c-sharp" name="code"&gt;public Decimal CalculateTaxes(Decimal grossIncome) {&lt;br /&gt;   var effectiveTax = 0.0M;&lt;br /&gt;         &lt;br /&gt;   if (grossIncome &gt; _taxBracket.LowerBound) {&lt;br /&gt;      var taxableIncome = grossIncome - _taxBracket.LowerBound;&lt;br /&gt;            &lt;br /&gt;      effectiveTax = taxableIncome * _taxBracket.TaxRate;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   return effectiveTax;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;However, what we want is a system with multiple tax brackets. Now we get to the testing scenario that was previously laid out for us. We can easily translate those tables into a test.&lt;br /&gt;&lt;br /&gt;&lt;pre class="c-sharp" name="code"&gt;[TestMethod]&lt;br /&gt;public void ShouldCalculateTaxUsingIsraelsTaxBrackets() {&lt;br /&gt;   var effectiveTax = new EffectiveTax();&lt;br /&gt;   effectiveTax.AddTaxBracket(lowerBound: 0, taxRate: 0.1M);&lt;br /&gt;   effectiveTax.AddTaxBracket(lowerBound: 5070, taxRate: 0.14M);&lt;br /&gt;   effectiveTax.AddTaxBracket(lowerBound: 8660, taxRate: 0.23M);&lt;br /&gt;   effectiveTax.AddTaxBracket(lowerBound: 14070, taxRate: 0.30M);&lt;br /&gt;   effectiveTax.AddTaxBracket(lowerBound: 21240, taxRate: 0.33M);&lt;br /&gt;   effectiveTax.AddTaxBracket(lowerBound: 40230, taxRate: 0.45M);&lt;br /&gt;&lt;br /&gt;   Assert.AreEqual(0, effectiveTax.CalculateTaxes(0));&lt;br /&gt;   Assert.AreEqual(500, effectiveTax.CalculateTaxes(5000));&lt;br /&gt;   Assert.AreEqual(609.2M, effectiveTax.CalculateTaxes(5800));&lt;br /&gt;   Assert.AreEqual(1087.8M, effectiveTax.CalculateTaxes(9000));&lt;br /&gt;   Assert.AreEqual(2532.9M, effectiveTax.CalculateTaxes(15000));&lt;br /&gt;   Assert.AreEqual(15068.1M, effectiveTax.CalculateTaxes(50000));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It was obvious that we needed some sort of collection to hold the TaxBrackets, and that we would need to loop over them to calculate the effective tax. The decision to reverse the loop, greatly simplifies the processing.&lt;br /&gt;&lt;br /&gt;Essentially we start with the highest amount of money that has a tax rate, and chop off that amount from the total amount remaining, taxing each chunk as we go and adding it to the total.&lt;br /&gt;&lt;br /&gt;&lt;pre class="c-sharp" name="code"&gt;public class EffectiveTax {&lt;br /&gt;&lt;br /&gt;   private readonly List&lt;taxbracket&gt; _taxBrackets = new List&lt;taxbracket&gt;();&lt;br /&gt;&lt;br /&gt;   public Decimal CalculateTaxes(Decimal grossIncome) {&lt;br /&gt;      var effectiveTax = 0.0M;&lt;br /&gt;      var incomeLeftToTax = grossIncome;&lt;br /&gt;&lt;br /&gt;      for (var i = (_taxBrackets.Count - 1); i &gt;= 0; i--) {&lt;br /&gt;         var taxBracket = _taxBrackets[i];&lt;br /&gt;&lt;br /&gt;         if (incomeLeftToTax &gt; taxBracket.LowerBound) {&lt;br /&gt;            var taxableIncome = incomeLeftToTax - taxBracket.LowerBound;&lt;br /&gt;&lt;br /&gt;            incomeLeftToTax -= taxableIncome;&lt;br /&gt;            effectiveTax += taxableIncome * taxBracket.TaxRate;&lt;br /&gt;         }&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      return effectiveTax;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void AddTaxBracket(Decimal lowerBound, Decimal taxRate) {&lt;br /&gt;      _taxBrackets.Add(new TaxBracket {&lt;br /&gt;         LowerBound = lowerBound,&lt;br /&gt;         TaxRate = taxRate&lt;br /&gt;      });&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private class TaxBracket {&lt;br /&gt;      internal Decimal LowerBound { get; set; }&lt;br /&gt;      internal Decimal TaxRate { get; set; }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/taxbracket&gt;&lt;/taxbracket&gt;&lt;/pre&gt;&lt;br /&gt;Finally we need to address a massive assumption with the current&amp;nbsp;implementation. Mainly, that the tax brackets are in ascending order based on their lower bound. That is a pretty big assumption, and one that could lead to nasty bugs in the future.&lt;br /&gt;&lt;br /&gt;For our last test, we mix up the ordering of the tax brackets and make sure everything still works.&lt;br /&gt;&lt;br /&gt;&lt;pre class="c-sharp" name="code"&gt;[TestMethod]&lt;br /&gt;public void ShouldCorrectlyOrderTaxBrackets() {&lt;br /&gt;   var effectiveTax = new EffectiveTax();&lt;br /&gt;   effectiveTax.AddTaxBracket(lowerBound: 40230, taxRate: 0.45M);&lt;br /&gt;   effectiveTax.AddTaxBracket(lowerBound: 14070, taxRate: 0.30M);&lt;br /&gt;   effectiveTax.AddTaxBracket(lowerBound: 0, taxRate: 0.1M);&lt;br /&gt;   effectiveTax.AddTaxBracket(lowerBound: 8660, taxRate: 0.23M);&lt;br /&gt;   effectiveTax.AddTaxBracket(lowerBound: 21240, taxRate: 0.33M);&lt;br /&gt;   effectiveTax.AddTaxBracket(lowerBound: 5070, taxRate: 0.14M);&lt;br /&gt;&lt;br /&gt;   Assert.AreEqual(0, effectiveTax.CalculateTaxes(0));&lt;br /&gt;   Assert.AreEqual(500, effectiveTax.CalculateTaxes(5000));&lt;br /&gt;   Assert.AreEqual(609.2M, effectiveTax.CalculateTaxes(5800));&lt;br /&gt;   Assert.AreEqual(1087.8M, effectiveTax.CalculateTaxes(9000));&lt;br /&gt;   Assert.AreEqual(2532.9M, effectiveTax.CalculateTaxes(15000));&lt;br /&gt;   Assert.AreEqual(15068.1M, effectiveTax.CalculateTaxes(50000));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Clearly this fails miserably so with a little adjustment to our method, we can ensure the ordering is correct before we start processing. The added benefit is that the code is now even more expressive than the explicit for loop from the previous iteration.&lt;br /&gt;&lt;br /&gt;&lt;pre class="c-sharp" name="code"&gt;public Decimal CalculateTaxes(Decimal grossIncome) {&lt;br /&gt;   var effectiveTax = 0.0M;&lt;br /&gt;   var incomeLeftToTax = grossIncome;&lt;br /&gt;&lt;br /&gt;   var orderedBrackets = _taxBrackets.OrderByDescending(tb =&gt; tb.LowerBound);&lt;br /&gt;&lt;br /&gt;   foreach (var taxBracket in orderedBrackets) {&lt;br /&gt;      if (incomeLeftToTax &gt; taxBracket.LowerBound) {&lt;br /&gt;         var taxableIncome = incomeLeftToTax - taxBracket.LowerBound;&lt;br /&gt;&lt;br /&gt;         incomeLeftToTax -= taxableIncome;&lt;br /&gt;         effectiveTax += taxableIncome * taxBracket.TaxRate;&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   return effectiveTax;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now, there are some clear omissions here, like checking for negative values, but I think it accomplished the spirit of the question.&lt;br /&gt;&lt;br /&gt;As I stated previously I haven't read any of the other solutions, so this may be an exact duplicate. Also, there may be much more elegant solutions to this problem, but as usual TDD has lead to something that is neat, clean, and well tested :)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2837647869424561922-8402817700899698992?l=technofattie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technofattie.blogspot.com/feeds/8402817700899698992/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://technofattie.blogspot.com/2011/09/solving-ayendes-tax-woes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default/8402817700899698992'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default/8402817700899698992'/><link rel='alternate' type='text/html' href='http://technofattie.blogspot.com/2011/09/solving-ayendes-tax-woes.html' title='Solving Ayende&apos;s Tax Woes'/><author><name>Josh</name><uri>http://www.blogger.com/profile/08438201529460997103</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_zrLYGpcNAqw/SMsZoOUBOhI/AAAAAAAAAQ0/v-9QdkwzIDg/S220/Josh.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2837647869424561922.post-1026053451399181592</id><published>2011-04-08T20:31:00.000-07:00</published><updated>2012-01-30T21:05:49.205-08:00</updated><title type='text'>Unit Testing and Declarative Security, Part 2</title><content type='html'>&lt;ul&gt;&lt;li&gt;&lt;a href="http://technofattie.blogspot.com/2011/02/unit-testing-and-declarative-security.html"&gt;See Part 1&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://technofattie.blogspot.com/2012/01/its-principal.html"&gt;And Part 3&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;a href="http://technofattie.blogspot.com/2011/02/unit-testing-and-declarative-security.html"&gt;In a previous post&lt;/a&gt; I talked about using the &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.permissions.principalpermissionattribute.aspx"&gt;PrincipalPermissionAttribute&lt;/a&gt; to achieve some last resort security that was tightly integrated into the framework.&lt;br /&gt;&lt;br /&gt;The nice thing about this approach is that you don't have to worry about some other programmer forgetting to check security before calling a method in your API. The bad news is because of the tight integration, Unit Testing becomes a little tricker. Since there is not a security service to mock, we have to get our hands dirty and actually set the &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.thread.currentprincipal.aspx"&gt;Principal&lt;/a&gt; so the method calls won't fail at runtime.&lt;br /&gt;&lt;br /&gt;We got around this last time by using &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.principal.genericprincipal.aspx"&gt;GenericPrincipal&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.principal.genericidentity.aspx"&gt;GenericIdentity&lt;/a&gt;, two classes provided for us by the FCL writers. However, the added code distracts from the test we really want to write. Lets look at that example again.&lt;br /&gt;&lt;br /&gt;&lt;pre class="c-sharp" name="code"&gt;[TestMethod]&lt;br /&gt;public void ShouldGetSuperSecretFromAgentUsingGenericPrincipalAndIdentity()&lt;br /&gt;{&lt;br /&gt;    var awesomeSauce = new GenericPrincipal(&lt;br /&gt;            new GenericIdentity("jbond"), new[] { "007" }&lt;br /&gt;        );&lt;br /&gt;&lt;br /&gt;    Thread.CurrentPrincipal = awesomeSauce;&lt;br /&gt;&lt;br /&gt;    var agent = new SecretAgent();&lt;br /&gt;&lt;br /&gt;    var secret = agent.GetSuperSecretStuff();&lt;br /&gt;&lt;br /&gt;    Assert.IsNotNull(secret);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So this isn't terrible right now, but it is code that will have to be repeated over and over again for each test that calls that method. In this scenario we really aren't interested in testing the security, but rather the guts of the method. We want to test security, but not in this method. Ok, let's start DRYing up this code.&lt;br /&gt;&lt;br /&gt;The easiest and simplest choice would be to just refactor out the code into a method, and then call it before our test. This is simple enough to do.&lt;br /&gt;&lt;br /&gt;&lt;pre class="c-sharp" name="code"&gt;[TestMethod]&lt;br /&gt;public void ShouldGetSuperSecretFromAgentUsingGenericPrincipalAndIdentity()&lt;br /&gt;{&lt;br /&gt;    SetUserRoles("007");&lt;br /&gt;&lt;br /&gt;    var agent = new SecretAgent();&lt;br /&gt;&lt;br /&gt;    var secret = agent.GetSuperSecretStuff();&lt;br /&gt;&lt;br /&gt;    Assert.IsNotNull(secret);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private void SetUserRoles(params String[] roles)&lt;br /&gt;{&lt;br /&gt;    if(roles == null || roles.Length == 0) return;&lt;br /&gt;&lt;br /&gt;    var principal = new GenericPrincipal(&lt;br /&gt;            new GenericIdentity("jbond"), roles&lt;br /&gt;        );&lt;br /&gt;&lt;br /&gt;    Thread.CurrentPrincipal = principal;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That is slightly better, and gives a much better indication of what is going on when looking at the test, but I still don't like it for a couple of reasons:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The call to SetUserRoles still takes away from the purpose of the test. Remember this test isn't about security, but the behavior of the method itself. Everytime you look at this test you will first have to figure out why the security is there, and this increases friction and slows down the &lt;a href="http://jamesshore.com/Blog/Red-Green-Refactor.html"&gt;RED/GREEN/REFACTOR&lt;/a&gt; cycle.&lt;/li&gt;&lt;li&gt;Code is still repeated because everytime we test a path through any method with security we will have to make a call to SetUserRoles, and that sucks. Any code that can be copied and pasted is worth your time to refactor.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;I really want to get to not thinking about security when I write my tests, so let's see if we can at least do that. Those of you familiar with any of the major &lt;a href="http://www.nunit.org/"&gt;Unit&lt;/a&gt; &lt;a href="http://www.gallio.org/"&gt;Testing&lt;/a&gt; &lt;a href="http://msdn.microsoft.com/en-us/library/ms182486.aspx"&gt;Frameworks&lt;/a&gt; will know that they all have an attribute that designates one method that will run before every test is run. In MSTest it is the &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.testinitializeattribute(v=VS.100).aspx"&gt;TestInitializeAttribute&lt;/a&gt;. We can use that to neatly tuck our security code away into a single method so we don't have to repeat it for every test.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="c-sharp" name="code"&gt;[TestInitialize]&lt;br /&gt;public void Init()&lt;br /&gt;{&lt;br /&gt;    SetUserRoles("007");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[TestMethod]&lt;br /&gt;public void ShouldGetSuperSecretFromAgentUsingGenericPrincipalAndIdentity()&lt;br /&gt;{&lt;br /&gt;    var agent = new SecretAgent();&lt;br /&gt;&lt;br /&gt;    var secret = agent.GetSuperSecretStuff();&lt;br /&gt;&lt;br /&gt;    Assert.IsNotNull(secret);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//SetUserRoles Method&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now, this is certainly a lot better than the previous version since we only have to call SetUserRoles in one place. Also, our test method is free from the security clutter so we don't have any mental road blocks while reading the test. However, I am still not very happy with the end result. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Why?&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;Remember when I said I didn't want to have to &lt;i&gt;think&lt;/i&gt; about the security while writing my tests? Well... I still do. Everytime I write a new method in my SUT, I will no doubt add another security attribute to it. Or, I will write a test to cover security, and then add the attribute to make my test pass. Either way, I will have to come back to the Init method and add another role to the list.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Nothing will cripple your unit testing efforts faster than brittle, hard to maintain tests!&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;So how do we get around this? Ok so I already told you in Part 1 that we could build a custom Principal and Identity in order to achieve the desired results, but I wanted to expound a little on the rationale for actually doing it.&lt;br /&gt;&lt;br /&gt;In &lt;a href="http://technofattie.blogspot.com/2012/01/its-principal.html"&gt;Part 3&lt;/a&gt; we solve all our problems (I promise!)&lt;br /&gt;&lt;/br&gt;&lt;br /&gt;&lt;/br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2837647869424561922-1026053451399181592?l=technofattie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technofattie.blogspot.com/feeds/1026053451399181592/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://technofattie.blogspot.com/2011/04/unit-testing-and-declarative-security.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default/1026053451399181592'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default/1026053451399181592'/><link rel='alternate' type='text/html' href='http://technofattie.blogspot.com/2011/04/unit-testing-and-declarative-security.html' title='Unit Testing and Declarative Security, Part 2'/><author><name>Josh</name><uri>http://www.blogger.com/profile/08438201529460997103</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_zrLYGpcNAqw/SMsZoOUBOhI/AAAAAAAAAQ0/v-9QdkwzIDg/S220/Josh.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2837647869424561922.post-6596126363104450971</id><published>2011-02-10T22:58:00.000-08:00</published><updated>2011-02-10T23:18:19.924-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WPF'/><category scheme='http://www.blogger.com/atom/ns#' term='Stackoverflow'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>WPF != Fancy Winforms</title><content type='html'>I'm a big fan of Stackoverflow, and I was just recently looking at this &lt;a href="http://stackoverflow.com/questions/4965023/c-check-if-text-file-has-content"&gt;very simple question regarding changing button color.&lt;/a&gt; On the surface it seems this would warrant a very simple answer, and indeed &lt;a href="http://stackoverflow.com/questions/4965023/c-check-if-text-file-has-content/4965058#4965058"&gt;Chris' Answer&lt;/a&gt; was simple, straightforward and to the point.&lt;br /&gt;&lt;br /&gt;However, it feels too much like how I would have done things back in the dark ages of WinForms. There seems to be this misconception that WPF is just a fancier version of the old Win32 standby. &lt;i&gt;(note I am not trying to imply this is what Chris thinks, it merely serves as a convenient backdrop for this post)&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;But WPF is not even a cousin, or distant relative of WinForms. If WPF saw WinForms in the hallway it would beat him up and take his lunch money from him. Anyway, that is enough of a rant. On with what started out as my original answer to the question, which turned into this epic post...&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;u&gt;Original Answer Starts Here:&lt;/u&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;So Chris' suggestion is pretty straightforward, and it is certainly easier to implement than what I am about to show you ;) However, if you are going to venture into the world of WPF then you need to experience what it has to offer.&lt;br /&gt;&lt;br /&gt;In my opinion the two biggest advantages in WPF are:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The power and flexibility of the declarative model&lt;/li&gt;&lt;li&gt;An incredibly rich data binding infrastructure&lt;/li&gt;&lt;/ol&gt;Granted those are immensely deep topics within WPF, but without at least gaining a minimal understanding of those topics, it will be like driving a Lamborghini around in first gear all the time.&lt;br /&gt;&lt;br /&gt;That being said, you can jump to the full solution &lt;a href="#fullsolution"&gt;here&lt;/a&gt;, copy and paste it into a clean solution, and play with it for a second. I'll be waiting patiently here to give you a detailed explanation of what is going on. &lt;br /&gt;&lt;br /&gt;Ready? Ok then, lets get going.&lt;br /&gt;&lt;br /&gt;Lets start with the core logic of the application, your requirements are:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;b&gt;Examine a file on disk&lt;/b&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Change the appearance of a button based on content length&lt;/b&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Update the appearance of the button when the file changes&lt;/b&gt;&lt;/li&gt;&lt;/ol&gt;Since the appearance of the button is presentation specific, we simply won't worry about that when implementing our core logic. So what we really need to do is monitor the file for changes, and update a local variable with the length of the file, if it exists.&lt;br /&gt;&lt;br /&gt;This is a perfect job for a &lt;a href="http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;FileSystemWatcher&lt;/span&gt;&lt;/a&gt;. The file watcher kicks off a thread in the background which utilizes some low level Win32 API's to monitor events on the file system. We can tie into those events via the watcher, and handle them in our application asynchonously.&lt;br /&gt;&lt;br /&gt;Creating a new watcher is pretty simple and all we really need to provide is the Path. Here I am simply using the current location of the Executing Assembly for the base path. The second thing you see here is the Filter property. This works just like the filter you would use in the command line.&lt;br /&gt;&lt;br /&gt;&lt;pre class="c#" name="code"&gt;private FileSystemWatcher _fileWatcher;&lt;br /&gt;private const String FileToWatch = "tempfile.txt";&lt;br /&gt;&lt;br /&gt;public void InitializeFileWatcher()&lt;br /&gt;{&lt;br /&gt;    _fileWatcher = new FileSystemWatcher();&lt;br /&gt;    _fileWatcher.Path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);&lt;br /&gt;    _fileWatcher.Filter = "*.txt";&lt;br /&gt;&lt;br /&gt;    //Snip...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Next we want to subscribe to the different types of events available, and tell the watcher to start doing it's thing. In this case our event handler is just a thin wrapper around a simple method that does all the "heavy" lifting. Lastly we call our &lt;span class="Apple-style-span" style="background-color: #cccccc; font-family: 'Courier New', Courier, monospace;"&gt;UpdateFileLength&lt;/span&gt;&lt;span class="Apple-style-span" style="background-color: white; font-family: 'Courier New', Courier, monospace;"&gt; &lt;/span&gt;method directly because we need to know what the status of the file is right now, without waiting on an event from our watcher.&lt;br /&gt;&lt;br /&gt;&lt;pre class="c#" name="code"&gt;public void InitializeFileWatcher()&lt;br /&gt;{&lt;br /&gt;    //Snip...&lt;br /&gt;&lt;br /&gt;    _fileWatcher.Created += fileWatcher_Handler;&lt;br /&gt;    _fileWatcher.Changed += fileWatcher_Handler;&lt;br /&gt;    _fileWatcher.Deleted += fileWatcher_Handler;&lt;br /&gt;    _fileWatcher.Renamed += fileWatcher_Handler;&lt;br /&gt;&lt;br /&gt;    _fileWatcher.EnableRaisingEvents = true;&lt;br /&gt;&lt;br /&gt;    UpdateFileLength(Path.Combine(_fileWatcher.Path, FileToWatch));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private void UpdateFileLength(string filePath)&lt;br /&gt;{&lt;br /&gt;    Int64? length = null;&lt;br /&gt;&lt;br /&gt;    if (Path.GetFileName(filePath) == FileToWatch)&lt;br /&gt;    {&lt;br /&gt;        var fi = new FileInfo(filePath);&lt;br /&gt;&lt;br /&gt;        if (fi.Exists)&lt;br /&gt;            length = fi.Length;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    Dispatcher.Invoke((Action)(&lt;br /&gt;        () =&amp;gt; FileContentLength = length)&lt;br /&gt;    );&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void fileWatcher_Handler(object sender, FileSystemEventArgs e)&lt;br /&gt;{&lt;br /&gt;    UpdateFileLength(e.FullPath);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The UpdateFileLength method is pretty simple. It checks to see if the file is the one we are looking for, extracts the length if it exists, and updates a property on our MainWindow. Something that may seem a bit odd however, is the use of the &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.aspx"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Dispatcher&lt;/span&gt;&lt;/a&gt; and an anonymous method in order to set that property.&lt;br /&gt;&lt;br /&gt;Remember how I said that the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;FileSystemWatcher&lt;/span&gt; kicks off a background thread. Well, technically &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;UpdateFileLength&lt;/span&gt; could be getting executed from a different thread than the UI thread. And well... it's a big NO NO to access things in the UI from another thread. Without going into a a lot of detail, the Dispatcher is responsible for scheduling things to happen on the UI thread in WPF. Here we are ensuring that no matter what thread executes this method, that that line will always be executed on the UI thread.&lt;br /&gt;&lt;br /&gt;Ok, so the last little bit is our property we use to store the current length of the file we are monitoring, but it is no ordinary property.&lt;br /&gt;&lt;br /&gt;&lt;pre class="c#" name="code"&gt;public static readonly DependencyProperty FileContentLengthProperty = DependencyProperty.Register(&lt;br /&gt;    "FileContentLength",&lt;br /&gt;    typeof(Int64?),&lt;br /&gt;    typeof(MainWindow),&lt;br /&gt;    new UIPropertyMetadata(null));&lt;br /&gt;&lt;br /&gt;public Int64? FileContentLength&lt;br /&gt;{&lt;br /&gt;    get&lt;br /&gt;    {&lt;br /&gt;        return (Int64?)GetValue(FileContentLengthProperty);&lt;br /&gt;    }&lt;br /&gt;    set&lt;br /&gt;    {&lt;br /&gt;        SetValue(FileContentLengthProperty, value);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;What you are staring at here is known as a &lt;a href="http://msdn.microsoft.com/en-us/library/ms752914.aspx"&gt;DependencyProperty&lt;/a&gt;, and they are pretty foundational to how WPF works, so take some time to learn about them. For our purposes, just know that what this provides for us is a way for WPF to monitor changes to our property, which allows for all sorts of fun stuff in the UI.&lt;br /&gt;&lt;br /&gt;Now, on to the UI and where the real magic happens. Did you notice we didn't ever reference any buttons or set colors in the code behind? That's because 99% of the time in WPF there is no need to. The declarative model we have in &lt;a href="http://msdn.microsoft.com/en-us/library/ms752059.aspx"&gt;XAML&lt;/a&gt; combined with the rich data binding ecosystem in WPF gives us the freedom to finally have true seperation of concerns between presentation and logic.&lt;br /&gt;&lt;br /&gt;The first order of business is to set the &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.datacontext.aspx"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;DataContext&lt;/span&gt;&lt;/a&gt; on the Window itself so that we can access all of the properties defined in our code behind. Ok there is only one, but we still need it.&lt;br /&gt;&lt;br /&gt;&lt;pre class="xml" name="code"&gt;DataContext="{Binding RelativeSource={RelativeSource Self}}"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Next we need a button on our window. Ok, nothing special going on here, except that there is no content, no coloring, just a Style property bound to some static resource called &lt;span class="Apple-style-span" style="color: #cc0000;"&gt;"FileBoundButton"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class="xml" name="code"&gt;&lt;br /&gt;&lt;button Style="{StaticResource FileBoundButton}"                 Name="button1" /&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms745683.aspx"&gt;Styles in WPF are another big complex topic&lt;/a&gt;, but just know that this isn't anything like CSS. You can set virtually any property on an element via a style, and include declarative triggers to change the appearance based on events, data, or even other elements. This is precisely how we are going to achieve the visual affect you are after and then some!&lt;br /&gt;&lt;br /&gt;&lt;textarea class="xml" name="code"&gt;&lt;br /&gt;&lt;style x:Key="FileBoundButton" TargetType="ContentControl"&gt;    &lt;setter Property="Background" Value="Green" /&gt;    &lt;setter Property="Content" Value="{Binding FileContentLength}" /&gt;    &lt;Style.Triggers&gt;        &lt;datatrigger Binding="{Binding FileContentLength}" Value="{x:Null}"&gt;            &lt;setter Property="Background" Value="LightGray" /&gt;            &lt;setter Property="Content" Value="No File!" /&gt;        &lt;/DataTrigger&gt;        &lt;datatrigger Binding="{Binding FileContentLength}" Value="0"&gt;            &lt;setter Property="Background" Value="Red" /&gt;        &lt;/DataTrigger&gt;    &lt;/Style.Triggers&gt;&lt;/Style&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;The style we are using is declared as a static resource on the window itself. You need a name if you want to be able to refer to it later, and using a TargetType of ContentControl instead of a Button means we could reuse this style a lot of different elements, not just a button.&lt;br /&gt;&lt;br /&gt;We set the Background property to Green initially, and we also set the Content equal to the value of our &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;FileContentLength&lt;/span&gt; property. Then we make use of DataTriggers to alter those settings based on the value of FileContentLength. The syntax of a DataTrigger can be a bit wonky at first, but if you were to spell it out in pseudo-code it would sound something like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;set the Background property to &lt;span class="Apple-style-span" style="background-color: lime;"&gt;Green&lt;/span&gt;&lt;br /&gt;set the Content to DataContext.FileContentLength&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;IF&lt;/span&gt; the value of DataContext.FileContentLength is &lt;span class="Apple-style-span" style="color: red;"&gt;NULL&lt;/span&gt;&lt;br /&gt;    &lt;span class="Apple-style-span" style="color: blue;"&gt;THEN&lt;/span&gt; set the Background property to &lt;span class="Apple-style-span" style="background-color: #cccccc;"&gt;LightGray&lt;/span&gt; &lt;span class="Apple-style-span" style="color: blue;"&gt;AND&lt;/span&gt;&lt;br /&gt;         set the Content to "No File!"&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;ELSE IF&lt;/span&gt; the value of DataContext.FileContentLength is &lt;span class="Apple-style-span" style="color: red;"&gt;0&lt;/span&gt;&lt;br /&gt;    &lt;span class="Apple-style-span" style="color: blue;"&gt;THEN&lt;/span&gt; set the Background property to &lt;span class="Apple-style-span" style="background-color: red;"&gt;Red&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You might be wondering exactly &lt;i&gt;what&lt;/i&gt;&amp;nbsp;DataContext this is referring to. Essentially whatever framework element this style happens to be applied to. Because we didn't set the Button's DataContext explicitely it will inherit the DataContext of the Window. But be careful! Where the DataContext comes from isn't always apparent.&lt;br /&gt;&lt;br /&gt;Now, if you put all this together and launch the app for the first time you should end up with a small window with a gray button in it that says "No File!"&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;img src="https://lh6.googleusercontent.com/_zrLYGpcNAqw/TVTfmg2jvoI/AAAAAAAAA18/PrNnn4ucwoc/s800/FileWatcher_NoFile.png"&gt;&lt;/img&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;Without closing the program, navigate to the executing directory of your application "[ProjectFolder]\bin\Debug" and create a new text file named "tempfile.txt" Now you should see the button change color to red and display a "0" since the file is empty.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;img src="https://lh4.googleusercontent.com/_zrLYGpcNAqw/TVTfmYRStiI/AAAAAAAAA10/pBNoBbSkEc0/s800/FileWatcher_EmptyFile.png"&gt;&lt;/img&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;Open the newly created text file and write something in there. Save the file and again, watch as your button magically changes before your eyes to green, and displaying "N" where N is the number of characters in your text file.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;img src="https://lh3.googleusercontent.com/_zrLYGpcNAqw/TVTfmQqJ5tI/AAAAAAAAA14/7jZ_skxgL4o/s800/FileWatcher_FileWithContent.png"&gt;&lt;/img&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;If you actually made it through this whole thing, then you have hopefully been opened up to a whole new world of possibilities by using WPF. Just remember that it is a very, very deep technology and you won't learn it over night. Here are some resources to get you started on your journey though.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms754130.aspx"&gt;The MSDN Walk Through.&lt;/a&gt; Heavy reading, but worth it.&lt;br /&gt;&lt;a href="http://www.wpftutorial.net/christian.php"&gt;Christian Moser's WPF Tutorial Site.&lt;/a&gt; Lots of easy to digest samples.&lt;br /&gt;&lt;a href="http://stackoverflow.com/questions/tagged/wpf"&gt;WPF Questions on Stackoverflow&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a name="fullsolution"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;`MainWindow.xaml`:&lt;br /&gt;&lt;br /&gt;&lt;textarea class="xml:collapse" name="code"&gt;&lt;br /&gt;&lt;window x:Class="TechnoFattie.WPF.MainWindow"        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"        mc:Ignorable="d" Height="86" Width="174"        Title="File Watcher Example"        DataContext="{Binding RelativeSource={RelativeSource Self}}"&gt;&lt;br /&gt;&lt;Window.Resources&gt;&lt;br /&gt;&lt;style x:Key="FileBoundButton" TargetType="Control"&gt;            &lt;setter Property="Background" Value="Green" /&gt;            &lt;Style.Triggers&gt;                &lt;datatrigger Binding="{Binding FileContentLength}" Value="{x:Null}"&gt;                    &lt;setter Property="Background" Value="LightGray" /&gt;                &lt;/DataTrigger&gt;                &lt;datatrigger Binding="{Binding FileContentLength}" Value="0"&gt;                    &lt;setter Property="Background" Value="Red" /&gt;                &lt;/DataTrigger&gt;            &lt;/Style.Triggers&gt;        &lt;/Style&gt;&lt;br /&gt;&lt;/Window.Resources&gt;&lt;br /&gt;&lt;grid x:Name="LayoutRoot"&gt;&lt;br /&gt;&lt;button Content="{Binding FileContentLength}"                 Style="{StaticResource FileBoundButton}"                 Name="button1" /&gt;&lt;br /&gt;&lt;/Grid&gt;&lt;br /&gt;&lt;/Window&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;`MainWindow.xaml.cs`:&lt;br /&gt;&lt;br /&gt;&lt;pre class="c#:collapse" name="code"&gt;public partial class MainWindow : Window&lt;br /&gt;{&lt;br /&gt;    private FileSystemWatcher _fileWatcher;&lt;br /&gt;    private const String FileToWatch = "tempfile.txt";&lt;br /&gt;&lt;br /&gt;    public MainWindow()&lt;br /&gt;    {&lt;br /&gt;        InitializeComponent();&lt;br /&gt;            &lt;br /&gt;        InitializeFileWatcher();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void InitializeFileWatcher()&lt;br /&gt;    {&lt;br /&gt;        _fileWatcher = new FileSystemWatcher();&lt;br /&gt;        _fileWatcher.Path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);&lt;br /&gt;        _fileWatcher.Filter = "*.txt";&lt;br /&gt;&lt;br /&gt;        _fileWatcher.Created += fileWatcher_Handler;&lt;br /&gt;        _fileWatcher.Changed += fileWatcher_Handler;&lt;br /&gt;        _fileWatcher.Deleted += fileWatcher_Handler;&lt;br /&gt;        _fileWatcher.Renamed += fileWatcher_Handler;&lt;br /&gt;&lt;br /&gt;        _fileWatcher.EnableRaisingEvents = true;&lt;br /&gt;&lt;br /&gt;        UpdateFileLength(Path.Combine(_fileWatcher.Path, FileToWatch));&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private void UpdateFileLength(string filePath)&lt;br /&gt;    {&lt;br /&gt;        Int64? length = null;&lt;br /&gt;&lt;br /&gt;        if (Path.GetFileName(filePath) == FileToWatch)&lt;br /&gt;        {&lt;br /&gt;            var fi = new FileInfo(filePath);&lt;br /&gt;&lt;br /&gt;            if (fi.Exists)&lt;br /&gt;                length = fi.Length;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        Dispatcher.Invoke((Action)(() =&amp;gt; FileContentLength = length));&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    void fileWatcher_Handler(object sender, FileSystemEventArgs e)&lt;br /&gt;    {&lt;br /&gt;        UpdateFileLength(e.FullPath);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Int64? FileContentLength&lt;br /&gt;    {&lt;br /&gt;        get&lt;br /&gt;        {&lt;br /&gt;            return (Int64?)GetValue(FileContentLengthProperty);&lt;br /&gt;        }&lt;br /&gt;        set&lt;br /&gt;        {&lt;br /&gt;            SetValue(FileContentLengthProperty, value);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static readonly DependencyProperty FileContentLengthProperty = DependencyProperty.Register(&lt;br /&gt;        "FileContentLength",&lt;br /&gt;        typeof(Int64?),&lt;br /&gt;        typeof(MainWindow),&lt;br /&gt;        new UIPropertyMetadata(null));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2837647869424561922-6596126363104450971?l=technofattie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technofattie.blogspot.com/feeds/6596126363104450971/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://technofattie.blogspot.com/2011/02/wpf-fancy-winforms.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default/6596126363104450971'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default/6596126363104450971'/><link rel='alternate' type='text/html' href='http://technofattie.blogspot.com/2011/02/wpf-fancy-winforms.html' title='WPF != Fancy Winforms'/><author><name>Josh</name><uri>http://www.blogger.com/profile/08438201529460997103</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_zrLYGpcNAqw/SMsZoOUBOhI/AAAAAAAAAQ0/v-9QdkwzIDg/S220/Josh.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='https://lh6.googleusercontent.com/_zrLYGpcNAqw/TVTfmg2jvoI/AAAAAAAAA18/PrNnn4ucwoc/s72-c/FileWatcher_NoFile.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2837647869424561922.post-5833672808795259148</id><published>2011-02-09T20:53:00.000-08:00</published><updated>2012-01-30T21:03:43.085-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Unit Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>Unit Testing and Declarative Security, Part 1</title><content type='html'>&lt;ul&gt;&lt;li&gt;&lt;a href="http://technofattie.blogspot.com/2011/04/unit-testing-and-declarative-security.html"&gt;See Part 2&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://technofattie.blogspot.com/2012/01/its-principal.html"&gt;And Part 3&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Security is hard. If you think it isn't your software is probably just waiting to be exploited by this guy:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-LFBH0lmiDZk/TVNtn_VV0aI/AAAAAAAAA1k/f72-ZNQtWSM/s1600/EvilHacker.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-LFBH0lmiDZk/TVNtn_VV0aI/AAAAAAAAA1k/f72-ZNQtWSM/s1600/EvilHacker.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Knowing this, the guys who put together the .Net framework gave us a pretty brain-dead approach to adding security declaratively&lt;sup&gt;1&lt;/sup&gt; to our code using the &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.permissions.principalpermissionattribute.aspx"&gt;PrincipalPermissionAttribute&lt;/a&gt;. Securing a method call becomes trivial this way.&lt;br /&gt;&lt;br /&gt;&lt;pre class="c-sharp" name="code"&gt;[PrincipalPermission(SecurityAction.Demand, Authenticated = true, Role = "007")]&lt;br /&gt;public Secret GetSuperSecretStuff(){&lt;br /&gt;    return Vault.SuperSecret;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Anybody who calls this method will have to be operating under a security context that is both authenticated and a member of the &lt;span class="Apple-style-span" style="color: #990000;"&gt;"007"&lt;/span&gt; role. However, calling this method without meeting the requirements will throw a big fat Exception. This can make unit testing a bit tricky since you most likely will &lt;strong&gt;not&lt;/strong&gt; have the proper credentials. &lt;br /&gt;&lt;br /&gt;For instance suppose the above method were defined on a &lt;span class="Apple-style-span" style="background-color: #cccccc; font-family: 'Courier New', Courier, monospace;"&gt;SecretAgent&lt;/span&gt; type in my project and I wanted to write a unit test for it:&lt;br /&gt;&lt;br /&gt;&lt;pre class="c-sharp" name="code"&gt;[TestMethod]&lt;br /&gt;public void ShouldGetSuperSecretFromAgent()&lt;br /&gt;{&lt;br /&gt;    var agent = new SecretAgent();&lt;br /&gt;&lt;br /&gt;    var secret = agent.GetSuperSecretStuff();&lt;br /&gt;&lt;br /&gt;    Assert.IsNotNull(secret);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Running this code will result in a big fat exception, and your test output will read:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="background-color: #fff2cc; font-size: large;"&gt;Test method TechnoFattie.Lib.Tests.SecretAgentBehavior.ShouldGetSuperSecretFromAgent threw exception: &lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: #fff2cc; font-size: large;"&gt;System.Security.SecurityException: Request for principal permission failed.&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;Bummer :(&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Getting around this is pretty easy though if you understand how security works in the .Net framework.&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;Most security in .Net is centered around checking the &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.thread.currentprincipal.aspx"&gt;Principal on the currently executing thread&lt;/a&gt; to see if it contains a specific role, and using the &lt;span class="Apple-style-span" style="background-color: #cccccc; font-family: 'Courier New', Courier, monospace;"&gt;PrincipalPermissionAttribute&lt;/span&gt; is no exception.&lt;br /&gt;&lt;br /&gt;You could think of using security declared in this way as having wrapped every call to &lt;span class="Apple-style-span" style="background-color: #cccccc; font-family: 'Courier New', Courier, monospace;"&gt;GetSuperSecretStuff&lt;/span&gt; like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class="c-sharp" name="code"&gt;if(Thread.CurrentPrincipal.IsInRole("007")){&lt;br /&gt;    var secret = GetSuperSecretStuff();&lt;br /&gt;}&lt;br /&gt;else{&lt;br /&gt;    throw new SecurityException("Request for principal permission failed.");&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;What we need is a way to completely control the Principal. Fortunately for us, replacing the principal is as simple as setting a property. You can assign any principal you want to &lt;span class="Apple-style-span" style="background-color: #cccccc; font-family: 'Courier New', Courier, monospace;"&gt;Thread.Current.Principal&lt;/span&gt; so long as it implements the &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.principal.iprincipal.aspx"&gt;IPrincipal&lt;/a&gt; interface.&lt;br /&gt;&lt;br /&gt;If we look the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="background-color: #cccccc;"&gt;IPrincipal&lt;/span&gt; &lt;/span&gt;interface, we will notice it is pretty darn simple:&lt;br /&gt;&lt;br /&gt;&lt;pre class="c-sharp" name="code"&gt;public interface IPrincipal&lt;br /&gt;{&lt;br /&gt;    IIdentity Identity { get; }&lt;br /&gt;    bool IsInRole(string role);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You will also notice that it contains an &lt;span class="Apple-style-span" style="background-color: #cccccc; font-family: 'Courier New', Courier, monospace;"&gt;Identity&lt;/span&gt; property, another very simple interface:&lt;br /&gt;&lt;br /&gt;&lt;pre class="c-sharp" name="code"&gt;public interface IIdentity&lt;br /&gt;{&lt;br /&gt;    string AuthenticationType { get; }&lt;br /&gt;    bool IsAuthenticated { get; }&lt;br /&gt;    string Name { get; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We could implement our own classes here and use them, but I generally prefer the path of laziness. And wouldn't you know it, the hard working guys at Microsoft decided they would spare us the grueling work of implementing three entire properties and one method. Having pity on the lesser developers like myself, they gave us...&lt;br /&gt;&lt;br /&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.security.principal.genericprincipal.aspx"&gt;GenericPrincipal&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.principal.genericidentity.aspx"&gt;GenericIdentity&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Standing on the shoulders of these giants we can rewrite our test method to take advantage of the no doubt hundreds of man hours required to not only implement these classes, but to carefully name them as well.&lt;br /&gt;&lt;br /&gt;&lt;pre class="c-sharp" name="code"&gt;[TestMethod]&lt;br /&gt;public void ShouldGetSuperSecretFromAgentUsingGenericPrincipalAndIdentity()&lt;br /&gt;{&lt;br /&gt;    var awesomeSauce = new GenericPrincipal(&lt;br /&gt;            new GenericIdentity("jbond"), new[] { "007" }&lt;br /&gt;        );&lt;br /&gt;&lt;br /&gt;    Thread.CurrentPrincipal = awesomeSauce;&lt;br /&gt;&lt;br /&gt;    var agent = new SecretAgent();&lt;br /&gt;&lt;br /&gt;    var secret = agent.GetSuperSecretStuff();&lt;br /&gt;&lt;br /&gt;    Assert.IsNotNull(secret);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now our test will happily pass, and life is good once again. Security can seem like a somewhat mystical thing in .Net, but as you can see the underlying mechanics are pretty simple. &lt;a href="http://technofattie.blogspot.com/2011/04/unit-testing-and-declarative-security.html"&gt;In the next installment&lt;/a&gt; I am actually going to implement a custom Principal type in order to be able to test more complicated security scenarios, and to reduce the amount of code needed to ease maintenance.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;i&gt;1. Don't mistake this approach for a real security solution however.  Ideally you should have already checked the user's credentials before hand and the method would never get called. This method is really only good as a fail-safe.&lt;/i&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2837647869424561922-5833672808795259148?l=technofattie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technofattie.blogspot.com/feeds/5833672808795259148/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://technofattie.blogspot.com/2011/02/unit-testing-and-declarative-security.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default/5833672808795259148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default/5833672808795259148'/><link rel='alternate' type='text/html' href='http://technofattie.blogspot.com/2011/02/unit-testing-and-declarative-security.html' title='Unit Testing and Declarative Security, Part 1'/><author><name>Josh</name><uri>http://www.blogger.com/profile/08438201529460997103</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_zrLYGpcNAqw/SMsZoOUBOhI/AAAAAAAAAQ0/v-9QdkwzIDg/S220/Josh.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-LFBH0lmiDZk/TVNtn_VV0aI/AAAAAAAAA1k/f72-ZNQtWSM/s72-c/EvilHacker.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2837647869424561922.post-3148763473132893959</id><published>2010-06-25T16:39:00.000-07:00</published><updated>2010-06-25T16:42:04.657-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Unit Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><category scheme='http://www.blogger.com/atom/ns#' term='Moq'/><title type='text'>Extending Moq Using Extension Methods</title><content type='html'>If you regularly use &lt;a href="http://en.wikipedia.org/wiki/Test-driven_development"&gt;TDD&lt;/a&gt;, then you are familiar with the concept of mocking. If you don't use TDD, then you need to slap yourself and apologize to &lt;a href="http://www.objectmentor.com/omTeam/martin_r.html"&gt;Bob Martin&lt;/a&gt;, &lt;a href="http://www.objectmentor.com/omTeam/feathers_m.html"&gt;Michael Feathers&lt;/a&gt; and &lt;a href="http://www.objectmentor.com/omTeam/jeffries_r.html"&gt;Ron Jeffries&lt;/a&gt; immediately. I'll wait here...&lt;br /&gt;&lt;br /&gt;While I would argue you should begin your TDD journey by &lt;a href="http://blog.objectmentor.com/articles/2009/10/28/manual-mocking-resisting-the-invasion-of-dots-and-parentheses"&gt;writing your own mocks&lt;/a&gt;; using a framework will certainly make like easier in many instances and allow you to focus on the tests themselves.&lt;br /&gt;&lt;br /&gt;I was a &lt;a href="http://www.ayende.com/projects/rhino-mocks.aspx"&gt;RhinoMocks&lt;/a&gt; guy for a long time, but have recently converted to &lt;a href="http://code.google.com/p/moq/"&gt;Moq&lt;/a&gt;... AND I LOVE IT!!! Moq is simple and easy to use, and doesn't get in the way of the intent of your tests. That being said, there are certain scenarios you run into with any framework that you end up coding around, and sometimes that &lt;em&gt;does&lt;/em&gt; get in the way of your what you trying to say with your test.&lt;br /&gt;&lt;br /&gt;Moq allows for a pretty simple syntax when you want to set up a return value on a mocked type.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;var mockService = new Mock&amp;lt;IReturnStuff&amp;gt;();&lt;br /&gt;mockService.Setup(svc =&amp;gt; svc.SomeMethodCall()).Returns("Hello, World!");&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Pretty sweet so far, and that works 99% of the time. But... what about a scenario where we want to return different values on successive calls to that method. I can think of a lot of situations where, in the absence of formal eventing, you want your code to test some value until it meets a certain criteria. You might be polling a web service for status updates, or checking a database to see if a record has been written. Whatever the case may be, it &lt;em&gt;will&lt;/em&gt; come up.&lt;br /&gt;&lt;br /&gt;So, for illustration purposes, let's make up one such example. Suppose we wanted to ask a service for a specified set of values, but the return types could be varied. Perhaps we only care about some subset of those values, and want to test that our code correctly deals with variable data.&lt;br /&gt;&lt;br /&gt;We have our service contract:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;public interface IReturnStuff&lt;br /&gt;{&lt;br /&gt;    String ReturnAString();&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Next we have our consuming class (the subject under test):&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;public class UsesReturnedStuff&lt;br /&gt;{&lt;br /&gt;    public IReturnStuff ReturnStuff { get; set; }&lt;br /&gt;    private Regex Filter { get; set; }&lt;br /&gt;&lt;br /&gt;    public UsesReturnedStuff(IReturnStuff returnStuff)&lt;br /&gt;    {&lt;br /&gt;        ReturnStuff = returnStuff;&lt;br /&gt;        Filter = new Regex("(the|quick|brown|fox|hello|world)(:Pu)?", RegexOptions.IgnoreCase);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public List&amp;lt;String&amp;gt; GetStuff(Int32 times)&lt;br /&gt;    {&lt;br /&gt;        var stuff = new List&amp;lt;String&amp;gt;();&lt;br /&gt;&lt;br /&gt;        for (var i = 0; i &amp;gt; times; i++)&lt;br /&gt;        {&lt;br /&gt;            var newStuff = ReturnStuff.ReturnAString();&lt;br /&gt;&lt;br /&gt;            if(Filter.IsMatch(newStuff))&lt;br /&gt;                stuff.Add(newStuff);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        return stuff;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As you can see we have a pretty basic setup here that uses a white-list approach to building up a list. We want to write some tests to mock this behavior. If we wanted two different return values when this method is called, we might instinctively write a test like this:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;[Test]&lt;br /&gt;public void LastSetupWins()&lt;br /&gt;{&lt;br /&gt;var mockReturnStuff = new Mock&amp;lt;IReturnStuff&amp;gt;();&lt;br /&gt;var usesStuff = new UsesReturnedStuff(mockReturnStuff.Object);&lt;br /&gt;&lt;br /&gt;mockReturnStuff.Setup(svc =&amp;gt; svc.ReturnAString()).Returns("Hello");&lt;br /&gt;mockReturnStuff.Setup(svc =&amp;gt; svc.ReturnAString()).Returns("World!");&lt;br /&gt;&lt;br /&gt;var stuff = usesStuff.GetStuff(2);&lt;br /&gt;&lt;br /&gt;Assert.AreEqual("Hello World!", String.Join(" ", stuff.ToArray()));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you couldn't already tell from the name of the test method, this won't work as the last return value to be Setup wins. The output from this test will produce the text:&lt;br /&gt;&lt;blockquote&gt;"World! World!"&lt;/blockquote&gt;Not so great, but the Moq documentation gives us a workaround by using a callback method. A little bit of refactoring and Voila!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;[Test]&lt;br /&gt;public void SetupWithCallback()&lt;br /&gt;{&lt;br /&gt;    var mockReturnStuff = new Mock&amp;lt;IReturnStuff&amp;gt;();&lt;br /&gt;    var usesStuff = new UsesReturnedStuff(mockReturnStuff.Object);&lt;br /&gt;&lt;br /&gt;    var returnValues = new[] {"Hello", "World!"};&lt;br /&gt;    var numCalls = 0;&lt;br /&gt;&lt;br /&gt;    mockReturnStuff.Setup(svc =&amp;gt; svc.ReturnAString())&lt;br /&gt;        .Returns(() =&amp;gt; returnValues[numCalls])&lt;br /&gt;        .Callback(() =&amp;gt; numCalls++);&lt;br /&gt;&lt;br /&gt;    var stuff = usesStuff.GetStuff(returnValues.Length);&lt;br /&gt;&lt;br /&gt;    Assert.AreEqual("Hello World!", String.Join(" ", stuff.ToArray()));&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here we are taking advantage of anonymous methods and closures to essentially keep feeding our Mock service it's next value. This works, but... yuck! Reading this test is not very clear, and it gets in the way of the intent.&lt;br /&gt;Since we are supposed to refactor our test code too, lets move the ugly bits out into a private method, and re-write our test again.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;private static Int32 SetupMany(Mock&amp;lt;IReturnStuff&amp;gt; mock, Expression&amp;lt;Func&amp;lt;IReturnStuff, String&amp;gt;&amp;gt; expression, params String[] args)&lt;br /&gt;{&lt;br /&gt;    var numCalls = 0;&lt;br /&gt;&lt;br /&gt;    mock.Setup(expression)&lt;br /&gt;        .Returns(() =&amp;gt; args[numCalls])&lt;br /&gt;        .Callback(() =&amp;gt; numCalls++);&lt;br /&gt;&lt;br /&gt;    return args.Length;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[Test]&lt;br /&gt;public void SetupWithExtractedMethod()&lt;br /&gt;{&lt;br /&gt;    var mockReturnStuff = new Mock&amp;lt;IReturnStuff&amp;gt;();&lt;br /&gt;    var usesStuff = new UsesReturnedStuff(mockReturnStuff.Object);&lt;br /&gt;&lt;br /&gt;    var calls = SetupMany(mockReturnStuff,&lt;br /&gt;                          svc =&amp;gt; svc.ReturnAString(),&lt;br /&gt;                          "Hello", "World!");&lt;br /&gt;&lt;br /&gt;    var stuff = usesStuff.GetStuff(calls);&lt;br /&gt;&lt;br /&gt;    Assert.AreEqual("Hello World!", String.Join(" ", stuff.ToArray()));&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is good. We haven't lost any functionality, but the intent of the test is much clearer. There is less friction because you can read the code and understand what it is doing pretty quickly without having to "decipher" the meaning.&lt;br /&gt;Now, this is all fine and good, but I am likely to run into this same scenario more than once. What I would really love to have is a SetupMany() method that was built into Moq. A method I could call directly on the mocked object. Well... starting with C# 3.0 Extension Methods give us the ability to do just that. With a little work, we should be able to create a very generic extension to give us the desired behavior.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;public static class MoqExtensions&lt;br /&gt;{&lt;br /&gt;    public static void SetupMany&amp;lt;TSvc, TReturn&amp;gt;(this Mock&amp;lt;TSvc&amp;gt; mock,&lt;br /&gt;        Expression&amp;lt;Func&amp;lt;TSvc, TReturn&amp;gt;&amp;gt; expression,&lt;br /&gt;        params TReturn[] args)&lt;br /&gt;        where TSvc : class&lt;br /&gt;    {&lt;br /&gt;        var numCalls = 0;&lt;br /&gt;&lt;br /&gt;        mock.Setup(expression)&lt;br /&gt;            .Returns(() =&amp;gt; numCalls &amp;lt; args.Length ? args[numCalls] : args[args.Length - 1])&lt;br /&gt;            .Callback(() =&amp;gt; numCalls++);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ok, so I know the method signature looks pretty scary. Just don't stare at it long enough or you will go blind! The extra bit with the Ternary operator is a bit of error checking to prevent you from running over the bounds of the array. If you call the method more times than available arguments, it will simply keep returning the last argument in the list.&lt;br /&gt;Refactoring our test one last time gives us an even cleaner syntax that works with any return type. The second test merely demonstrates the "sticky" final value being returned over and over.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;[Test]&lt;br /&gt;public void SetupWithGenericExtensionMethod()&lt;br /&gt;{&lt;br /&gt;    var mockReturnStuff = new Mock&amp;lt;IReturnStuff&amp;gt;();&lt;br /&gt;    var usesStuff = new UsesReturnedStuff(mockReturnStuff.Object);&lt;br /&gt;&lt;br /&gt;    mockReturnStuff.SetupMany(svc =&amp;gt; svc.ReturnAString(), "Hello", "World!");&lt;br /&gt;&lt;br /&gt;    var stuff = usesStuff.GetStuff(2);&lt;br /&gt;&lt;br /&gt;    Assert.AreEqual("Hello World!", String.Join(" ", stuff.ToArray()));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[Test]&lt;br /&gt;public void SetupWithLotsOfParams()&lt;br /&gt;{&lt;br /&gt;    var mockReturnStuff = new Mock&amp;lt;IReturnStuff&amp;gt;();&lt;br /&gt;    var usesStuff = new UsesReturnedStuff(mockReturnStuff.Object);&lt;br /&gt;&lt;br /&gt;    mockReturnStuff.SetupMany(svc =&amp;gt; svc.ReturnAString(),&lt;br /&gt;                              "the","quick","brown","fox","jumps","over","the","fence","hello!");&lt;br /&gt;&lt;br /&gt;    var stuff = usesStuff.GetStuff(11);&lt;br /&gt;&lt;br /&gt;    Assert.AreEqual("the quick brown fox the hello! hello! hello!", String.Join(" ", stuff.ToArray()));&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And there you have it. Extending the Moq API without having to actually go in and modify the source. Hopefully this will save you a headache or two in the future.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2837647869424561922-3148763473132893959?l=technofattie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technofattie.blogspot.com/feeds/3148763473132893959/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://technofattie.blogspot.com/2010/06/if-you-regularly-use-tdd-then-you-are.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default/3148763473132893959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default/3148763473132893959'/><link rel='alternate' type='text/html' href='http://technofattie.blogspot.com/2010/06/if-you-regularly-use-tdd-then-you-are.html' title='Extending Moq Using Extension Methods'/><author><name>Josh</name><uri>http://www.blogger.com/profile/08438201529460997103</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_zrLYGpcNAqw/SMsZoOUBOhI/AAAAAAAAAQ0/v-9QdkwzIDg/S220/Josh.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2837647869424561922.post-7689900283525147639</id><published>2010-05-04T05:46:00.000-07:00</published><updated>2010-05-04T05:48:25.706-07:00</updated><title type='text'>Fear Of Success</title><content type='html'>I was in the middle of making a rather lengthy comment on &lt;a href="http://thetestingblog.com/2010/04/30/exploratory-testing-and-a-prophet-without-honor/"&gt;Daniel’s most recent blog post&lt;/a&gt; when I decided it was long enough to warrant a full posting.&lt;br /&gt;&lt;br /&gt;I wanted to get across the point that the situation Daniel finds himself in is not solely the plight of the software tester. Rather, anyone who esteems software quality runs the risk of being criticized, dismissed, or made fun of. Why is it that organizations and groups are so resistant to something that will improve their process, their product, and their bottom line. The idea is one I have been thinking a lot about, and I believe I have had an epiphany.&lt;br /&gt;&lt;b&gt;&lt;br /&gt;Read more at &lt;a href="http://thetestingblog.com/2010/05/03/fear-of-success/"&gt;The Testing Blog&lt;/a&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2837647869424561922-7689900283525147639?l=technofattie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technofattie.blogspot.com/feeds/7689900283525147639/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://technofattie.blogspot.com/2010/05/fear-of-success.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default/7689900283525147639'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default/7689900283525147639'/><link rel='alternate' type='text/html' href='http://technofattie.blogspot.com/2010/05/fear-of-success.html' title='Fear Of Success'/><author><name>Josh</name><uri>http://www.blogger.com/profile/08438201529460997103</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_zrLYGpcNAqw/SMsZoOUBOhI/AAAAAAAAAQ0/v-9QdkwzIDg/S220/Josh.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2837647869424561922.post-5182669085768435861</id><published>2010-05-04T05:43:00.000-07:00</published><updated>2010-05-04T05:45:09.811-07:00</updated><title type='text'>QA, Being A Professional, And Waiting Tables</title><content type='html'>If you are a little lost by the title, it will all make sense in a moment… um… sort of.&lt;br /&gt;&lt;br /&gt;Until I started my career as a software developer I worked a lot of other jobs. I have had a job since I was 16 years old, and that was just an excuse to get out of doing manual work for my parents around the house. I’ve worked as a bagger at a grocery store, cashier at a big-box-mart, usher, concessions, and box clerk for a movie theater, tech support for a DSL provider, general laborer for a masonry outfit, and the last job I worked before slinging code full-time was waiting tables.&lt;br /&gt;&lt;br /&gt;All of these jobs really have one thing in common: I was the person who always caught the tail end of the customer’s experience: whether it was good or bad… especially when it was bad!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Read more at &lt;a href="http://thetestingblog.com/2010/04/08/qa-being-a-professional-and-waiting-tables/"&gt;The Testing Blog&lt;/a&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2837647869424561922-5182669085768435861?l=technofattie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technofattie.blogspot.com/feeds/5182669085768435861/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://technofattie.blogspot.com/2010/05/httpthetestingblogcom20100408qa-being.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default/5182669085768435861'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default/5182669085768435861'/><link rel='alternate' type='text/html' href='http://technofattie.blogspot.com/2010/05/httpthetestingblogcom20100408qa-being.html' title='QA, Being A Professional, And Waiting Tables'/><author><name>Josh</name><uri>http://www.blogger.com/profile/08438201529460997103</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_zrLYGpcNAqw/SMsZoOUBOhI/AAAAAAAAAQ0/v-9QdkwzIDg/S220/Josh.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2837647869424561922.post-1905636350604931091</id><published>2009-06-23T18:47:00.001-07:00</published><updated>2009-06-23T21:18:13.649-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='enum'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='dataset'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Custom Enum in strongly typed DataSet</title><content type='html'>&lt;div style="text-align: left;"&gt;Recently I found a question about &lt;a href="http://stackoverflow.com/questions/1035796/enum-in-dataset"&gt;using Enums in a DataSet&lt;/a&gt; on &lt;a href="http://www.blogger.com/www.stackoverflow.com"&gt;StackOverflow&lt;/a&gt;. I was a little dissapointed at the answers people provided that were either down right wrong, or overly complicated. Sometimes I think people are so hungry for reputation points they forget that they are supposed to be &lt;i&gt;answering&lt;/i&gt; questions.&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Anyway, one poster recommended using strongly typed DataSets, but then advocated partial classes, or modifying the generated code. While a strongly typed DataSet is the way to go, you don't have to do anything fancy to get enum support.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Lets say we have just created a DataSet, and dropped a single DataTable into it:&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;img src="http://2.bp.blogspot.com/_zrLYGpcNAqw/SkGNLW-5LkI/AAAAAAAAArw/cSOTIk5daTo/s320/EnumDataSet.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 186px; height: 75px;" border="0" alt="" id="BLOGGER_PHOTO_ID_5350713058580311618" /&gt;&lt;div&gt;Normally &lt;b&gt;AwesomeId&lt;/b&gt; would just map to some integer key in a lookup table, and for whatever reason you have an enum that maps directly to this table in code:&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre name="code" class="c#"&gt;namespace&amp;nbsp;StackOverflowExamples.Library.DataAccess.EnumDataSet&lt;br /&gt;{&lt;br /&gt; public&amp;nbsp;enum&amp;nbsp;AwesomeEnum&lt;br /&gt; {&lt;br /&gt;  Awesome,&lt;br /&gt;  MoreAwesome,&lt;br /&gt;  AwesomeIncarnate&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;What you want to avoid is having to cast this back and forth from an &lt;b&gt;Int&lt;/b&gt; to an Enum. The nice folks at Microsoft were kind enough to give us a type property for each column in a DataSet that can be changed. If you select the column you want to map, and then navigate to the properties tab in Visual Studio, you will see that the column type is easily changeable.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;img src="http://4.bp.blogspot.com/_zrLYGpcNAqw/SkGRSbszr5I/AAAAAAAAAr4/KgYzIcV0YP8/s320/AwesomeIdColumn.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" border="0" alt="" id="BLOGGER_PHOTO_ID_5350717578152226706" /&gt;&lt;/div&gt;&lt;div&gt;Now all you have to do is substitute the fully qualified Enum Type into that field and you are good to go.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;a href="http://picasaweb.google.com/lh/photo/ubIVvV3zxTXtfpTD2sr6cA?authkey=Gv1sRgCJeptOeUyKuEXA&amp;amp;feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_zrLYGpcNAqw/SkGS6iPG6vI/AAAAAAAAAsA/58dvcN0BomI/s800/AwesomeIdColumnDataTypeRenamed.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;&lt;div&gt;Are we there yet? Sort of. You could officially use this right now if you want, but chances are somehwere down the road you will eventually run into this gem (after a rebuild) when you attempt to open the designer.&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#0000EE;"&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="color:#000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://picasaweb.google.com/lh/photo/61HkPacV0Aqm0oTZzodxLA?authkey=Gv1sRgCJeptOeUyKuEXA&amp;amp;feat=embedwebsite"&gt;&lt;img src="http://lh5.ggpht.com/_zrLYGpcNAqw/SkGXrP7jCuI/AAAAAAAAAtE/ILJ7j9bzQPc/s800/WrongDataTypeError.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;In case this happens, don't worry you haven't permanently broken the designer, but you will have to manually edit the .xsd file. Navigate to your DataSet .xsd file and right click on it. Choose to open it up with the text editor of your choice, but you are better off just using the default Visual Studio text editor.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://picasaweb.google.com/lh/photo/6mPamn5Km70Bn-79VWzoWw?authkey=Gv1sRgCJeptOeUyKuEXA&amp;amp;feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_zrLYGpcNAqw/SkGZq1h1DhI/AAAAAAAAAtI/-C4fknFOb2g/s800/xsdfile.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Normally I don't advocate editing raw autogened XML, but this one is an easy fix. Find the line that maps your column name to a specific type. It should look something like this:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;xs:element name=&amp;quot;AwesomeId&amp;quot; msdata:DataType=&amp;quot;StackOverflowExamples.Library.DataAccess.EnumDataSet.AwesomeEnum, StackOverflowExamples.Library, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null&amp;quot; msprop:Generator_UserColumnName=&amp;quot;AwesomeId&amp;quot; msprop:Generator_ColumnPropNameInRow=&amp;quot;AwesomeId&amp;quot; msprop:Generator_ColumnVarNameInTable=&amp;quot;columnAwesomeId&amp;quot; msprop:Generator_ColumnPropNameInTable=&amp;quot;AwesomeIdColumn&amp;quot; type=&amp;quot;xs:anyType&amp;quot; minOccurs=&amp;quot;0&amp;quot; /&amp;gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;Take a look at the &lt;i&gt;msdata:DataType&lt;/i&gt; attribute. As you can clearly see, our fully qualified type is listed here, but there is some assembly information that is causing us problems. Simply remove everything after the &lt;i&gt;Type Name.&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;xs:element name=&amp;quot;AwesomeId&amp;quot; msdata:DataType=&amp;quot;StackOverflowExamples.Library.DataAccess.EnumDataSet.AwesomeEnum&amp;quot; msprop:Generator_UserColumnName=&amp;quot;AwesomeId&amp;quot; msprop:Generator_ColumnPropNameInRow=&amp;quot;AwesomeId&amp;quot; msprop:Generator_ColumnVarNameInTable=&amp;quot;columnAwesomeId&amp;quot; msprop:Generator_ColumnPropNameInTable=&amp;quot;AwesomeIdColumn&amp;quot; type=&amp;quot;xs:anyType&amp;quot; minOccurs=&amp;quot;0&amp;quot; /&amp;gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;Now you can save the .xsd file, close it, and reopen your DataSet in the designer without any more problems.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Enjoy your strongly typed DataSet with custom Enum values :)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2837647869424561922-1905636350604931091?l=technofattie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technofattie.blogspot.com/feeds/1905636350604931091/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://technofattie.blogspot.com/2009/06/enum-in-strongly-typed-dataset.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default/1905636350604931091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default/1905636350604931091'/><link rel='alternate' type='text/html' href='http://technofattie.blogspot.com/2009/06/enum-in-strongly-typed-dataset.html' title='Custom Enum in strongly typed DataSet'/><author><name>Josh</name><uri>http://www.blogger.com/profile/08438201529460997103</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_zrLYGpcNAqw/SMsZoOUBOhI/AAAAAAAAAQ0/v-9QdkwzIDg/S220/Josh.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_zrLYGpcNAqw/SkGNLW-5LkI/AAAAAAAAArw/cSOTIk5daTo/s72-c/EnumDataSet.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2837647869424561922.post-2533815609126113196</id><published>2007-12-21T22:40:00.000-08:00</published><updated>2007-12-21T23:55:00.868-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='F#'/><title type='text'>MandelBrot Bitmap</title><content type='html'>So recently I was reading &lt;a href="http://www.secretgeek.net"&gt;secretGeek&lt;/a&gt; (a very underated blog I enjoy), and there was this interesting post about an &lt;a href="http://blogs.msdn.com/lukeh/archive/2007/11/14/f.aspx"&gt;F# program&lt;/a&gt; that Mr. Bambrick tweaked a little. The &lt;a href="http://www.secretgeek.net/f_mandel.asp"&gt;variation&lt;/a&gt; was interesting, and it piqued my interests into the cryptic style behind F#. However, just before I could get away with another quick read my geekish manhood was challenged.&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;p align="left"&gt;&lt;em&gt;"Your mission!&lt;br /&gt;Next step: do the same thing rendering pixels to a bitmap instead... then i could try breaking that up amongst multiple cores... no... sleep time.&lt;br /&gt;&lt;br /&gt;The interested reader is invited to finish this problem for me ;-)"&lt;/em&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;-- secretGeek&lt;/p&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I had to do something or I could never again return to secretGeek without being pushed around by all the other readers (they think they're so cool with their big brains). So... I went home and geeked out in front of my laptop, which is kind of like Hulking out for nerds except for the muscles and awesomeness.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;After installing the F# components and firing up VS, I copied the necessary file and began to make some modifications. After 3 hours of staring at documentation (Oh what I wouldn't give for some curly braces) and about 30 seconds of coding I came up with a pretty simple solution that works nicely.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Here are the relevant code changes:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="color:#3333ff;"&gt;let&lt;/span&gt; stepY = 0.1 / 40.0 &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="color:#009900;"&gt;//Scale goes in increments of 20 pixels for height&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#3333ff;"&gt;let&lt;/span&gt; stepX = 0.05 / 20.0 &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="color:#006600;"&gt;&lt;span style="color:#009900;"&gt;//Scale goes in increments of 60 pixels for width&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#009900;"&gt;//Simple declarations to get the height and width of the Bitmap&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#3333ff;"&gt;let&lt;/span&gt; numPixelsX = (int)(3.0 / stepX)&lt;br /&gt;&lt;span style="color:#3333ff;"&gt;let&lt;/span&gt; numPixelsY = (int)(2.0 / stepY)&lt;br /&gt;&lt;span style="color:#3333ff;"&gt;let&lt;/span&gt; bmp = &lt;span style="color:#3333ff;"&gt;new&lt;/span&gt; Bitmap(numPixelsX, numPixelsY)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="color:#009900;"&gt;//This is used to figure out what the current X and Y coordinates are&lt;br /&gt;// during processing in order to set the appropriate pixels in the Bitmap&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#3333ff;"&gt;let&lt;/span&gt; getPosY y = (int)(Math.Abs((Math.Floor -1.0 - y) / stepY))&lt;br /&gt;&lt;span style="color:#3333ff;"&gt;let&lt;/span&gt; getPosX x = (int)(Math.Abs((Math.Floor -2.0 - x) / stepX))&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#3333ff;"&gt;for&lt;/span&gt; y &lt;span style="color:#3333ff;"&gt;in&lt;/span&gt; [-1.0..stepY..1.0] &lt;span style="color:#3333ff;"&gt;do&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#3333ff;"&gt;for&lt;/span&gt; x &lt;span style="color:#3333ff;"&gt;in&lt;/span&gt; [-2.0..stepX..1.0] &lt;span style="color:#3333ff;"&gt;do &lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#3333ff;"&gt;match&lt;/span&gt; mandelbrot (Complex.Create (x, y)) &lt;span style="color:#3333ff;"&gt;with&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;DidNotEscape -&gt; bmp.SetPixel(getPosX x, getPosY y, Color.FromArgb(255, 255, 255));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;Escaped e -&gt; bmp.SetPixel(getPosX x, getPosY y, Color.FromArgb((min 9 e) * 20, 0, 0));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#3333ff;"&gt;done&lt;/span&gt;;&lt;br /&gt;&lt;span style="color:#3333ff;"&gt;done&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;bmp.Save(String.Format(&lt;span style="color:#990000;"&gt;"Images\\mandelBrot_{0}_{1}.bmp"&lt;/span&gt;, numPixelsX, numPixelsY), ImageFormat.Bmp)&lt;br /&gt;bmp.Save(String.Format(&lt;span style="color:#990000;"&gt;"Images\\mandelBrot_{0}_{1}.png"&lt;/span&gt;, numPixelsX, numPixelsY), ImageFormat.Png)&lt;br /&gt;bmp.Save(String.Format(&lt;span style="color:#990000;"&gt;"Images\\mandelBrot_{0}_{1}.jpeg"&lt;/span&gt;, numPixelsX, numPixelsY), ImageFormat.Jpeg)&lt;/span&gt;&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;And here is a sample of what the output looks like:&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://2.bp.blogspot.com/_zrLYGpcNAqw/R2y6BEgHIgI/AAAAAAAAADc/ak_RH1D9FFE/s1600-h/mandelBrot_300_200.jpeg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5146693001728696834" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://2.bp.blogspot.com/_zrLYGpcNAqw/R2y6BEgHIgI/AAAAAAAAADc/ak_RH1D9FFE/s320/mandelBrot_300_200.jpeg" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Cheers,&lt;/p&gt;&lt;p&gt;Josh&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2837647869424561922-2533815609126113196?l=technofattie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technofattie.blogspot.com/feeds/2533815609126113196/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://technofattie.blogspot.com/2007/12/mandelbrot-bitmap.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default/2533815609126113196'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2837647869424561922/posts/default/2533815609126113196'/><link rel='alternate' type='text/html' href='http://technofattie.blogspot.com/2007/12/mandelbrot-bitmap.html' title='MandelBrot Bitmap'/><author><name>Josh</name><uri>http://www.blogger.com/profile/08438201529460997103</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_zrLYGpcNAqw/SMsZoOUBOhI/AAAAAAAAAQ0/v-9QdkwzIDg/S220/Josh.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_zrLYGpcNAqw/R2y6BEgHIgI/AAAAAAAAADc/ak_RH1D9FFE/s72-c/mandelBrot_300_200.jpeg' height='72' width='72'/><thr:total>1</thr:total></entry></feed>
