<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://devlicio.us/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Billy McCafferty : C#</title><link>http://devlicio.us/blogs/billy_mccafferty/archive/tags/C_2300_/default.aspx</link><description>Tags: C#</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP1 (Build: 31106.3070)</generator><item><title>IT Samurai School coming soon...</title><link>http://devlicio.us/blogs/billy_mccafferty/archive/2009/05/03/it-samurai-school-coming-soon.aspx</link><pubDate>Mon, 04 May 2009 02:32:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:46471</guid><dc:creator>Billy McCafferty</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;As if my life wasn&amp;#39;t boring enough trying to get S#arp Architecture 1.0 out the door...&lt;/p&gt;
&lt;p&gt;&lt;a target="_blank" href="http://www.itsamuraischool.com/"&gt;&lt;img style="border:0;" alt="www.itsamuraischool.com" src="http://devlicio.us/resized-image.ashx/__size/600x450/__key/CommunityServer.Components.UserFiles/00.00.00.21.06/itsamuraischool.gif" width="550" height="347" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=46471" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/Architecture/default.aspx">Architecture</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/.NET/default.aspx">.NET</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/Software+Development/default.aspx">Software Development</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/Algorithms/default.aspx">Algorithms</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/Refactoring/default.aspx">Refactoring</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/NHibernate/default.aspx">NHibernate</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/Project+Management/default.aspx">Project Management</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/Test-Driven+Development/default.aspx">Test-Driven Development</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/Agile+Development/default.aspx">Agile Development</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/MVC.NET/default.aspx">MVC.NET</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/S_2300_arp+Architecture/default.aspx">S#arp Architecture</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/DDD/default.aspx">DDD</category></item><item><title>Code Quiz:  How well do you understand ThreadStatic?</title><link>http://devlicio.us/blogs/billy_mccafferty/archive/2009/01/09/code-quiz-how-well-do-you-understand-threadstatic.aspx</link><pubDate>Fri, 09 Jan 2009 23:51:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:43692</guid><dc:creator>Billy McCafferty</dc:creator><slash:comments>7</slash:comments><description>&lt;p&gt;I just ran into the most interesting bug in recent recollection.&amp;nbsp; What&amp;#39;s wrong with the following code?&lt;/p&gt;
&lt;p&gt;...
public override IEnumerable&amp;lt;PropertyInfo&amp;gt; SignatureProperties {
    get {
        IEnumerable&amp;lt;PropertyInfo&amp;gt; properties;
        
        if (signaturePropertiesDictionary.TryGetValue(GetType(), out properties)) 
            return properties;
        ...
    }
}
[ThreadStatic]
private static readonly Dictionary&amp;lt;Type, IEnumerable&amp;lt;PropertyInfo&amp;gt;&amp;gt; signaturePropertiesDictionary = 
    new Dictionary&amp;lt;Type, IEnumerable&amp;lt;PropertyInfo&amp;gt;&amp;gt;();
...&lt;/p&gt;
&lt;p&gt;And you&amp;#39;re not allowed answering if you get S#arp Architecture forum emails...and no peaking if you&amp;#39;re not!! ;)&lt;/p&gt;
&lt;p&gt;Billy McCafferty &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=43692" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/.NET/default.aspx">.NET</category></item><item><title>The Mother of Exception Handling Anti-Patterns</title><link>http://devlicio.us/blogs/billy_mccafferty/archive/2007/11/30/exception-handling-anti-pattern.aspx</link><pubDate>Fri, 30 Nov 2007 13:36:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:38937</guid><dc:creator>Billy McCafferty</dc:creator><slash:comments>8</slash:comments><description>&lt;p&gt;I know this has been discussed before elsewhere - but since I&amp;#39;m cranky about finding it after not-so-few-minutes of looking in some&amp;nbsp;legacy code I&amp;#39;m working on&amp;nbsp;- what follows is NOT an example of&amp;nbsp;proper exception handling:&lt;/p&gt;
&lt;p&gt;} catch (Exception ex) {
  AuditLogger.LogError(ex);
}&lt;/p&gt;
&lt;p&gt;This &amp;quot;swallow and forget&amp;quot; approach causes an immense amount of pain for all parties involved.&amp;nbsp; I&amp;#39;ve been working on some third party code and&amp;nbsp;was troubled by the fact that the Event Viewer had a number of errors in the log, but that I hadn&amp;#39;t encountered any blatant errors while&amp;nbsp;using the application.&amp;nbsp; I&amp;nbsp;only&amp;nbsp;knew that every once and a while, the application didn&amp;#39;t respond as I expected it to respond.&amp;nbsp; From a developer&amp;#39;s perspective, this is annoying and time consuming to pin down.&amp;nbsp; From a&amp;nbsp;business owner&amp;#39;s perspective,&amp;nbsp;this inconsistent&amp;nbsp;behavior leads to lost business or worse.&lt;/p&gt;
&lt;p&gt;Swallowing&amp;nbsp;the exception is analogous to the &amp;quot;On Error Resume Next&amp;quot; which had many a developer (aka - me) throwing monitors out windows while debugging Active Server Pages way back when and which continues to&amp;nbsp;blemish the VB.NET language.&amp;nbsp; If there&amp;#39;s an exception, it should be assumed that&amp;nbsp;something is terribly wrong; otherwise, it wouldn&amp;#39;t be called an exception.&amp;nbsp; When exceptions occur, the application should fail and fail fast; and if that can&amp;#39;t happen in your application (aka - a pacemaker), then careful attention should be made to ensure that exception recovery is complete, having put the application back into a state as if the exception had not occurred.&lt;/p&gt;
&lt;p&gt;Failing fast doesn&amp;#39;t have to mean failing ugly.&amp;nbsp; Let&amp;#39;s face it, we write bugs in our code.&amp;nbsp; We shouldn&amp;#39;t be embarrassed to politely let the user know that something went wrong (that it wasn&amp;#39;t their fault), that we&amp;#39;ve been informed of the problem, and that we&amp;#39;ll get back to them in a timely and courteous manner with a resolution.&amp;nbsp; But what we shouldn&amp;#39;t be doing is hiding bugs under the rug and keeping our fingers crossed that the application will somehow recover on its own.&amp;nbsp; If you&amp;#39;re lucky, the user won&amp;#39;t notice that anything happened and will be able to continue.&amp;nbsp; But in&amp;nbsp;most cases, these&amp;nbsp;swallowed exceptions confuse users with erratic behavior (that&amp;#39;s erratic &lt;em&gt;application &lt;/em&gt;behavior, not erratic users...although they can be problematic as well) and make it hellishly difficult for developers to figure out why the application is behaving as it is.&lt;/p&gt;
&lt;p&gt;At bare minimum, use the following as a starting point for better exception handling:&lt;/p&gt;
&lt;p&gt;} catch (Exception ex) {
  AuditLogger.LogError(ex);
  throw;
}&lt;/p&gt;
&lt;p&gt;Note that it does not say &amp;quot;throw ex;&amp;quot;&amp;nbsp; The difference is subtle but important.&amp;nbsp; &amp;quot;throw ex;&amp;quot; re-throws the exception and overwrites the stack trace.&amp;nbsp; &amp;quot;throw;&amp;quot; simply allows the exception to pass through as if&amp;nbsp;it had never been caught at all.&lt;/p&gt;
&lt;p&gt;As I assume most of you already know this, please lean over and&amp;nbsp;tap the nearest developer to you who doesn&amp;#39;t read anything, and tell them you&amp;#39;ll beat them with a dead chicken if you ever catch them swallowing exceptions!&amp;nbsp; (Dead chicken optional for any PETA&amp;nbsp;readers out there.)&lt;/p&gt;
&lt;p&gt;Billy McCafferty&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=38937" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/C_2300_/default.aspx">C#</category></item><item><title>Back to Basics:  XOR</title><link>http://devlicio.us/blogs/billy_mccafferty/archive/2007/11/24/back-to-basics-xor.aspx</link><pubDate>Sat, 24 Nov 2007 15:47:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:38917</guid><dc:creator>Billy McCafferty</dc:creator><slash:comments>7</slash:comments><description>&lt;p&gt;Conditionals are a common spot for the unintended creation of un-maintainable and un-readable code.&amp;nbsp; To&amp;nbsp;mitigate complicated conditionals, refactoring with &lt;a href="http://www.refactoring.com/catalog/decomposeConditional.html"&gt;Decompose Conditional&lt;/a&gt; always helps in conveying what you&amp;#39;re trying to do.&amp;nbsp; In other times, it&amp;#39;s simply a matter of making the conditional logic itself less complicated.&amp;nbsp; An oft-overlooked operator within C#, or within any language that supports it, is mutual exclusivity, or &lt;a href="http://en.wikipedia.org/wiki/XOR"&gt;XOR&lt;/a&gt;.&amp;nbsp; This is provided by the&amp;nbsp;^ character in C#.&amp;nbsp; XOR states that&amp;nbsp;a conditional will return true if one&amp;nbsp;operand is true but not the other.&amp;nbsp; The following demonstrates the differences between AND, OR and XOR.&lt;/p&gt;
&lt;p&gt;AND&lt;br /&gt;
&lt;table style="BORDER-RIGHT:black 1px solid;BORDER-TOP:black 1px solid;BORDER-LEFT:black 1px solid;BORDER-BOTTOM:black 1px solid;BACKGROUND-COLOR:#ededed;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="FONT-WEIGHT:bold;"&gt;Operand&lt;/td&gt;
&lt;td style="FONT-WEIGHT:bold;"&gt;Operand&lt;/td&gt;
&lt;td style="FONT-WEIGHT:bold;"&gt;Result&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/p&gt;
&lt;p&gt;OR&lt;br /&gt;
&lt;table style="BORDER-RIGHT:black 1px solid;BORDER-TOP:black 1px solid;BORDER-LEFT:black 1px solid;BORDER-BOTTOM:black 1px solid;BACKGROUND-COLOR:#ededed;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="FONT-WEIGHT:bold;"&gt;Operand&lt;/td&gt;
&lt;td style="FONT-WEIGHT:bold;"&gt;Operand&lt;/td&gt;
&lt;td style="FONT-WEIGHT:bold;"&gt;Result&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/p&gt;
&lt;p&gt;XOR&lt;br /&gt;
&lt;table style="BORDER-RIGHT:black 1px solid;BORDER-TOP:black 1px solid;BORDER-LEFT:black 1px solid;BORDER-BOTTOM:black 1px solid;BACKGROUND-COLOR:#ededed;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="FONT-WEIGHT:bold;"&gt;Operand&lt;/td&gt;
&lt;td style="FONT-WEIGHT:bold;"&gt;Operand&lt;/td&gt;
&lt;td style="FONT-WEIGHT:bold;"&gt;Result&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/p&gt;
&lt;p&gt;Note again that XOR returns false if both are true or both are false,&amp;nbsp;but returns true&amp;nbsp;when only one&amp;nbsp;operand is true.&lt;/p&gt;
&lt;p&gt;When used appropriately, XOR can greatly simplify a conditional statement and ease of readability. Consider the following conditional: &lt;code&gt;((a &amp;gt; 0 &amp;amp;&amp;amp; b &amp;lt;= 0) || (b &amp;gt; 0 &amp;amp;&amp;amp; a &amp;lt;= 0))&lt;/code&gt;. Using the XOR operator, this conditional can be simplified to: &lt;code&gt;(a &amp;gt; 0 ^ b &amp;gt; 0)&lt;/code&gt;. Clean, simple, and easy to read.&amp;nbsp; A review of&amp;nbsp;other&amp;nbsp;&lt;a href="http://msdn2.microsoft.com/en-US/library/6a71f45d(VS.80).aspx"&gt;C# operators on the MSDN site&lt;/a&gt; may lead to the discovery of other&amp;nbsp;coding simplifications&amp;nbsp;that you were not aware of or had long forgotten...or more concisely: &amp;nbsp;(not aware of ^ long forgotten).&amp;nbsp; Sorry, had to do it.&lt;/p&gt;
&lt;p&gt;Billy McCafferty&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=38917" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/C_2300_/default.aspx">C#</category></item><item><title>Using Equals/GetHashCode Effectively</title><link>http://devlicio.us/blogs/billy_mccafferty/archive/2007/04/25/using-equals-gethashcode-effectively.aspx</link><pubDate>Wed, 25 Apr 2007 21:53:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:23429</guid><dc:creator>Billy McCafferty</dc:creator><slash:comments>46</slash:comments><description>&lt;p&gt;[Updated March 10, 2009:&amp;nbsp;&amp;nbsp;&lt;strong&gt;Important!!&lt;/strong&gt;&amp;nbsp; While&amp;nbsp;the original content shown below is usable in most cases, there are scenarios wherein it breaks down.&amp;nbsp;&amp;nbsp;The results of GetHashCode should &lt;em&gt;not&lt;/em&gt; also be used as the means for expressing&amp;nbsp;object equality.&amp;nbsp; Accordingly, this, and other issues have been resolved and may be viewed within S#arp Architecture&amp;#39;s BaseObject.cs class found at &lt;a href="http://sharp-architecture.googlecode.com/svn/trunk/src/SharpArch/SharpArch.Core/DomainModel/BaseObject.cs"&gt;http://sharp-architecture.googlecode.com/svn/trunk/src/SharpArch/SharpArch.Core/DomainModel/BaseObject.cs&lt;/a&gt;.]&lt;/p&gt;
&lt;p&gt;[Updated June 23, 2008:&amp;nbsp; A simplified and more systematic approach to this may be found within &lt;a href="http://code.google.com/p/sharp-architecture/"&gt;S#arp Architecture&lt;/a&gt;.&amp;nbsp; While the complexities of the Equals/GetHashCode method are kept away in a base class, you simply need to add an [Identity] attribute over each property in a class which is part of the domain object&amp;#39;s &amp;quot;signature.&amp;quot;&amp;nbsp; It also supports multiple attributes to be used in the same class for multi-property uniqueness - outside of the ID itself.]&lt;/p&gt;
&lt;p&gt;The ability to override GetHashCode is available on every object but is seldom required for POCOs.&amp;nbsp; The Equals method usually provides all of the comparison functionality we&amp;#39;ll ever&amp;nbsp;need.&amp;nbsp; But when using an ORM such as NHibernate,&amp;nbsp;GetHashCode takes a more prominent role as it helps NHibernate determine if an object already exists in a collection.&amp;nbsp; Not overriding GetHashCode, or doing so inappropriately, may lead to duplicate objects showing up in collections and/or objects missing altogether.&amp;nbsp; When needed, most people implement both methods&amp;nbsp;and end up with&amp;nbsp;similar code in both.&amp;nbsp; So to ease the burden of managing both of these methods, there&amp;#39;s exploitable overlap between Equals and GetHashCode to kill two birds with one stone...no offense to any PETA members out there.&amp;nbsp;&amp;nbsp;(A thanks goes out to &lt;a href="http://devlicio.us/blogs/alan_northam/default.aspx"&gt;Alan Northam&lt;/a&gt; whose&amp;nbsp;approach made me aware of the code duplication I previously had in my own approach.)&lt;/p&gt;
&lt;p&gt;In my project work, I consider the following to be true when comparing two objects:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If two objects have IDs, and have the &lt;i&gt;same&lt;/i&gt; IDs, then they may be considered equal without&amp;nbsp;examining them further.&amp;nbsp; (I&amp;#39;m assuming ID to be an identity field, or equivalent,&amp;nbsp;in the DB.)&lt;/li&gt;
&lt;li&gt;If two objects have IDs, but&amp;nbsp;have &lt;i&gt;different&lt;/i&gt; IDs, than they&amp;nbsp;may be considered&amp;nbsp;not equal without examining them further.&amp;nbsp; E.g., If customer A has an ID of 4 while customer B has an ID of 5, then they are not equal, QED.&lt;/li&gt;
&lt;li&gt;If neither object has an ID or only one of them has an ID,&amp;nbsp;but their &amp;quot;business value signatures&amp;quot; are identical, then they&amp;#39;re equal.&amp;nbsp; E.g., customer A has an ID of 4 and a&amp;nbsp;social-security-number of 123-45-6789 while customer B has no ID but also has a social-security-number of 123-45-6789.&amp;nbsp; In this case, customer A and customer B are equal.&amp;nbsp; By &amp;quot;business signatures,&amp;quot; I imply a combination of those properties which deem an&amp;nbsp;entity unique, regardless of its ID.&amp;nbsp; (As a side, see Eric Evans&amp;#39; &lt;a href="http://www.awprofessional.com/bookstore/product.asp?isbn=0321125215&amp;amp;redir=1&amp;amp;rl=1"&gt;Domain Driven Design&lt;/a&gt; for a stellar conversation of value&amp;nbsp;and entity objects.&amp;nbsp;&amp;nbsp;A &lt;a href="http://www.infoq.com/minibooks/domain-driven-design-quickly"&gt;summary&amp;nbsp;version is also available&lt;/a&gt;.)&lt;/li&gt;
&lt;li&gt;If one of them is null, then they are not equal.&amp;nbsp; (Whoo, that was easy.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With the above considerations in mind, we&amp;#39;ll want to write code to make the following&amp;nbsp;unit test pass.&amp;nbsp; Note that Customer takes a company name into its constructor.&amp;nbsp; It also has&amp;nbsp;a settable contact name.&amp;nbsp; The combination of&amp;nbsp;its company name and contact name give Customer its unique business signature.&lt;/p&gt;
&lt;p&gt;[Test]
public void CanCompareCustomers() {
  Customer customerA = new Customer(&amp;quot;Acme&amp;quot;);
  Customer customerB = new Customer(&amp;quot;Anvil&amp;quot;);
    
  Assert.AreNotEqual(customerA, null);
  Assert.AreNotEqual(customerA, customerB);
  customerA.SetIdTo(1);
  customerB.SetIdTo(1);
  // Even though the signatures are different, 
  // the persistent IDs were the same. Call me 
  // crazy, but I put that much trust into IDs.
  Assert.AreEqual(customerA, customerB);
  Customer customerC = new Customer(&amp;quot;Acme&amp;quot;);
  // Since customerA has an ID but customerC 
  // doesn&amp;#39;t, their signatures will be compared
  Assert.AreEqual(customerA, customerC);
  customerC.ContactName = &amp;quot;Coyote&amp;quot;;
  // Signatures are now different
  Assert.AreNotEqual(customerA, customerC);
  // customerA.Equals(customerB) because they 
  //  have the same ID.
  // customerA.Equals(customerC) because they 
  //  have the same signature.
  // customerB.DoesNotEquals(customerC) because 
  //  we can&amp;#39;t compare their IDs, since 
  //  customerC is transient, and their 
  //  signatures are different.
  Assert.AreNotEqual(customerB, customerC);
}&lt;/p&gt;
&lt;p&gt;Although some argue against a single object which all other persistable domain objects inherit from, I use one nonetheless and&amp;nbsp;ingeniously call it &amp;quot;DomainObject.&amp;quot;&amp;nbsp; (Those are&amp;nbsp;Dr. Evil quotes there.)&amp;nbsp; &amp;quot;DomainObject,&amp;quot; in its entirety, contains the following:&lt;/p&gt;
&lt;p&gt;public abstract class DomainObject&amp;lt;IdT&amp;gt;
{
  /// &amp;lt;summary&amp;gt;
  /// ID may be of type string, int, 
  /// custom type, etc.
  /// &amp;lt;/summary&amp;gt;
  public IdT ID {
    get { return id; }
  }
  public override sealed bool Equals(object obj) {
    DomainObject&amp;lt;IdT&amp;gt; compareTo = 
      obj as DomainObject&amp;lt;IdT&amp;gt;;
    return (compareTo != null) &amp;amp;&amp;amp;
      (HasSameNonDefaultIdAs(compareTo) ||
       // Since the IDs aren&amp;#39;t the same, either 
       // of them must be transient to compare 
       // business value signatures
       (((IsTransient()) || compareTo.IsTransient()) &amp;amp;&amp;amp;
       HasSameBusinessSignatureAs(compareTo)));
  }
  /// &amp;lt;summary&amp;gt;
  /// Transient objects are not associated with an 
  /// item already in storage.  For instance, a 
  /// Customer is transient if its ID is 0.
  /// &amp;lt;/summary&amp;gt;
  public bool IsTransient() {
    return ID == null || ID.Equals(default(IdT));
  }
  /// &amp;lt;summary&amp;gt;
  /// Must be implemented to compare two objects
  /// &amp;lt;/summary&amp;gt;
  public abstract override int GetHashCode();
  private bool HasSameBusinessSignatureAs(DomainObject&amp;lt;IdT&amp;gt; compareTo) {
    return GetHashCode().Equals(compareTo.GetHashCode());
  }
  /// &amp;lt;summary&amp;gt;
  /// Returns true if self and the provided domain 
  /// object have the same ID values and the IDs 
  /// are not of the default ID value
  /// &amp;lt;/summary&amp;gt;
  private bool HasSameNonDefaultIdAs(DomainObject&amp;lt;IdT&amp;gt; compareTo) {
    return (ID != null &amp;amp;&amp;amp; 
            ! ID.Equals(default(IdT))) &amp;amp;&amp;amp;
      (compareTo.ID != null &amp;amp;&amp;amp; 
       ! compareTo.ID.Equals(default(IdT))) &amp;amp;&amp;amp;
      ID.Equals(compareTo.ID);
  }
  /// &amp;lt;summary&amp;gt;
  /// Set to protected to allow unit tests to set 
  /// this property via reflection and to allow 
  /// domain objects more flexibility in setting 
  /// this for those objects with assigned IDs.
  /// &amp;lt;/summary&amp;gt;
  protected IdT id = default(IdT);
} &lt;/p&gt;
&lt;p&gt;Note that Equals is sealed and&amp;nbsp;cannot be overridden by a DomainObject implementation.&amp;nbsp; I suppose it could be unsealed, but since I put a lot of work into that method, I&amp;nbsp;don&amp;#39;t want anyone mucking it up!&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Now assume that Customer implements DomainObject.&amp;nbsp; As mentioned above, the combination of its company name and contact name give it its unique signature.&amp;nbsp; So its GetHashCode&amp;nbsp;would be&amp;nbsp;as follows:&lt;/p&gt;
&lt;p&gt;public override int GetHashCode() {
    return (GetType().FullName + &amp;quot;|&amp;quot; +
            CompanyName + &amp;quot;|&amp;quot; +
            ContactName).GetHashCode();
}&lt;/p&gt;
&lt;p&gt;You&amp;#39;ll notice that the start of the method includes the full name of the class type itself.&amp;nbsp; With this in place, two different classes would never return the same signature.&amp;nbsp; (You&amp;#39;ll have to reconsider how&amp;nbsp;GetHashCode is&amp;nbsp;implemented to handle inheritance structures; e.g. a Customer and an Employee both inherit from a Person class but Customer and Employee may be&amp;nbsp;equal in some instances...for this, I&amp;#39;d probably only add GetHashCode to the Person class.)&amp;nbsp; Additionally, note that GetHashCode should &lt;i&gt;only&lt;/i&gt; contain the &amp;quot;business signature&amp;quot; of the object and not include its ID.&amp;nbsp; Including the ID in the signature would make it impossible to find equality between a transient object&amp;nbsp;and a ! transient object.&amp;nbsp; (Equality for all regardless of transience I say!)&lt;/p&gt;
&lt;p&gt;Billy McCafferty&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=23429" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/NHibernate/default.aspx">NHibernate</category></item><item><title>Varying a Property's get/set Accessibility</title><link>http://devlicio.us/blogs/billy_mccafferty/archive/2007/02/15/varying-a-property-s-get-set-accessibility.aspx</link><pubDate>Thu, 15 Feb 2007 23:55:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:12219</guid><dc:creator>Billy McCafferty</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/billy_mccafferty/rsscomments.aspx?PostID=12219</wfw:commentRss><comments>http://devlicio.us/blogs/billy_mccafferty/archive/2007/02/15/varying-a-property-s-get-set-accessibility.aspx#comments</comments><description>&lt;P&gt;It is a common occurrence wherein you may want to publicly expose a property's getter&amp;nbsp;but&amp;nbsp;internally restrict the setter. (The &lt;A class="" href="http://devlicio.us/blogs/billy_mccafferty/archive/2006/12/18/refactor-it-challenge-3.aspx"&gt;last refactoring challenge&lt;/A&gt;&amp;nbsp;had a good use for this.)&amp;nbsp; I regularly see people provide a publicly exposed property - with only a getter - and then add an internally available method for setting that property. Alternatively, as long as you're only "tightening" access, you can simply pre-append the appropriate access keyword in front of the get/set, accordingly. For example:&lt;/P&gt;&lt;TEXTAREA class=c#:nogutter name=code rows=4 cols=50&gt;public string Description {
    get { return description; }
    internal set { description = value; }
}&lt;/TEXTAREA&gt; 
&lt;P&gt;In the above code, the getter is publicly available while the setter is only internally available to the assembly in which it's defined. You can also use protected, private and logical combinations, if needed.&lt;/P&gt;
&lt;P&gt;Billy&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=12219" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/C_2300_/default.aspx">C#</category></item><item><title>Inject DI Container into Domain Objects with NHibernate</title><link>http://devlicio.us/blogs/billy_mccafferty/archive/2007/02/05/inject-di-container-into-domain-objects-with-nhibernate.aspx</link><pubDate>Tue, 06 Feb 2007 00:52:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:9685</guid><dc:creator>Billy McCafferty</dc:creator><slash:comments>25</slash:comments><description>&lt;P&gt;I've been asked a couple of times how to give a domain object access to a dependency injection (DI) container, such as Castle Windsor, if the domain object is loaded via an ORM, such as NHibernate.&amp;nbsp; There are two apparent ways to do this:&amp;nbsp; 1) you can manually give the domain object access to the DI via "setter injection" from your controller or service layer, or 2) you can use an NHibernate IInterceptor to preset the DI container when the object is loaded from the database.&amp;nbsp; The latter is much cleaner and avoids having to pass service&amp;nbsp;object references through middlemen classes.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Disclaimer:&lt;/STRONG&gt;&amp;nbsp; I feel I should&amp;nbsp;add a&amp;nbsp;disclaimer to this post that this technique should not&amp;nbsp;be used as standard practice.&amp;nbsp; Giving domain objects direct access to the DI container can be very powerful but also enables the domain layer to take on responsibilities that it should not have.&amp;nbsp; Furthermore, having access to the DI container from the domain layer creates, at the very least,&amp;nbsp;a virtual dependency on everything available via the DI container; consequently, additional maintenance issues may have to be considered.&amp;nbsp; Finally, the DI container itself presents another layer of indirection which can be difficult to&amp;nbsp;easily understand during the maintenance phase of a project.&amp;nbsp; With that said...&lt;/P&gt;
&lt;P&gt;Assume you want to show who a customer was referred by but can't set it up in a nice HBM mapping.&amp;nbsp; The only way you can do it, for some reason or another, is by having the Customer instance make an explicit call to the database.&amp;nbsp; Our goals are 1) to keep Customer only dependent on DAO &lt;EM&gt;interfaces&lt;/EM&gt; and 2) to automatically inject the DAO dependency to Customer as soon as its loaded from the database even if it's loaded via an ORM.&amp;nbsp; (Obviously, this example is a little strange to begin with but illustrates the technique, nonetheless.&amp;nbsp; The technique is equally applicable for providing other services, such as an email utility.)&lt;/P&gt;
&lt;P&gt;If you'd like to walk through modifying an application, already wired for Castle Windsor, to accommodate doing this,&amp;nbsp;download the &lt;A class="" href="http://www.codeproject.com/useritems/ModelViewPresenter/EnterpriseApplicationMvp.zip"&gt;"enterprise" sample app&lt;/A&gt; found&amp;nbsp;within&amp;nbsp;the &lt;A class="" href="http://www.codeproject.com/useritems/ModelViewPresenter.asp"&gt;MVP with ASP.NET article on CodeProject.com&lt;/A&gt;&amp;nbsp;and follow the steps below.&amp;nbsp;&amp;nbsp;(Alternatively, you can just download the sample at the end of this post to see the finished product.)&amp;nbsp; You'll need to follow the steps found within the article to get it working with your SQL Server/Northwind database.&amp;nbsp; The modification steps to the sample app are as follows:&lt;/P&gt;
&lt;P&gt;1) First, since we always take a test-driven approach (right?), amend MvpSample.Tests.Data.CustomerDaoTests to reflect the following:&lt;/P&gt;
&lt;DIV style="FONT-SIZE:10pt;BACKGROUND:white;OVERFLOW:auto;COLOR:black;FONT-FAMILY:Courier New;"&gt;
&lt;P style="MARGIN:0px;"&gt;[&lt;SPAN style="COLOR:#2b91af;"&gt;TestFixture&lt;/SPAN&gt;]&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;[&lt;SPAN style="COLOR:#2b91af;"&gt;Category&lt;/SPAN&gt;(&lt;SPAN style="COLOR:#a31515;"&gt;"NHibernate Tests"&lt;/SPAN&gt;)]&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:blue;"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;class&lt;/SPAN&gt; &lt;SPAN style="COLOR:#2b91af;"&gt;CustomerDaoTests&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;{&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; Initializes the NHibernate session bound to &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; HttpContext. This TestFixtureSetUp could be &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; moved to a NHibernateUnitTest class so you &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; don't have to &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; copy/past it into every unit test class.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;SPAN style="COLOR:#2b91af;"&gt;TestFixtureSetUp&lt;/SPAN&gt;]&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;void&lt;/SPAN&gt; Setup() {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:#2b91af;"&gt;NHibernateSessionManager&lt;/SPAN&gt;.Instance&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; .RegisterInterceptor(&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR:#2b91af;"&gt;NHibernateInterceptor&lt;/SPAN&gt;());&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:#2b91af;"&gt;NHibernateSessionManager&lt;/SPAN&gt;.Instance&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; .BeginTransaction();&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; Tests successful dependency injection &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; from within the domain layer.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;SPAN style="COLOR:#2b91af;"&gt;Test&lt;/SPAN&gt;]&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;void&lt;/SPAN&gt; TestGetReferrer() {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:#2b91af;"&gt;IDaoFactory&lt;/SPAN&gt; daoFactory = &lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR:#2b91af;"&gt;NHibernateDaoFactory&lt;/SPAN&gt;();&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:#2b91af;"&gt;ICustomerDao&lt;/SPAN&gt; customerDao = &lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; daoFactory.GetCustomerDao();&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:#2b91af;"&gt;Customer&lt;/SPAN&gt; foundCustomer = &lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; customerDao.GetById(&lt;SPAN style="COLOR:#a31515;"&gt;"CHOPS"&lt;/SPAN&gt;, &lt;SPAN style="COLOR:blue;"&gt;false&lt;/SPAN&gt;);&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:#2b91af;"&gt;Customer&lt;/SPAN&gt; referrer = &lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; foundCustomer.GetReferrer();&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:#2b91af;"&gt;Assert&lt;/SPAN&gt;.AreEqual(&lt;SPAN style="COLOR:#a31515;"&gt;"Folies gourmandes"&lt;/SPAN&gt;, &lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; referrer.CompanyName);&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;... remainder of pre-existing tests... &lt;/P&gt;
&lt;P&gt;In the above code, you can see that we're doing two new things.&amp;nbsp; First, we've added the call to RegisterInterceptor to the Setup method.&amp;nbsp; (Since you have to register interceptors &lt;EM&gt;before&lt;/EM&gt; starting a transaction, the order is important here.)&amp;nbsp; So, as the code implies, we can wire up container DI via a custom, NHibernate Interceptor.&amp;nbsp; The second thing to note is the new test.&amp;nbsp; We'll be adding the method GetReferrer, which will&amp;nbsp;use the DI container,&amp;nbsp;to the Customer&amp;nbsp;class.&lt;/P&gt;
&lt;P&gt;2) If you try to compile the above change, VS will initially complain about the missing NHibernate interceptor class.&amp;nbsp; So add a new class called NHibernateInterceptor and at it to the MvpSample.Data package.&amp;nbsp; Since it's specific to the data layer - and to NHibernate for that matter -&amp;nbsp;the data layer is&amp;nbsp;the appropriate place to put it.&amp;nbsp; The class is defined as follows:&lt;/P&gt;
&lt;DIV style="FONT-SIZE:10pt;BACKGROUND:white;OVERFLOW:auto;COLOR:black;FONT-FAMILY:Courier New;"&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:blue;"&gt;namespace&lt;/SPAN&gt; MvpSample.Data&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;{&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;class&lt;/SPAN&gt; &lt;SPAN style="COLOR:#2b91af;"&gt;NHibernateInterceptor&lt;/SPAN&gt; : &lt;SPAN style="COLOR:#2b91af;"&gt;IInterceptor&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;bool&lt;/SPAN&gt; OnLoad(&lt;SPAN style="COLOR:blue;"&gt;object&lt;/SPAN&gt; entity, &lt;SPAN style="COLOR:blue;"&gt;object&lt;/SPAN&gt; id, &lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;object&lt;/SPAN&gt;[] state, &lt;SPAN style="COLOR:blue;"&gt;string&lt;/SPAN&gt;[] propertyNames, &lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:#2b91af;"&gt;IType&lt;/SPAN&gt;[] types)&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:green;"&gt;// Only use "setter injection" to give objects&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:green;"&gt;// that implement IUsesDependencyInjection a &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:green;"&gt;// reference to the DI container.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;if&lt;/SPAN&gt; (&lt;SPAN style="COLOR:blue;"&gt;typeof&lt;/SPAN&gt;(&lt;SPAN style="COLOR:#2b91af;"&gt;IUsesDependencyInjection&lt;/SPAN&gt;)&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; .IsInstanceOfType(entity)) {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ((&lt;SPAN style="COLOR:#2b91af;"&gt;IUsesDependencyInjection&lt;/SPAN&gt;) entity)&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; .DependencyInjectionContainer =&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR:#2b91af;"&gt;WindsorContainer&lt;/SPAN&gt;(&lt;SPAN style="COLOR:blue;"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR:#2b91af;"&gt;XmlInterpreter&lt;/SPAN&gt;());&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:green;"&gt;// Even though we gave the object it's DI &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:green;"&gt;// container, return the fact that we &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:green;"&gt;// didn't modify the persistent properties&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;return&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;false&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;bool&lt;/SPAN&gt; OnFlushDirty(&lt;SPAN style="COLOR:blue;"&gt;object&lt;/SPAN&gt; entity, &lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;object&lt;/SPAN&gt; id, &lt;SPAN style="COLOR:blue;"&gt;object&lt;/SPAN&gt;[] currentState, &lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;object&lt;/SPAN&gt;[] previousState, &lt;SPAN style="COLOR:blue;"&gt;string&lt;/SPAN&gt;[] propertyNames, &lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:#2b91af;"&gt;IType&lt;/SPAN&gt;[] types)&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:green;"&gt;// Return the fact that we didn't &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:green;"&gt;// modify the entity&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;return&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;false&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;bool&lt;/SPAN&gt; OnSave(&lt;SPAN style="COLOR:blue;"&gt;object&lt;/SPAN&gt; entity, &lt;SPAN style="COLOR:blue;"&gt;object&lt;/SPAN&gt; id, &lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;object&lt;/SPAN&gt;[] state, &lt;SPAN style="COLOR:blue;"&gt;string&lt;/SPAN&gt;[] propertyNames, &lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:#2b91af;"&gt;IType&lt;/SPAN&gt;[] types)&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:green;"&gt;// Return the fact that we didn't &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:green;"&gt;// modify the entity&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;return&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;false&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;void&lt;/SPAN&gt; OnDelete(&lt;SPAN style="COLOR:blue;"&gt;object&lt;/SPAN&gt; entity, &lt;SPAN style="COLOR:blue;"&gt;object&lt;/SPAN&gt; id, &lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;object&lt;/SPAN&gt;[] state, &lt;SPAN style="COLOR:blue;"&gt;string&lt;/SPAN&gt;[] propertyNames, &lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:#2b91af;"&gt;IType&lt;/SPAN&gt;[] types) {}&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;void&lt;/SPAN&gt; PreFlush(&lt;SPAN style="COLOR:#2b91af;"&gt;ICollection&lt;/SPAN&gt; entities) {}&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;void&lt;/SPAN&gt; PostFlush(&lt;SPAN style="COLOR:#2b91af;"&gt;ICollection&lt;/SPAN&gt; entities) {}&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;object&lt;/SPAN&gt; IsUnsaved(&lt;SPAN style="COLOR:blue;"&gt;object&lt;/SPAN&gt; entity) {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;return&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;null&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;int&lt;/SPAN&gt;[] FindDirty(&lt;SPAN style="COLOR:blue;"&gt;object&lt;/SPAN&gt; entity, &lt;SPAN style="COLOR:blue;"&gt;object&lt;/SPAN&gt; id, &lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;object&lt;/SPAN&gt;[] currentState, &lt;SPAN style="COLOR:blue;"&gt;object&lt;/SPAN&gt;[] previousState, &lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;string&lt;/SPAN&gt;[] propertyNames, &lt;SPAN style="COLOR:#2b91af;"&gt;IType&lt;/SPAN&gt;[] types) {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;return&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;null&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;object&lt;/SPAN&gt; Instantiate(&lt;SPAN style="COLOR:#2b91af;"&gt;Type&lt;/SPAN&gt; type, &lt;SPAN style="COLOR:blue;"&gt;object&lt;/SPAN&gt; id) {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;return&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;null&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;}&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;The only bit of interesting code is found within the method OnLoad.&amp;nbsp; This method first checks to see if the persistent object being loaded implements the interface IUsesDependencyInjection and then sets the publicly accessible property to give the object a reference to the Castle Windsor container.&amp;nbsp; This is also called "setter injection."&lt;/P&gt;
&lt;P&gt;3) The next logical step is to define the IUsesDependencyInjection interface.&amp;nbsp; This will be implemented by our persistent business objects which should have a reference to the DI container when they're loaded from the database.&amp;nbsp; The interface will be added to the MvpSample.Core project since the business objects will be implementing it.&amp;nbsp; The simple interface is as follows:&lt;/P&gt;
&lt;DIV style="FONT-SIZE:10pt;BACKGROUND:white;OVERFLOW:auto;COLOR:black;FONT-FAMILY:Courier New;"&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:blue;"&gt;namespace&lt;/SPAN&gt; MvpSample.Core.DataInterfaces&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;{&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;interface&lt;/SPAN&gt; &lt;SPAN style="COLOR:#2b91af;"&gt;IUsesDependencyInjection&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:#2b91af;"&gt;IWindsorContainer&lt;/SPAN&gt; DependencyInjectionContainer {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;set&lt;/SPAN&gt;; &lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;get&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;}&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;4) Now modify MvpSample.Core.Domain.Customer to implement this interface.&amp;nbsp; It'll immediatly complain that Custom needs to implement the getter/setter from the interface.&amp;nbsp; You have a choice here; you can either implement the code in the Customer class itself, or, you can add it to the persistent object super class called DomainObject.&amp;nbsp; (I.e. All persistent objects inherit from this class in the sample project.)&amp;nbsp; I chose to put the implementation details into DomainObject for two reasons:&amp;nbsp; A) it's now reusable without any duplicated code and exposes a very handy public setter for all persistent classes and B) you can place pre-condition code in the getter to ensure that the DI container has been set before it's used.&amp;nbsp; The latter point will avoid any unexpected "object reference was null" exceptions.&amp;nbsp; The downside to putting it into DomainObject is that it exposes a lot more power to a lot more classes.&amp;nbsp; So this should be avoided if it's only going to be used by a couple of objects.&amp;nbsp; (Regardless,&amp;nbsp;DomainObject shouldn't inherit from IUsesDependencyInjection, only Customer should, at this time; otherwise, the interceptor will automatically give every persistent object a reference to the container...which might not be a terrible thing in some situations.)&amp;nbsp; So in the DomainObject class, we add:&lt;/P&gt;
&lt;DIV style="FONT-SIZE:10pt;BACKGROUND:white;OVERFLOW:auto;COLOR:black;FONT-FAMILY:Courier New;"&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; Publicly accessible to allow the dependency &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; injection container to be given to the object.&amp;nbsp; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; If you have your domain object implement &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;&amp;lt;see cref="IUsesDependencyInjection" /&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt;, &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; it'll automatically be wired up with the DI &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; container when loaded with the ORM. If &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; someone&amp;nbsp; has switched out the ORM or &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; disabled this, then the container can still &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; be set via this property.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:blue;"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR:#2b91af;"&gt;IWindsorContainer&lt;/SPAN&gt; DependencyInjectionContainer {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;set&lt;/SPAN&gt; {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; dependencyInjectionContainer = &lt;SPAN style="COLOR:blue;"&gt;value&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;get&lt;/SPAN&gt; {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;if&lt;/SPAN&gt; (dependencyInjectionContainer == &lt;SPAN style="COLOR:blue;"&gt;null&lt;/SPAN&gt;) &lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;throw&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR:#2b91af;"&gt;ApplicationException&lt;/SPAN&gt;(&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:#a31515;"&gt;"dependencyInjectionContainer has not "&lt;/SPAN&gt; +&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:#a31515;"&gt;"yet been initialized"&lt;/SPAN&gt;);&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;return&lt;/SPAN&gt; dependencyInjectionContainer;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;}&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;5)&amp;nbsp;The only remaining piece, to get the unit test working, is to add the GetReferrer method to Customer:&lt;/P&gt;
&lt;DIV style="FONT-SIZE:10pt;BACKGROUND:white;OVERFLOW:auto;COLOR:black;FONT-FAMILY:Courier New;"&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; This is an example of using DI from &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; the domain layer itself.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:blue;"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR:#2b91af;"&gt;Customer&lt;/SPAN&gt; GetReferrer() {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:green;"&gt;// Obviously, hard-coding "FOLIG" is &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:green;"&gt;// unrealistic...but it'll work to illustrate&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:green;"&gt;// the use of a DI container from within the &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:green;"&gt;// domain layer.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;return&lt;/SPAN&gt; ((&lt;SPAN style="COLOR:#2b91af;"&gt;IDaoFactory&lt;/SPAN&gt;) &lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; DependencyInjectionContainer[&lt;SPAN style="COLOR:blue;"&gt;typeof&lt;/SPAN&gt;(&lt;SPAN style="COLOR:#2b91af;"&gt;IDaoFactory&lt;/SPAN&gt;)])&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; .GetCustomerDao().GetById(&lt;SPAN style="COLOR:#a31515;"&gt;"FOLIG"&lt;/SPAN&gt;, &lt;SPAN style="COLOR:blue;"&gt;false&lt;/SPAN&gt;);&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;}&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;6) The NUnit test that we wrote previously should now compile and run successfully.&amp;nbsp; (Be sure to copy the web's Config folder into the MvpSample.Tests/bin/Debug so the unit test will find it.&amp;nbsp; A post-compilation&amp;nbsp;script would be good for doing this on future builds.)&lt;/P&gt;
&lt;P&gt;7) Now that we have the unit test working successfully, all we have to do is modify the NHibernateSessionModule (an IHttpModule) to register the interceptor when the transaction-per-web-request is started:&lt;/P&gt;
&lt;DIV style="FONT-SIZE:10pt;BACKGROUND:white;OVERFLOW:auto;COLOR:black;FONT-FAMILY:Courier New;"&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; Opens a session within a transaction at the &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; beginning of the HTTP request. This doesn't &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; actually open a connection to the database &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; until needed.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:gray;"&gt;///&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:blue;"&gt;private&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;void&lt;/SPAN&gt; BeginTransaction(&lt;SPAN style="COLOR:blue;"&gt;object&lt;/SPAN&gt; sender, &lt;SPAN style="COLOR:#2b91af;"&gt;EventArgs&lt;/SPAN&gt; e) {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:green;"&gt;// This needs to be called BEFORE begin &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:green;"&gt;// transaction since an interceptor can't&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:green;"&gt;// be registered after a session has been &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:green;"&gt;// created.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:#2b91af;"&gt;NHibernateSessionManager&lt;/SPAN&gt;.Instance&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; .RegisterInterceptor(&lt;SPAN style="COLOR:blue;"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR:#2b91af;"&gt;NHibernateInterceptor&lt;/SPAN&gt;());&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:#2b91af;"&gt;NHibernateSessionManager&lt;/SPAN&gt;.Instance&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; .BeginTransaction();&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;}&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;Obviously, you don't &lt;EM&gt;have&lt;/EM&gt; to use a transaction for this to work, but it shows how an interceptor works when a transaction is being used.&lt;/P&gt;
&lt;P&gt;8) To see it all in action, add a lblReferredBy label to the web project page found at /Views/EditCustomerView.ascx and set its text value to the referrer from within the set property of CustomerToUpdate, found within its code-behind page:&lt;/P&gt;
&lt;DIV style="FONT-SIZE:10pt;BACKGROUND:white;OVERFLOW:auto;COLOR:black;FONT-FAMILY:Courier New;"&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:blue;"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR:#2b91af;"&gt;Customer&lt;/SPAN&gt; CustomerToUpdate {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;get&lt;/SPAN&gt; { ...&amp;nbsp;}&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;set&lt;/SPAN&gt; {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; lblReferredBy.Text = &lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;value&lt;/SPAN&gt;.GetReferrer().CompanyName;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;...&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;}&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;That's it in a nutshell.&amp;nbsp; The process goes as follows:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;
&lt;DIV&gt;Web request gets sent to server.&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV&gt;NHibernateSessionModule creates the interceptor, registers it with the Open-Session-in-View session and begins a transaction.&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV&gt;Page loads a persistent object from the database.&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV&gt;NHibernateInterceptor checks to see if the object being loaded implements IUsesDependencyInjection and sets its DI container, accordingly.&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV&gt;Other code calls the method GetReferrer, found on the Customer object.&amp;nbsp; GetReferrer uses the DI container to load another Customer from the database via a data-access object.&amp;nbsp; But before it's loaded, the getter method of the DI container ensures that&amp;nbsp;the DI container is available for use and throws an exception if not.&amp;nbsp;&lt;/DIV&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;This tutorial has shown how to give a domain object a reference to a DI container if that object was loaded from the database using NHibernate.&amp;nbsp; The attached sample is a working version of all the steps mentioned above.&lt;/P&gt;
&lt;P&gt;As always, please let me know if you have any comments, questions or suggestions.&lt;/P&gt;
&lt;P&gt;Billy&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=9685" width="1" height="1"&gt;</description><enclosure url="http://devlicio.us" length="1020341" type="application/x-zip-compressed" /><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/NHibernate/default.aspx">NHibernate</category></item><item><title>Refactor It! Challenge 3 - The State of Things</title><link>http://devlicio.us/blogs/billy_mccafferty/archive/2006/12/18/refactor-it-challenge-3.aspx</link><pubDate>Tue, 19 Dec 2006 06:23:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:1923</guid><dc:creator>Billy McCafferty</dc:creator><slash:comments>13</slash:comments><description>If you're not familiar with the Refactor It! challenges, please &lt;A href="http://devlicio.us/blogs/billy_mccafferty/archive/2006/11/13/refactor-it-the-weekly-book-giveaway.aspx"&gt;read this post&lt;/A&gt;. (Yes, this one is quite a bit overdue.) Now on to challenge 3...&lt;BR&gt;&lt;BR&gt;Welcome back to another refactoring challenge! This challenge will pit your skills against the very useful &lt;A class="" href="http://www.dofactory.com/Patterns/PatternState.aspx"&gt;State Design Pattern&lt;/A&gt; along with writing your own unit tests. It should take 1-2 hours for senior developers and a couple more for others. While the previous challenge made you focus only on the refactoring without worrying about writing unit tests, this challenge requires you to complete the refactoring &lt;I&gt;along with&lt;/I&gt; writing your own unit tests. Here's the premise...&lt;BR&gt;&lt;BR&gt;&lt;B&gt;Background &amp;amp; Problem&lt;/B&gt;&lt;BR&gt;&lt;BR&gt;This "refactoring to patterns" challenge surfaced during the past couple of weeks on an actual project. The real-world project is a project management tool that interfaces with a schedule management tool. The schedule management tool maintains a listing of project activities which include scheduled start/finish dates, actual start/finish dates (if they're available), and a remaining duration of the activity. (For the purposes of this challenge, many other activity properties have been dropped for simplification.) Since an API was not available to work with the scheduling tool's data, I had to communicate with its database directly. The problem was that quite a lot of business rules were executed when an activity changed from Not Started to Started, for example. ("Not Started" activities have scheduled start/finish dates but no actual dates; "Started" activities have an actual start date, a scheduled finish date but no other dates; and "Finished" activities have actual start/finish dates and no scheduled start/finish dates.) Taking a quick look at the class Challenge3.Domain.ProjectActivity shows how quickly this is getting out of hand. &lt;BR&gt;&lt;BR&gt;&lt;B&gt;Your Incentive&lt;/B&gt;&lt;BR&gt;&lt;BR&gt;Up for grabs this week is the following book along with a &lt;A class="" href="http://submain.com/?nav=products.cio" target=_blank&gt;CodeIt.Once Refactoring&lt;/A&gt; tool 3-User license pack! This seminal writing has become a required part of any serious developer's bookshelf.&lt;BR&gt;
&lt;P&gt;&lt;IMG alt="Design Patterns: Elements of Reusable Object-Oriented Software" src="http://www.awprofessional.com/ShowCover.asp?isbn=0201633612&amp;amp;type=c" width=125&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.awprofessional.com/bookstore/product.asp?isbn=0201633612&amp;amp;rl=1"&gt;Design Patterns: Elements of Reusable Object-Oriented Software&lt;/A&gt;&lt;BR&gt;By Erich Gamma, Richard Helm, Ralph Johnson, John M. Vlissides.&lt;/P&gt;&lt;B&gt;Instructions to Enter&lt;/B&gt;&lt;BR&gt;&lt;BR&gt;Make sure you read all the instructions as they're different from the previous challenge! 
&lt;OL&gt;
&lt;LI&gt;Make sure you have NUnit installed; available at &lt;A href="http://www.nunit.org/" target=_blank&gt;http://www.nunit.org/&lt;/A&gt;.&lt;/LI&gt;
&lt;LI&gt;Download Challenge3.zip, found below.&lt;/LI&gt;
&lt;LI&gt;Open the solution with VS 2005 and compile it.&lt;/LI&gt;
&lt;LI&gt;Open NUnit, go to File/Open, then open &amp;lt;solution directory&amp;gt;/Challenge3.Tests/bin/Debug/Challenge3.Tests.dll. Click run and make sure all the tests pass. There should be a few unit tests that are ignored; but none should be failing.&lt;/LI&gt;
&lt;LI&gt;Complete the refactorings as described below. Be sure to follow the style of the code that is already in place: classes, methods and public properties in PascalCase, private members in camelCase, etc. Following the style that's already there is always a good rule of thumb when modifying legacy code.&lt;/LI&gt;
&lt;LI&gt;When finished with the refactorings, make sure all the unit tests are still passing and that no test is being ignored, zip up your solution and send to &lt;A href="mailto:challenge3@emccafferty.com"&gt;challenge3@emccafferty.com&lt;/A&gt;. As you may only win once, only submit a solution if you'd like to be eligible for the prize or let me know that you don't want to be entered for the drawing.&lt;BR&gt;Because of the upcoming holiday schedule, the due date for your submission is &lt;SPAN style="FONT-WEIGHT:bold;COLOR:red;"&gt;Thursday night at midnight, January 4, US mountain time&lt;/SPAN&gt;.&lt;/LI&gt;&lt;/OL&gt;&lt;B&gt;Challenge 3 Download Overview&lt;/B&gt;&lt;BR&gt;&lt;BR&gt;The VS 2005 solution contains two projects: 
&lt;UL&gt;
&lt;LI&gt;Challenge3.Core: This class library contains the business logic layer of the application. This class library is further broken down as follows: 
&lt;UL&gt;
&lt;LI&gt;The Domain folder contains all the entities and value objects. It also contains a sub-folder, ActivityState, which will hold the state design-pattern classes.&lt;/LI&gt;
&lt;LI&gt;The Utils folder contains a design-by-contract &lt;A href="http://www.codeproject.com/csharp/designbycontract.asp"&gt;utility class written by Kevin McFarlane&lt;/A&gt;. The utility class is for all the Check.Requires you'll see throughout the code.&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;
&lt;LI&gt;Challenge3.Tests: This class library contains the unit tests of the application. As there is no defined presentation layer, the unit tests serve as a portal to how the application works.&lt;/LI&gt;&lt;/UL&gt;&lt;B&gt;Now Refactor It!&lt;/B&gt;&lt;BR&gt;&lt;BR&gt;Below is a listing of smells that need to be fixed within the project. Each point indicates the file that contains the smell, a description of the problem and any guidelines for completing the refactoring. There may be other smells in the code, but these are the only ones that should be addressed.&lt;BR&gt;&lt;BR&gt;&lt;I&gt;Smell: Conditional Complexity&lt;/I&gt;&lt;BR&gt;&lt;I&gt;Refactoring: &lt;A href="http://industriallogic.com/xp/refactoring/alteringConditionalsWithState.html"&gt;Replace State-Altering Conditionals with State&lt;/A&gt;&lt;/I&gt;&lt;BR&gt;&lt;BR&gt;Although there's only one smell to be refactoring in this challenge, it's an ugly one!&lt;BR&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;I&gt;Challenge3.Domain.ProjectActivity&lt;/I&gt;: This domain class represents a specific activity within a project's schedule. In the real-world app that this was inspired by, I was communicating with a third party database and had to respect the rules of the data communications being performed by the third party client app. (I was bypassing the client app altogether with my own code but needed to ensure continued data integrity.) For example, if an activity is currently Not Started and becomes Started, then the &lt;I&gt;scheduled&lt;/I&gt; start date needs to be set to a null date and the &lt;I&gt;actual&lt;/I&gt; start date then needs to be set, accordingly. In addition to this, the remaining duration of the activity needs to be calculated and set. A simple implementation of the state pattern could remedy the conditional logic in the UpdateActivityStartAndFinishWith method. &lt;I&gt;But here's the kicker...&lt;/I&gt;you need to take into account not only the object's current state but what state it will be in next. For instance, going from Not Started to Finished is &lt;I&gt;not&lt;/I&gt; the same as going from Started to Finished. In the real-world app that this was inspired by, there were unique actions which needed to take place for each of the nine possible transitions; e.g. Not Started to Started, Not Started to Not Started (this isn't necessarily a state change, but the dates can still be modified), Not Started to Finished, Started to Not Started, etc. Your tasks are as follows:&lt;BR&gt;&lt;BR&gt;
&lt;OL&gt;
&lt;LI&gt;Leverage the state design-pattern to simplify the change in states currently being handled by the method UpdateActivityStartAndFinishWith. Any state-related classes should be placed into the folder Challenge3.Domain.ActivityState. There are a few comments in the mentioned method...be sure to pay attention to them!&lt;/LI&gt;
&lt;LI&gt;While implementing the state design pattern, existing unit tests should be maintained and new unit tests should be written for any new code. You shouldn't have to remove any unit tests from Challenge3.Tests.Core.Domain.ProjectProjectActivityStateChangeTests; but you may want to add a new suite of unit tests for the state classes which will be created. Currently 97% of Challenge3.Core.Domain is being unit tested. Your submitted solution must have at least 95% of Challenge3.Core.Domain still under unit tests. You can use a tool such as &lt;A href="http://ncover.org/site/"&gt;NCover&lt;/A&gt; or &lt;A href="http://cenqua.com/clover.net/"&gt;Clover.NET&lt;/A&gt; to verify unit test coverage. (Don't worry about unit testing the Utils namespace; consider this to be a third party DLL.)&lt;/LI&gt;&lt;/OL&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Good luck and let me know if you have any questions. And remember, the first submitter with a correct entry gets his/her name thrown into the hat twice!&lt;/P&gt;
&lt;P&gt;Happy holidays!&lt;BR&gt;&lt;BR&gt;Billy&lt;/P&gt;
&lt;P&gt;12/19/06 9:32 AM Mtn Time - Updated project to use US culture dates within unit tests.&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=1923" width="1" height="1"&gt;</description><enclosure url="http://devlicio.us" length="129116" type="application/x-zip-compressed" /><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/.NET/default.aspx">.NET</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/Refactoring/default.aspx">Refactoring</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/Contests/default.aspx">Contests</category></item><item><title>Refactor It! Challenge 2 Results</title><link>http://devlicio.us/blogs/billy_mccafferty/archive/2006/11/30/refactor-it-challenge-2-results.aspx</link><pubDate>Fri, 01 Dec 2006 01:07:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:970</guid><dc:creator>Billy McCafferty</dc:creator><slash:comments>4</slash:comments><description>Congratulations to Michaël Willemot who is the winner of &lt;A href="http://devlicio.us/blogs/billy_mccafferty/archive/2006/11/23/refactor-it-challenge-2.aspx"&gt;Challenge 2&lt;/A&gt;! Michaël has won a copy of &lt;A href="http://www.awprofessional.com/bookstore/product.asp?isbn=0321268202&amp;amp;rl=1"&gt;Applying Domain-Driven Design and Patterns: With Examples in C# and .NET&lt;/A&gt; by Jimmy Nilsson along with a 3-user license pack for &lt;A href="http://submain.com/?nav=products.cio"&gt;CodeIt.Once Refactoring&lt;/A&gt;. (The winner was randomly selected from all correct entries received.) Geert Baeyaert had the first correct submission and, incidentally, the first correct bonus entry as well.&lt;BR&gt;&lt;BR&gt;There were 19 entries altogether with 17 correct entries. 11 entries attempted the bonus but only 5 entries correctly completed the bonus with a mock logger. Here's a run down of the correct entrants: Adam Vandenberg (bonus as well), Andrzej Kuczynski, Avi A, Bill Arnette, Brian Sherwin, Franck Tetard, Geert Baeyaert (first entry and bonus as well), Harry Chou (bonus as well), John Penokie, Jonathan Roe, Joshua McKinney (bonus as well), Matt Payne, Michael Willemot, Navneet Gupta, Rasmus Faber-Espensen, Rune Rystad (last week's winner, so not eligible for prize, but got bonus as well), Vitaly Davidovich. Nice work all!&lt;BR&gt;&lt;BR&gt;&lt;B&gt;Interesting Finds&lt;/B&gt;&lt;BR&gt;&lt;BR&gt;Below are a few items of particular interest that were found in the submissions: 
&lt;UL&gt;
&lt;LI&gt;A few entrants included an abstract "join spec" that acted as the parent for the AndSpec, NotSpec and OrSpec. This helped centralize functionality and reduce duplicated code. Furthermore, a couple of entrants also made the spec pattern completely generic so its structure could be easily reused with different domain objects. Great call on both approaches.&lt;/LI&gt;
&lt;LI&gt;I forgot to mention, and I'm glad I did, to remove the two unit tests that were affected when you removed the methods FindByNotTypeAndAtLeastTotalCost and FindAtLeastQuantityOrAtLeastTotalCost. Quite a few people wondered whether they should be left alone, modified, or deleted. I'm glad it brought up this unintended conversation. Unit tests should be seen as a dynamic, living part of the code and are subject to the same level of refactoring as the "real" code. If a unit test is no longer pulling its weight or is no longer applicable, get rid of it. As Brian Sherwin noted, a great book to take a look at is &lt;A href="http://www.awprofessional.com/bookstore/product.asp?isbn=0321146530&amp;amp;rl=1"&gt;Test-Driven Development&lt;/A&gt; by Kent Beck. This book demonstrates just how dynamic unit test development really is. With full-throttle TDD, the unit tests morph as much, if not more, as the production code itself.&lt;/LI&gt;
&lt;LI&gt;The log4net bonus tripped up entrants mainly due to two reasons: 1) two separate logs needed to be generated, as was working in the original code, not just one, and 2) the singleton methods were tricky to mock. One solution to the first trip-point was to pass two loggers, one for the owner's log and one for the auditor's log to the nightly log process. The drawback to this approach is the maintenance headache with having to later on pass a third, forth, or nth logger to the class or to another class altogether. Alternatively, another approach is to supply a simplified &lt;A href="http://java.sun.com/blueprints/corej2eepatterns/Patterns/ServiceLocator.html"&gt;Service Locator&lt;/A&gt;. This "logger locator" could be easily passed to anything and extended easily. I've attached a zip file, ExampleSolutions.zip, which contains four entries which used this type of approach (and contain a few variants of the spec pattern as well). The second trip-point was dealing with mocking the call to a method on a singleton. You can make a wrapper for the object, or, if you're in a real pickle, you can use a tool such as &lt;A href="http://www.typemock.com/"&gt;TypeMock&lt;/A&gt; which can mock just about anything, even sealed classes. The drawback to using a tool such as this is that it makes it easier to write more tightly coupled code. As mentioned in a previous post, Michael Feather's &lt;A href="http://www.phptr.com/bookstore/product.asp?isbn=0131177052&amp;amp;rl=1"&gt;Working Effectively with Legacy Code&lt;/A&gt; has a number of great ideas for dealing with these types of situations without resorting to such a powerful tool. (You saw what the ring of power did to Frodo, didn't you?)&lt;/LI&gt;
&lt;LI&gt;Someone brought up the question of what to do if you find yourself writing duplicated spec-creation code in different areas of the code. One solution is to create concrete "combination spec" classes for each of these variants. The problem with this is that it leads to the same type of combinatorial class explosion that we were running into before. Alternatively, for the duplicated spec combinations, you could create a CombinationSpecFactory class. This would have one or more creation methods that would return a Spec class; one method for each unique combination which is duplicated in more than one place. You might ask, what's better about having a factory with combination-spec-creation methods vs. having a number of concrete-combination spec classes? My preference of a factory over individual classes would be to keep the Spec class package clean; I want to keep my Spec class names to be as atomic as possible. I'd love to hear other thoughts on this issue!&lt;/LI&gt;&lt;/UL&gt;Instead of describing the smell refactorings in detail, I'll let the code speak for itself. I've attached ExampleSolutions.zip below which contains four projects that have the bonus challenge included along with well-written log4net wrappers.&amp;nbsp; Your comments are most welcome as to pros and cons of each approach.&lt;BR&gt;&lt;BR&gt;I hope these refactoring challenges continue to be useful, offering plenty of food for thought. Stay tuned to the next challenge which will be rearing its ugly head sometime next week!&lt;BR&gt;&lt;BR&gt;Billy&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=970" width="1" height="1"&gt;</description><enclosure url="http://devlicio.us" length="587238" type="application/x-zip-compressed" /><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/Refactoring/default.aspx">Refactoring</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/Contests/default.aspx">Contests</category></item><item><title>Refactor It! Challenge 2</title><link>http://devlicio.us/blogs/billy_mccafferty/archive/2006/11/23/refactor-it-challenge-2.aspx</link><pubDate>Thu, 23 Nov 2006 08:46:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:746</guid><dc:creator>Billy McCafferty</dc:creator><slash:comments>4</slash:comments><description>If you're not familiar with&amp;nbsp;the Refactor It! challenges, please &lt;A href="http://devlicio.us/blogs/billy_mccafferty/archive/2006/11/13/refactor-it-the-weekly-book-giveaway.aspx"&gt;read this post&lt;/A&gt;. (Yes, this one is a little late in being published...but it's worth it!) Now on to challenge 2...&lt;BR&gt;&lt;BR&gt;Welcome back to another refactoring challenge! I'm excited about this week's challenge and am sure it'll be interesting and challenging for all skill levels. It should take about 2 hours for senior developers and a couple more for intermediate developers. While last week's challenge served as a good introduction to refactoring in general, this week's challenge focuses on design pattern refactorings. Here's the premise...&lt;BR&gt;&lt;BR&gt;&lt;B&gt;Background &amp;amp; Problem&lt;/B&gt;&lt;BR&gt;&lt;BR&gt;This application continues from the theme started in last week's challenge and includes a logging system for the local tiki bar. Each day, very early in the morning, a logging process kicks off which creates two logs summarizing orders placed on the previous day. An order has a customer, a date, a specific tiki drink, and a quantity of that drink. If the customer wants different types of tiki drinks, they need to place an order for each type. It's not your tiki bar, so that's just the way it is! The first log created each night is for the bar owner and includes all orders which had a total cost of at least $20 &lt;I&gt;or&lt;/I&gt; had a quantity of at least 5. The second log is for the auditor and includes all tiki drink orders which had a total cost of at least $10 &lt;I&gt;and&lt;/I&gt; were not for the drink called the "London Fog Cutter." (Don't ask me why the auditor doesn't want to know about these drinks...I just work here!)&lt;BR&gt;&lt;BR&gt;The problem, in a nutshell, is two-fold. The first problem is that the filtering mechanism for figuring out which orders should be logged is getting quite complicated. The &lt;A href="http://www.martinfowler.com/apsupp/spec.pdf"&gt;specification design pattern&lt;/A&gt;, a specialized version of the &lt;A href="http://www.dofactory.com/Patterns/PatternInterpreter.aspx"&gt;interpreter design pattern&lt;/A&gt;, needs to be employed to make the filtering easier to maintain. The second problem is that a bi-directional dependency exists between the data layer and the business logic layer. Consequently, it's very difficult to unit test the business logic layer without actually hitting the database. We'll need to introduce a &lt;A href="http://www.martinfowler.com/eaaCatalog/separatedInterface.html"&gt;separated interface&lt;/A&gt;, also known as the &lt;A href="http://www.objectmentor.com/resources/articles/dip.pdf"&gt;dependency inversion principle&lt;/A&gt;, to decouple the business logic layer from the data access layer. We'll then need to use a &lt;A href="http://www-128.ibm.com/developerworks/library/j-mocktest.html"&gt;mock object&lt;/A&gt; so that we can predictably test the business logic layer without needing to worry about having a database around. (Tools exist to automate mock object creation, but let's we'll use one developed by hand.)&lt;BR&gt;&lt;BR&gt;&lt;B&gt;Your Incentive&lt;/B&gt;&lt;BR&gt;&lt;BR&gt;Up for grabs this week is the following book along with a &lt;A class="" href="http://submain.com/?nav=products.cio" target=_blank&gt;CodeIt.Once Refactoring&lt;/A&gt; tool 3-User license pack! This is a great book and will be a well-earned prize.&lt;BR&gt;
&lt;P&gt;&lt;IMG alt="Applying Domain-Driven Design and Patterns: With Examples in C# and .NET" src="http://www.awprofessional.com/ShowCover.asp?isbn=0321268202&amp;amp;type=c" width=125&gt; &lt;/P&gt;
&lt;DIV id=cover&gt;
&lt;P&gt;&lt;A href="http://www.awprofessional.com/bookstore/product.asp?isbn=0321268202&amp;amp;rl=1"&gt;Applying Domain-Driven Design and Patterns: With Examples in C# and .NET&lt;/A&gt;&lt;BR&gt;By Jimmy Nilsson.&lt;/P&gt;&lt;B&gt;Instructions to Enter&lt;/B&gt;&lt;BR&gt;&lt;BR&gt;Make sure you read all the instructions as they're different from last week's challenge! 
&lt;OL&gt;
&lt;LI&gt;Make sure you have NUnit installed; available at &lt;A href="http://www.nunit.org/" target=_blank&gt;http://www.nunit.org/&lt;/A&gt;.&lt;/LI&gt;
&lt;LI&gt;Download Challenge2.zip found below.&lt;/LI&gt;
&lt;LI&gt;Open the solution with VS 2005 and compile it.&lt;/LI&gt;
&lt;LI&gt;Open NUnit, go to File/Open, then open &amp;lt;solution directory&amp;gt;/Challenge2.Tests/bin/Debug/Challenge2.Tests.dll. Click run and make sure all the tests pass. There should be a few unit tests that are ignored; but none should be failing.&lt;/LI&gt;
&lt;LI&gt;After running the tests, confirm that two log were generated in &amp;lt;solution directory&amp;gt;/Challenge2.Tests/bin/Debug/. The log files are named Auditor.log and Owner.log and contain a number of order summaries pulled from the "database."&lt;/LI&gt;
&lt;LI&gt;Complete the refactorings as described below. Be sure to follow the style of the code that is already in place: classes, methods and public properties in PascalCase, private members in camelCase, etc. Following the style that's already there is always a good rule of thumb when modifying legacy code.&lt;/LI&gt;
&lt;LI&gt;When finished with the refactorings, make sure all the unit tests are still passing and that no test is being ignored, zip up your solution and send to &lt;A href="mailto:challenge2@emccafferty.com"&gt;challenge2@emccafferty.com&lt;/A&gt;. As you may only win once, only submit a solution if you'd like to be eligible for the prize or let me know that you don't want to be entered for the drawing.&lt;BR&gt;Because of the lateness of this post and this week's holiday, the due date for your submission is &lt;SPAN style="FONT-WEIGHT:bold;COLOR:red;"&gt;Wednesday night at midnight, Nov. 29, US mountain time&lt;/SPAN&gt;. It's not an easy one, so I wouldn't wait until Wednesday to get started!&lt;/LI&gt;&lt;/OL&gt;&lt;B&gt;Challenge 2 Download Overview&lt;/B&gt;&lt;BR&gt;&lt;BR&gt;The VS 2005 solution contains two projects (at the moment): 
&lt;UL&gt;
&lt;LI&gt;Challenge2.Core: This class library contains the data access and business logic layers of the application. This class library is further broken down as follows: 
&lt;UL&gt;
&lt;LI&gt;The Data folder contains all the data-access code. The only class within this folder, OrderDao, simulates talking to a real database by generating zero or more sample orders. The unpredictability of the results serves to simulate a real-life database.&lt;/LI&gt;
&lt;LI&gt;The Domain folder contains all the entities and value objects. It also contains a sub-folder, OrderFinder, albeit still in the same namespace, which holds the order-filtering logic.&lt;/LI&gt;
&lt;LI&gt;The Services folder contains the nightly logger process.&lt;/LI&gt;
&lt;LI&gt;The Utils folder contains a design-by-contract &lt;A href="http://www.codeproject.com/csharp/designbycontract.asp"&gt;utility class written by Kevin McFarlane&lt;/A&gt;. The utility class is for all the Check.Requires you'll see throughout the code.&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;
&lt;LI&gt;Challenge2.Core: This class library contains the unit tests of the application. As there is no defined presentation layer, the unit tests serve as a portal to how the application works.&lt;/LI&gt;
&lt;LI&gt;Challenge2.Data: This isn't in the download, but you'll be adding this class library soon enough.&lt;/LI&gt;&lt;/UL&gt;&lt;B&gt;Now Refactor It!&lt;/B&gt;&lt;BR&gt;&lt;BR&gt;Below is a listing of smells that need to be fixed within the project. Each point indicates the file that contains the smell, a description of the problem and any guidelines for completing the refactoring. There may be other smells in the code, but these are the only ones that should be addressed.&lt;BR&gt;&lt;BR&gt;&lt;I&gt;Smell: Combinatorial Explosion&lt;/I&gt;&lt;BR&gt;&lt;I&gt;Refactoring: &lt;A href="http://industriallogic.com/xp/refactoring/implicitLanguageWithInterpreter.html"&gt;Replace Implicit Language with Interpreter&lt;/A&gt;&lt;/I&gt;&lt;BR&gt;&lt;BR&gt;I have yet to write an application that doesn't include a bit of filtering capabilities. Furthermore, it's often the case that the filtering capabilities need to be extended throughout the life of the application. If only a couple of filters are required, then hard-coding the filter logic isn't that big of a deal. But if the number of filters grow or the logic becomes more complicated than just "AND"s, then using the &lt;A href="http://www.dofactory.com/Patterns/PatternInterpreter.aspx"&gt;interpreter design pattern&lt;/A&gt; may be an appropriate fit. But there's also the question as to whether filtering should be done by the database or by the code. As I prefer to keep database logic to the simplest CRUD (create/read/update/delete) functionality, I avoid putting complicated filtering logic into the database unless performance warrants otherwise. A good rule of thumb is that if you have a couple hundred items or less to filter, and you have more than a few filters that change regularly, then putting the filtering into the business logic layer is a good way to go; otherwise, the database should be doing the basic filtering. Alternatively, ORMs such as NHibernate provide their own implementation of the &lt;A href="http://www.dofactory.com/Patterns/PatternInterpreter.aspx"&gt;interpreter design pattern&lt;/A&gt;. So onto the smell... 
&lt;UL&gt;
&lt;LI&gt;&lt;I&gt;Challenge2.Core.OrderFinder&lt;/I&gt;: This order-filtering class exposes the verbosely named methods FindByNotTypeAndAtLeastTotalCost and FindAtLeastQuantityOrAtLeastTotalCost. Besides taking a while to read, these methods are difficult to extend, likely to change and are far from flexible. Without removing these methods (yet), refactor to the &lt;A href="http://www.martinfowler.com/apsupp/spec.pdf"&gt;specification design pattern&lt;/A&gt; to make the filtering capabilities much more flexible. To assist, uncomment the unit tests within Challenge2.Tests.Core.Domain.OrderFinderTests one at a time, following the order suggested. Get each unit test working by implementing the implied code. Put all your "Spec" classes into the folder Challenge2.Core.Domain.OrderFinder but keep the namespace of those classes to be Challenge2.Core.Domain.&lt;/LI&gt;
&lt;LI&gt;&lt;I&gt;Challenge2.Core.Services.NightlyOrderLogger&lt;/I&gt;: This class creates writes two logs, one for the tiki bar owner and one for the auditor. To get the appropriate orders to log, it makes a call to the database to get all of yesterday's orders, and then leverages the OrderFinder class to filter, accordingly. Refactor this class to use the specification classes that you just created and delete the methods FindByNotTypeAndAtLeastTotalCost and FindAtLeastQuantityOrAtLeastTotalCost from Challenge2.Core.OrderFinder.&lt;/LI&gt;&lt;/UL&gt;&lt;I&gt;Smell: Dependency on Concrete Service&lt;/I&gt;&lt;BR&gt;&lt;I&gt;Refactorings: &lt;A href="http://www.refactoring.com/catalog/extractInterface.html"&gt;Extract Interface&lt;/A&gt; and Introduce &lt;A href="http://www.martinfowler.com/eaaCatalog/separatedInterface.html"&gt;Separated Interface&lt;/A&gt;&lt;/I&gt;&lt;BR&gt;&lt;BR&gt;If you're wondering why you've never heard of the smell listed above, you probably won't be alone. (And if I ever write a book, I'll be sure to change that!) One of the most frequent issues I find with legacy code is direct dependencies on concrete classes that provide a service. A service, in this case, may be a data-access object which communicates with a database, an emailing utility class, an external web service, etc. A service is usually resource intensive, time consuming, or something that shouldn't be executed outside of a production environment. Having dependencies on concrete service classes does not present a problem if the code won't ever be unit tested, but neither will standing in the middle of a highway as long as there's no traffic...but I digress.&lt;BR&gt;&lt;BR&gt;A solution for removing a dependency on a concrete service is to introduce, instead, a dependency on an interface. (I'll discuss more of the benefits of this in a moment.) But if the service class is still within the same physical assembly as the business logic layer, then there's nothing to stop a developer from bypassing the interface and going back to the concrete service class directly. To enforce a policy of services via interfaces, a &lt;A href="http://www.martinfowler.com/eaaCatalog/separatedInterface.html"&gt;separated interface&lt;/A&gt; may be introduced. 
&lt;UL&gt;
&lt;LI&gt;&lt;I&gt;Challenge2.Core.Services.NightlyOrderLogger&lt;/I&gt;: Notice that this class creates a new instance of OrderDao to retrieve relevant orders from the database. This presents two problems. The first is that the process is time consuming from a unit test point of view. If you have a couple hundred unit tests and many of them require communications with a database, the unit testing process can begin to take 10 minutes or more. Once this happens, developers stop running unit tests altogether. (I experienced this on a previous project.) Furthermore, unit tests expect predictable results to verify code is working properly. Unless a database is reinitialized at the beginning of each test run, the results may vary and the tests will begin to break. This is another motivating factor for developers to stop running unit tests. (This was another unpleasant experience from a previous project.) One action you can take to mitigate this is to label any test that depends on a database with a "Database Test" categorization. With this in place, it's easy to "ignore" these tests within NUnit. But how can we test the business logic if we're ignoring much of it?&lt;BR&gt;&lt;BR&gt;You can alleviate these problems by leveraging a mock object that &lt;I&gt;simulates&lt;/I&gt; the service in an efficient and predictable manner. Take a look at Challenge2.Tests.MockObjects.Data.MockOrderDao. This class simulates the behavior of the real OrderDao class but returns the exact same results each time. Consequently, it's possible to use this mock object in place of OrderDao to verify that the business logic is working properly. Using mock objects in place of production data-access objects, you won't need to reinitialize the database on each test run. Carry out the following steps to introduce a &lt;A href="http://www.martinfowler.com/eaaCatalog/separatedInterface.html"&gt;Separated Interface&lt;/A&gt; and inject mock objects into your business logic layer for testing purposes.&lt;BR&gt;&lt;BR&gt;
&lt;OL&gt;
&lt;LI&gt;Use the refactoring technique &lt;A href="http://www.refactoring.com/catalog/extractInterface.html"&gt;Extract Interface&lt;/A&gt; on the class OrderDao to create an interface called IOrderDao. Put the extracted interface into Challenges2.Core.DataInterfaces and have OrderDao implement it. (The interface should have just one method called GetOrderPlacedOn.)&lt;/LI&gt;
&lt;LI&gt;Compile and run the unit tests to make sure everything is still working.&lt;/LI&gt;
&lt;LI&gt;A mock object already exists, to simulate this data-access object, found at Challenge2.Tests.MockObjects.Data.MockOrderDao. Have this class also implement the IOrderDao interface.&lt;/LI&gt;
&lt;LI&gt;Within Challenge2.Tests.Core.Services.NightlyOrderLoggerTests, there's a method called CanExecuteNightlyOrderLogger. Within this method, create an instance of MockOrderDao and pass it as a parameter to the method ExecuteNightlyLogging. You'll get a compilation error at this point. This is OK as we want the unit test to drive our code changes.&lt;/LI&gt;
&lt;LI&gt;Add the following two unit test assertion to the same CanExecuteNightlyOrderLogger method: (You'll still be getting compilation errors from the previous step.)&lt;BR&gt;&lt;PRE&gt;Assert.AreEqual(3, summary.AuditorsLogEntryCount);
Assert.AreEqual(4, summary.OwnersLogEntryCount);&lt;/PRE&gt;&lt;/LI&gt;
&lt;LI&gt;Modify the ExecuteNightlyLogging method of Challenge2.Core.Services.NightlyOrderLogger to accept an IOrderDao object. Be sure to use Check.Require to make sure it's not null. The name of the parameter should simply be orderDao. This will conflict with the new instantiation of OrderDao a few lines down. That's expected. Delete the line &lt;CODE&gt;OrderDao orderDao = new OrderDao();&lt;/CODE&gt;. The NightlyOrderLogger is no longer dependent on a concrete service class; e.g. OrderDao. Instead, it only depends on the IOrderDao interface. But developers are still free to use OrderDao directly if they so wish. Now we'll introduce the &lt;A href="http://www.martinfowler.com/eaaCatalog/separatedInterface.html"&gt;separated interface&lt;/A&gt;.&lt;/LI&gt;
&lt;LI&gt;Before proceeding, make sure everything compiles and the unit tests are passing.&lt;/LI&gt;
&lt;LI&gt;Add a new project to the solution called Challenge2.Data. This project will contain classes which communicate with the database.&lt;/LI&gt;
&lt;LI&gt;Move Challenge2.Core.Data.OrderDao to this new project and delete the Data folder from Chanllenge2.Core. (You'll need to add a reference to Challenge2.core from the Challenge2.Data project. While you're add it, also add a reference to Challenge2.Data from the Challenge2.Tests project.)&lt;/LI&gt;
&lt;LI&gt;Finally, repair the namespace reference problems found within Challenge2.Core and Challenge2.Data, compile and confirm that all the unit tests are still passing.&lt;/LI&gt;&lt;/OL&gt;&lt;BR&gt;As an optional, bonus step (and to get your name thrown into the hat twice), pass a mock log4net logger to NightlyOorderLogger in addition to the mocked OrderDao so that log files aren't necessarily generated during unit testing. &lt;/LI&gt;&lt;/UL&gt;So what did we just accomplish? There are a few benefits to what we just did: 1) the unit tests are blazing fast as they don't depend on database communications, 2) the data-access and business logic layers are now loosely coupled, 3) the data-access layer can be easily mocked or even, albeit not likely, replaced with a completely different database communications layer, and 4) developers can no longer introduce new, bi-directional dependencies between the data-access and business logic layers. The last point goes a long way to keeping an application clean, testable and maintainable.&lt;BR&gt;&lt;BR&gt;This refactoring challenge is &lt;I&gt;quite&lt;/I&gt; a few steps beyond the simple, introductory refactorings we saw last week. But I hope I've illustrated that refactoring techniques can not only make a method cleaner, they can also provide direction for refactoring application architecture as a whole.&lt;BR&gt;&lt;BR&gt;Good luck on the challenge and let me know if you have any questions!&lt;BR&gt;&lt;BR&gt;Billy&lt;/DIV&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=746" width="1" height="1"&gt;</description><enclosure url="http://devlicio.us" length="142027" type="application/x-zip-compressed" /><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/Architecture/default.aspx">Architecture</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/.NET/default.aspx">.NET</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/Refactoring/default.aspx">Refactoring</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/Contests/default.aspx">Contests</category></item><item><title>Refactor It! Challenge 1 Results</title><link>http://devlicio.us/blogs/billy_mccafferty/archive/2006/11/20/refactor-it-challenge-1-results.aspx</link><pubDate>Mon, 20 Nov 2006 23:13:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:703</guid><dc:creator>Billy McCafferty</dc:creator><slash:comments>5</slash:comments><description>Congratulations to Rune Rystad who is the winner of &lt;A href="http://devlicio.us/blogs/billy_mccafferty/archive/2006/11/14/refactor-it-challenge-1.aspx"&gt;Challenge 1&lt;/A&gt;! Rune has won a copy of &lt;A href="http://www.awprofessional.com/bookstore/product.asp?isbn=0321246756&amp;amp;rl=1"&gt;Framework Design Guidelines&lt;/A&gt; by Krzysztof Cwalina and Brad Abrams along with a 3-user license pack for &lt;A href="http://submain.com/?nav=products.cio"&gt;CodeIt.Once Refactoring&lt;/A&gt;. (The winner was randomly selected from all correct entries received.) For the record, Jeff Perrin had the first correct submission...so he got his name thrown into the hat twice and gets a nice pat on the back. ;)&lt;BR&gt;&lt;BR&gt;Wow, what a response! There were 21 correct entries out of a total of 25 submissions received before the Sunday night deadline. Due to the number of entrants, if I haven't responded with feedback, you can assume your submission was correct. I was glad to see that people enjoyed working through the challenge and hope you all got something out of it.&lt;BR&gt;&lt;BR&gt;Before digging into the results and the solution itself, I wanted to bring up a couple of notes about refactoring and the challenge itself. There's an important aspect of refactoring that the challenge doesn't illustrate very well: a tenant of refactoring is keeping the code in a working state as much as possible and to only have one unit test failing at a time. Consequently, refactoring should be seen as a process, and not just a before and after state. I'll give an example of this when discussing the example solution. On another note, a couple of entrants brought up the point that there were other smells in the code not mentioned in the challenge description...heck yeah there were! If you've worked with legacy code, and we all have, you'll see smells all over the place. At times, the smells are so bad that it's difficult to make any forward progress with refactoring without feeling that you have to gut the whole thing. In times like these, Michael Feather's &lt;A href="http://www.phptr.com/bookstore/product.asp?isbn=0131177052&amp;amp;rl=1"&gt;Working Effectively with Legacy Code&lt;/A&gt; can be a great resource. These comments have inspired me to include one such example in the the next challenge.&lt;BR&gt;&lt;BR&gt;&lt;B&gt;Interesting Finds&lt;/B&gt;&lt;BR&gt;&lt;BR&gt;Below are a few items of particular interest that were found in the submissions: 
&lt;UL&gt;
&lt;LI&gt;Some created a new class called &lt;CODE&gt;EmailAddress&lt;/CODE&gt; to handle checking the validity of an email address. Although not required for this particular challenge, doing so consolidates the business logic, makes it more reusable and treats an email address as a first class citizen; and it&amp;nbsp;usually should be.&lt;/LI&gt;
&lt;LI&gt;To fix the "magic number" smell in the Customers class, Adam Vandenberg included a clever usage of iterators to get the list of all customers of drinking age:&lt;BR&gt;&lt;TEXTAREA class=c#:nogutter name=code rows=15 cols=50&gt;		/// &amp;lt;summary&amp;gt;
		/// Enumerate only &amp;lt;see cref="Customer"/&amp;gt;s who are of legal drinking age in the USA.
		/// &amp;lt;/summary&amp;gt;
		private IEnumerable&amp;lt;Customer&amp;gt; USADrinkingAgeCustomers {
			get {
				foreach (Customer customer in this)
					if (customer.CanDrinkInUSA)
						yield return customer;
			}
		}
&lt;/TEXTAREA&gt; &lt;/LI&gt;
&lt;LI&gt;Some created a configuration-settings, reader class that centralized the mining of the config file into a single class. This is an example of what Martin Fowler calls a &lt;A href="http://www.martinfowler.com/eaaCatalog/gateway.html"&gt;Gateway&lt;/A&gt;. I thought it was a great idea and have included it in the example solution. (Another good time to use a gateway is when working with data stored in Session.) The major benefit of using this approach is that if the config (or session) keys change, then you only need to change them in one spot outside of the config file.&lt;/LI&gt;&lt;/UL&gt;&lt;B&gt;Smell Refactorings&lt;/B&gt;&lt;BR&gt;&lt;BR&gt;Now let's take a look at &lt;I&gt;one&lt;/I&gt; possible solution to the refactorings. There are many different approaches to the challenge, and many of them are equally valid.&lt;BR&gt;&lt;BR&gt;&lt;I&gt;Smell: Comments&lt;/I&gt; 
&lt;UL&gt;
&lt;LI&gt;Challenge1.Core.Domain.Customer: There were two comments at the top of this class dictating business rules for "age" and "emailAddress." As mentioned before, some entries included an &lt;CODE&gt;EmailAddress&lt;/CODE&gt; class to encapsulate the logic for verifying the validity of an email address. This particular refactoring, unsurprisingly enough, is called &lt;A href="http://www.refactoring.com/catalog/moveMethod.html"&gt;Move Method&lt;/A&gt;. Detailing how this is done, without breaking existing code, you would take the following refactoring steps:&lt;BR&gt;&lt;BR&gt;
&lt;OL&gt;
&lt;LI&gt;Introduce a new method in the &lt;CODE&gt;Customer&lt;/CODE&gt; class called &lt;CODE&gt;IsEmailAddressValid&lt;/CODE&gt;. This method would accept an email address and return whether or not it's valid. This refactoring is called &lt;A href="http://www.refactoring.com/catalog/extractMethod.html"&gt;Extract Method&lt;/A&gt;. This method could then be used to enforce a valid email address in the constructor of &lt;CODE&gt;Customer&lt;/CODE&gt;. Now we can get rid of the comment concerning passing a valid email. But should the &lt;CODE&gt;Customer&lt;/CODE&gt; class really know how to check for the validity of an email address? We'll address this concern after we make sure we haven't broken anything.&lt;/LI&gt;
&lt;LI&gt;Run the unit tests to make sure everything still works as expected.&lt;/LI&gt;
&lt;LI&gt;Create a unit test class, called &lt;CODE&gt;EmailAddressTests&lt;/CODE&gt; for a yet, non-existent &lt;CODE&gt;EmailAddress&lt;/CODE&gt; class. (This class is in the solution as Challenge1.Tests.Core.Domain.EmailAddressTests.)&lt;/LI&gt;
&lt;LI&gt;Add a unit test called &lt;CODE&gt;CheckValidEmailAddress&lt;/CODE&gt; which creates an instance of an &lt;CODE&gt;EmailAddress&lt;/CODE&gt;, passing in a valid email address, as a string, to its constructor. In the unit test, assert that the &lt;CODE&gt;IsValid&lt;/CODE&gt; method of the object returns true for a valid email address. (You're correct if you're asking yourself, &lt;I&gt;what IsValid method?&lt;/I&gt; This is called &lt;A href="http://www.agiledata.org/essays/tdd.html"&gt;test driven development&lt;/A&gt;...we'll let the unit test tell us what code to write.&lt;/LI&gt;
&lt;LI&gt;Copy the code in &lt;CODE&gt;Customer.IsEmailAddressValid&lt;/CODE&gt; to a new method within &lt;CODE&gt;EmailAddress&lt;/CODE&gt; called &lt;CODE&gt;IsValid&lt;/CODE&gt;. Don't remove the duplicate code from &lt;CODE&gt;Customer&lt;/CODE&gt; yet...we want to fix the currently breaking unit test before moving on to anything else. (Incidentally, some entries checked for the email address, validity check in the constructor of &lt;CODE&gt;EmailAddress&lt;/CODE&gt; while others left it to other classes to ask &lt;CODE&gt;EmailAddress&lt;/CODE&gt; if it was valid. Either way may be correct depending on the business requirements and both approaches were considered correct for this challenge.)&lt;/LI&gt;
&lt;LI&gt;Compile and verify that the &lt;CODE&gt;CheckValidEmailAddress&lt;/CODE&gt; unit test is passing.&lt;/LI&gt;
&lt;LI&gt;Add another unit test called &lt;CODE&gt;CheckInvalidEmailAddress&lt;/CODE&gt;, passing in an invalid email address this time, and assert that &lt;CODE&gt;IsValid&lt;/CODE&gt; return false.&lt;/LI&gt;
&lt;LI&gt;Compile and verify that the &lt;CODE&gt;CheckInvalidEmailAddress&lt;/CODE&gt; unit test is passing.&lt;/LI&gt;
&lt;LI&gt;&lt;I&gt;Now&lt;/I&gt;, have &lt;CODE&gt;Customer&lt;/CODE&gt; talk to the &lt;CODE&gt;EmailAddress&lt;/CODE&gt; object directly to determine email address validity instead of the private method &lt;CODE&gt;IsEmailAddressValid&lt;/CODE&gt;.&lt;/LI&gt;
&lt;LI&gt;Compile and run the unit tests again to make sure everything still works.&lt;/LI&gt;
&lt;LI&gt;Delete the &lt;CODE&gt;IsEmailAddressValid&lt;/CODE&gt; method from the &lt;CODE&gt;Customer&lt;/CODE&gt; class and run the tests again.&lt;/LI&gt;&lt;/OL&gt;&lt;BR&gt;The preceding steps&amp;nbsp;included the refactorings &lt;A href="http://www.refactoring.com/catalog/introduceAssertion.html"&gt;Introduce Assertion&lt;/A&gt;, &lt;A href="http://www.refactoring.com/catalog/extractMethod.html"&gt;Extract Method&lt;/A&gt;, &lt;A href="http://www.refactoring.com/catalog/moveMethod.html"&gt;Move Method&lt;/A&gt;, and &lt;A href="http://www.refactoring.com/catalog/decomposeConditional.html"&gt;Decompose Conditional&lt;/A&gt;. No wonder it took so many steps! Although the details of additional refactoring will not be broken down to such detail, I wanted to show how a refactoring is carried out at a lower level. (And if I haven't promoted it enough already, I highly recommend reading Martin Fowler's &lt;A href="http://www.martinfowler.com/books.html#refactoring"&gt;Refactoring&lt;/A&gt; to see each of these refactorings examined in more depth.) The above seems quite tedious, but the entire cycle takes just a couple of minutes and gives you confidently, working code (aka - peace of mind).&lt;BR&gt;&lt;BR&gt;If you've looked at the solution code, you may have noticed calls to &lt;CODE&gt;Check.Require&lt;/CODE&gt; to implement the &lt;A href="http://www.refactoring.com/catalog/introduceAssertion.html"&gt;Introduce Assertion&lt;/A&gt; refactoring. This code calls a wonderful &lt;A href="http://www.codeproject.com/csharp/designbycontract.asp"&gt;design-by-contract class originally written by Kevin McFarlane&lt;/A&gt;. You can read more about it, and design-by-contract in general, &lt;A href="http://devlicio.us/blogs/billy_mccafferty/archive/2006/09/22/Design_2D00_by_2D00_Contract_3A00_-A-Practical-Introduction.aspx"&gt;in a previous post&lt;/A&gt;. Although it seems overkill and unnecessary, sprinkling &lt;CODE&gt;Check.Require&lt;/CODE&gt; all over your code will save you hours upon hours in the debugger. (Just give it a whirl for a couple of days and you'll be convinced.)&lt;/LI&gt;
&lt;LI&gt;Challenge1.Core.Services.EmailService: If I write anything about the comment-smell in this class, I'd create a "duplicated blog content" smell. I.e. see the details of the first point for all the nitty-gritty details.&lt;/LI&gt;&lt;/UL&gt;&lt;I&gt;Smell: Magic Numbers&lt;/I&gt; 
&lt;UL&gt;
&lt;LI&gt;Challenge1.Core.Services.EmailService: There was a hard-coded SMTP server name and email address in the code. The correct solution was to put these values in App.config so that they could easily be changed between development and production environments. Taking it a step further, the example solution includes a new class, Challenge1.Core.ConfigSettings, which provides centralized access to the config settings. A couple of entries suggested this approach.&lt;/LI&gt;
&lt;LI&gt;Challenge1.Core.Domain.Customers: This class also had a hard-coded email address; the previous point's fix also applies to this one. Additionally, this class had a hard-coded value of "21" to represent the legal drinking age in the United States. The refactoring &lt;A href="http://www.refactoring.com/catalog/replaceMagicNumberWithSymbolicConstant.html"&gt;Replace Magic Number with Symbolic Constant&lt;/A&gt; has been used in the example solution to give the number more meaning. I chose to put this magic number into a constant instead of the config file because it is highly unlikely, in spite of how much we tried before we were 21, that this age will change. But the constant's name serves to make the code more readable. Finally, this class had a couple of strings, representing the spam's subject and body, which never changed. Although not implicated before, I've also placed these strings into constants as well. In a real-world situation, these probably would be pulled from a database or flat-file...neither of which I want to get into now! If requirements dictated that either of these be changed in the future, that would be the time to refactor the code to a more maintainable solution.&lt;/LI&gt;&lt;/UL&gt;&lt;I&gt;Smell: Long Method and Complicated Conditionals&lt;/I&gt; 
&lt;UL&gt;
&lt;LI&gt;Challenge1.Core.Domain.Customers: The method &lt;CODE&gt;SendBeerSpamToCustomersOfDrinkingAge&lt;/CODE&gt; has been sliced and diced, using the refactorings &lt;A href="http://www.refactoring.com/catalog/extractMethod.html"&gt;Extract Method&lt;/A&gt;, &lt;A href="http://www.refactoring.com/catalog/decomposeConditional.html"&gt;Decompose Conditional&lt;/A&gt;, and &lt;A href="http://www.refactoring.com/catalog/replaceMagicNumberWithSymbolicConstant.html"&gt;Replace Magic Number with Symbolic Constant&lt;/A&gt; to make it, arguably, easier to understand. The method name &lt;CODE&gt;ConditionallyTrackAndSendSpamTo&lt;/CODE&gt; may seem long, but it fully describes that the method sends spam, conditionally, and tracks any emails that are sent. You should never shorten a method name with acronyms or leave out a responsibility from the name. If you follow this rule of thumb, then long method names may be a sign that a method is trying to do too much. Perhaps we should &lt;A href="http://www.refactoring.com/catalog/extractMethod.html"&gt;Extract Method&lt;/A&gt; again to enable us to make the method name shorter and more concise?&lt;BR&gt;&lt;BR&gt;In carrying out the refactoring &lt;A href="http://www.refactoring.com/catalog/decomposeConditional.html"&gt;Decompose Conditional&lt;/A&gt;, for this class, I introduced the method &lt;CODE&gt;IsHomebrewOrderPurchasedInPastSixMonths&lt;/CODE&gt; to the order class. Now &lt;I&gt;there's&lt;/I&gt; a method name! This is an example of a decomposed conditional taken to the extreme. It perfectly summarizes the conditional in a readable fashion; but it's easy to see that this could get out of hand if we need to add other methods such as &lt;CODE&gt;IsMoonshineOrderPurchasedInPastEightMonths&lt;/CODE&gt;. We could parameterize both the type and the timeframe, but what if we add another variable to the mix...er...mess? If that never happens, then this method may be adequate, but if that very probable situation &lt;I&gt;does&lt;/I&gt; occur, it may be time to refactor to the &lt;A href="http://www.dofactory.com/Patterns/PatternInterpreter.aspx"&gt;interpreter design pattern&lt;/A&gt;. But again, if there's never a need to expand the filtering capabilities for orders, then we needn't invest the time, nor added complexity, of introducing this design pattern. (Down pattern-itus, down! Good dog.)&lt;/LI&gt;&lt;/UL&gt;As I've mentioned, there are many, &lt;I&gt;many&lt;/I&gt; ways to refactor this solution and what I've described is just one of them...with that, I open the floodgates to constructive criticism! ;) To make a preemptive strike, there could be a few more unit tests and the &lt;CODE&gt;Customers&lt;/CODE&gt; class is taking on a few too many responsibilities; but since I've spent way too much time on this post already, I'll leave the remaining smells as food for thought!&lt;BR&gt;&lt;BR&gt;Stay tuned for tomorrow's challenge!&lt;BR&gt;&lt;BR&gt;Billy&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=703" width="1" height="1"&gt;</description><enclosure url="http://devlicio.us" length="35996" type="application/x-zip-compressed" /><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/.NET/default.aspx">.NET</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/Refactoring/default.aspx">Refactoring</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/Contests/default.aspx">Contests</category></item><item><title>Refactor It!  Challenge 1</title><link>http://devlicio.us/blogs/billy_mccafferty/archive/2006/11/14/refactor-it-challenge-1.aspx</link><pubDate>Tue, 14 Nov 2006 21:24:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:592</guid><dc:creator>Billy McCafferty</dc:creator><slash:comments>13</slash:comments><description>&lt;P&gt;For an overview of this contest, read this &lt;A href="http://devlicio.us/blogs/billy_mccafferty/archive/2006/11/13/refactor-it-the-weekly-book-giveaway.aspx"&gt;opening introduction&lt;/A&gt;. Now, onto this week's refactoring challenge...&lt;BR&gt;&lt;BR&gt;As Fowler's subtitle describes, refactoring is about "improving the design of existing code"; an introduction to the subject can be found at &lt;A href="http://www.refactoring.com/" target=_blank&gt;refactoring.com&lt;/A&gt;. This first challenge includes a number of very common smells and straight-forward refactorings to remove those smells. For those of you who are new to refactoring, this particular challenge provides the perfect starting place. For those of who are refactoring guru's, I've got your can of worms coming soon!&lt;/P&gt;
&lt;P&gt;&lt;B&gt;Instructions to Enter&lt;/B&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Make sure you have NUnit installed; available at &lt;A href="http://www.nunit.org/" target=_blank&gt;http://www.nunit.org&lt;/A&gt;.&lt;/LI&gt;
&lt;LI&gt;Download Challenge1.zip found below.&lt;/LI&gt;
&lt;LI&gt;Open the solution with VS 2005 and compile it.&lt;/LI&gt;
&lt;LI&gt;Open NUnit, go to File/Open, then open &amp;lt;solution directory&amp;gt;/Challenge1.Tests/bin/Debug/Challenge1.Tests.dll. Click run and make sure all the tests pass.&lt;/LI&gt;
&lt;LI&gt;Complete the refactorings as described below. Be sure to follow the style of the code that is already in place: classes, methods and public properties in PascalCase, private members in camelCase, etc. Following the style that's already there is always a good rule of thumb when modifying legacy code.&lt;/LI&gt;
&lt;LI&gt;When finished, make sure all the unit tests are still passing after you've completed the refactorings, zip up your solution and send to &lt;A href="mailto:challenge1@emccafferty.com"&gt;challenge1@emccafferty.com&lt;/A&gt;. As you may only win once, only submit a solution if you'd like to be eligible for the prize.&lt;/LI&gt;&lt;/OL&gt;Up for grabs this week is the following book along with a &lt;A class="" href="http://submain.com/?nav=products.cio" target=_blank&gt;CodeIt.Once Refactoring&lt;/A&gt; tool 3-User license pack!&lt;BR&gt;&lt;BR&gt;
&lt;DIV id=cover&gt;&lt;IMG alt="Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries" src="http://www.awprofessional.com/ShowCover.asp?isbn=0321246756&amp;amp;type=c" width=125&gt; 
&lt;P&gt;&lt;A href="http://www.awprofessional.com/bookstore/product.asp?isbn=0321246756&amp;amp;rl=1"&gt;Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries&lt;BR&gt;&lt;/A&gt;By Krzysztof Cwalina, Brad Abrams.&lt;/P&gt;
&lt;P&gt;&lt;B&gt;Now Refactor It!&lt;/B&gt;&lt;BR&gt;&lt;BR&gt;Below is a listing of smells that need to be fixed within the project. Each point indicates the file that contains the smell, a description of the problem and any guidelines for completing the refactoring.&amp;nbsp; You may find quite a few other smells in the code as well, but only focus on the ones listed here.&lt;BR&gt;&lt;BR&gt;&lt;I&gt;Smell: Comments&lt;/I&gt;&lt;BR&gt;&lt;BR&gt;Not all comments are bad. But many comments are an indication that something is too complex, that a business rule isn't being enforced, or that a method or class is doing too much in one place. Comments should describe &lt;I&gt;why&lt;/I&gt; something is done and not necessarily &lt;I&gt;what&lt;/I&gt; something does unless it's complex and there's no simpler way to do it. Another drawback to comments is that they need to be maintained along with the code. Instead, focus should be put toward making the code speak for itself; this gets rid of the comments and makes it more maintainable. The following are some comment smells found within the code that need to be fixed:&lt;/P&gt;&lt;/DIV&gt;
&lt;UL&gt;
&lt;LI&gt;Challenge1.Core.Domain.Customer: There are two comments concerning the allowable parameters. These comments don't seem to be enforcing much. Enforce these comments and get rid of them to make the code speak for itself. Don't worry about checking to see if the email address is valid. For a hint in the right direction, take a look at the constructor of Challenge1.Core.Domain.Order. (Guideline: Include the refactorings "Extract Method" and "Introduce Assertion.")&lt;/LI&gt;
&lt;LI&gt;Challenge1.Core.Services.EmailService: There's a comment on line 10. How can we get rid of this comment and make the "if" statement which follows a little more understandable? (Guideline: Include the refactorings "Extract Method," "Decompose Conditional" and "Introduce Assertion.")&lt;/LI&gt;&lt;/UL&gt;&lt;I&gt;Smell: Magic Numbers&lt;/I&gt;&lt;BR&gt;&lt;BR&gt;A magic number is a constant which appears in the code itself.&amp;nbsp; There are&amp;nbsp;a few&amp;nbsp;examples of magic numbers in the&amp;nbsp;code that need to be fixed:&lt;BR&gt;
&lt;UL&gt;
&lt;LI&gt;Challenge1.Core.Services.EmailService: There's a hard-coded email address and a hard-coded SMTP server within the method SendEmailTo. &amp;nbsp;(Although not a number, this would still be classified as the Magic Number smell.)&amp;nbsp; If the email address changes or the SMTP server changes, you'll have to make a modification and recompile the entire project. How should this be fixed to make it&amp;nbsp;easier to change these items and to deploy it to various servers?&lt;/LI&gt;
&lt;LI&gt;Challenge1.Core.Domain.Customers: The same type of problem is found at the bottom of the method SendBeerSpamToCustomersOfDrinkingAge. Doh...who programmed this piece of ...!&lt;/LI&gt;
&lt;LI&gt;Challenge1.Core.Domain.Customers: This class contains the magic number "21." How should it be fixed? Is it appropriate to fix it in the same way as the EmailService fix, or do we really need to worry about changes to this number very often? Regardless, this is a magic number which isn't very explicit.&lt;/LI&gt;&lt;/UL&gt;&lt;I&gt;Smell: Long Method and Complicated Conditionals&lt;/I&gt;&lt;BR&gt;&lt;BR&gt;A long method is any method that has more than one responsibility or is too long to understand easily. As a rule of thumb, I try to make sure no method has more than about ten functional lines of code. In practice, I usually find that most of my methods are between three and ten lines long. (As a side note... Taking this to the extreme, is it incorrect to have a method with just one line of code? Not if it helps make your code more explicit and understandable.) In addition to improving readability, short methods make it much easier to spot duplicated code. For the challenge at hand, fix the following smell:&lt;BR&gt;
&lt;UL&gt;
&lt;LI&gt;Challenge1.Core.Domain.Customers: The method SendBeerSpamToAppropriateCustomers is an example of a long method. It has two obvious responsibilities, but it also has a couple of other, subtle responsibilities buried into the conditionals. The comment above the conditional could also be dropped if the conditional were made more explicit. Use the refactorings "Extract Method" and "Decompose Conditional" as many times as appropriate to improve readability and consolidate responsibilities. You needn't introduce any new classes to refactor this method.&lt;/LI&gt;&lt;/UL&gt;To find help or explanations for a particular refactoring, "Extract Method" for example, try googling "extract method refactoring." Good luck and let me know if you have any questions!&lt;BR&gt;&lt;BR&gt;Billy&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=592" width="1" height="1"&gt;</description><enclosure url="http://devlicio.us" length="26755" type="application/x-zip-compressed" /><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/.NET/default.aspx">.NET</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/Refactoring/default.aspx">Refactoring</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/Contests/default.aspx">Contests</category></item><item><title>Refactor It!  The Weekly Book Giveaway</title><link>http://devlicio.us/blogs/billy_mccafferty/archive/2006/11/13/refactor-it-the-weekly-book-giveaway.aspx</link><pubDate>Tue, 14 Nov 2006 04:55:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:575</guid><dc:creator>Billy McCafferty</dc:creator><slash:comments>15</slash:comments><description>&lt;DIV align=left&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;&lt;SPAN style="WIDTH:100%;TEXT-ALIGN:center;"&gt;&lt;STRONG&gt;Each week, refactor&amp;nbsp;my smelly project and win a free book&lt;BR&gt;along with a &lt;A href="http://submain.com/?nav=products.cio" target=_blank&gt;CodeIt.Once Refactoring&lt;/A&gt; tool 3-User license pack!&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV align=left&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV align=left&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;&lt;SPAN&gt;&lt;EM&gt;Here's how it'll work&lt;/EM&gt;...&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;/FONT&gt;&lt;/DIV&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV align=left&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;&lt;SPAN&gt;Each week, beginning tomorrow, Nov. 13, a VS 2005 project will be provided which contains one or more specified "smells."&amp;nbsp; The project may be a Windows App, a Console App,&amp;nbsp;an ASP.NET Web App or even a simple Class Library; but it will always be in C# 2.0.&amp;nbsp; Refactorings may range from simply introducing new methods to applying design patterns.&amp;nbsp; The project will have one or more unit tests, verified with NUnit 2.0, to verify that the project is in working order.&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;/FONT&gt;&lt;/DIV&gt;
&lt;LI&gt;
&lt;DIV align=left&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;&lt;SPAN&gt;You have until the&amp;nbsp;specified time&amp;nbsp;to submit your zipped, refactored solution.&amp;nbsp; Instructions for submitting your solution will be presented when the contest begins.&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;&lt;SPAN&gt;&lt;EM&gt;To be considered, the solution must be&amp;nbsp;compilable&amp;nbsp;with all unit tests passing.&lt;/EM&gt; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;LI&gt;
&lt;DIV align=left&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;&lt;SPAN&gt;The winner will be randomly selected from all "correct" submissions received.&amp;nbsp; (I'll use my 2-year old to pick the name instead of Math.Random to make sure it's truly random!)&amp;nbsp;&amp;nbsp;As there are 1,000 ways to skin a cat - no offense to any PETA readers - "correct" entries will be subjectively determined by yours truly, Billy McCafferty.&amp;nbsp; Along with an announcement of the week's winner, a results summary and&amp;nbsp;refactoring analysis will be presented.&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;&lt;SPAN&gt;"Correct" can generally be defined as the solution which presents simple, concise, and maintainable refactorings for the specified smells.&amp;nbsp; Other "correctness" guidelines may be provided at the beginning of each challenge.&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;LI&gt;
&lt;DIV align=left&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;&lt;SPAN&gt;To help your chances, the first "correct" solution received will have two names thrown into the hat instead of one.&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;/FONT&gt;&lt;/DIV&gt;
&lt;LI&gt;
&lt;DIV align=left&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;&lt;SPAN&gt;Only one entry may be submitted for each&amp;nbsp;challenge and,&amp;nbsp;unless specified at the opening of a contest,&amp;nbsp;each&amp;nbsp;participant may only win once.&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV align=left&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;&lt;SPAN&gt;The weekly contest will continue until I get refactoring-itus or I run out of books, whichever comes sooner.&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;DIV align=left&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;&lt;SPAN&gt;&lt;EM&gt;Why refactoring&lt;/EM&gt;...&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV align=left&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV align=left&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;&lt;SPAN&gt;Refactoring has been widely adopted as a vital technique for producing high quality software.&amp;nbsp; It is important that we each&amp;nbsp;embrace this practice into our development work.&amp;nbsp; This contest will serve to present an overview of common smells found within code and&amp;nbsp;discuss&amp;nbsp;techniques to correct those smells&amp;nbsp;for creating better software.&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV align=left&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV align=left&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;&lt;SPAN&gt;&lt;EM&gt;Resources to help&lt;/EM&gt;...&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV align=left&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV align=left&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;&lt;SPAN&gt;The essentials are &lt;U&gt;Refactoring&lt;/U&gt; by Martin Fowler and &lt;U&gt;Refactoring to Patterns&lt;/U&gt; by Joshua Kerievsky.&amp;nbsp; Other&amp;nbsp;resources that may be helpful include &lt;U&gt;Working Effectively with Legacy Code&lt;/U&gt; by Michael Feathers and &lt;U&gt;Patterns of Enterprise Application Architecture&lt;/U&gt; by Martin Fowler.&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV align=left&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV align=left&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;&lt;SPAN&gt;&lt;EM&gt;Books up for grabs&lt;/EM&gt;...&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV align=left&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;
&lt;P&gt;&lt;IMG alt="Design Patterns: Elements of Reusable Object-Oriented Software" src="http://www.awprofessional.com/ShowCover.asp?isbn=0201633612&amp;amp;type=c" width=125&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.awprofessional.com/bookstore/product.asp?isbn=0201633612&amp;amp;rl=1"&gt;Design Patterns: Elements of Reusable Object-Oriented Software&lt;/A&gt;&lt;BR&gt;By Erich Gamma, Richard Helm, Ralph Johnson, John M. Vlissides.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;DIV id=cover&gt;&lt;IMG alt="Essential Windows Workflow Foundation" src="http://www.awprofessional.com/ShowCover.asp?isbn=0321399838&amp;amp;type=c" width=125&gt; 
&lt;P&gt;&lt;A href="http://www.awprofessional.com/bookstore/product.asp?isbn=0321399838&amp;amp;rl=1"&gt;Essential Windows Workflow Foundation&lt;/A&gt;&lt;BR&gt;By Dharma Shukla, Bob Schmidt.&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;DIV id=cover&gt;&lt;IMG alt="Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries" src="http://www.awprofessional.com/ShowCover.asp?isbn=0321246756&amp;amp;type=c" width=125&gt; 
&lt;P&gt;&lt;A href="http://www.awprofessional.com/bookstore/product.asp?isbn=0321246756&amp;amp;rl=1"&gt;Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries&lt;BR&gt;&lt;/A&gt;By Krzysztof Cwalina, Brad Abrams.&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;/STRONG&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;IMG alt="Applying Domain-Driven Design and Patterns: With Examples in C# and .NET" src="http://www.awprofessional.com/ShowCover.asp?isbn=0321268202&amp;amp;type=c" width=125&gt; &lt;/P&gt;
&lt;DIV id=cover&gt;
&lt;P&gt;&lt;A href="http://www.awprofessional.com/bookstore/product.asp?isbn=0321268202&amp;amp;rl=1"&gt;Applying Domain-Driven Design and Patterns: With Examples in C# and .NET&lt;/A&gt;&lt;BR&gt;By Jimmy Nilsson.&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;BR&gt;&lt;IMG alt="Essential ASP.NET With Examples in C#" src="http://www.awprofessional.com/ShowCover.asp?isbn=0201760401&amp;amp;type=c" width=125&gt; &lt;/P&gt;
&lt;DIV id=cover&gt;
&lt;P&gt;&lt;A href="http://www.awprofessional.com/bookstore/product.asp?isbn=0201760401&amp;amp;rl=1"&gt;Essential ASP.NET With Examples in C#&lt;/A&gt;&lt;BR&gt;By Fritz Onion.&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;DIV id=cover&gt;&lt;IMG alt="Essential ASP.NET 2.0" src="http://www.awprofessional.com/ShowCover.asp?isbn=0321237706&amp;amp;type=c" width=125&gt; &lt;/DIV&gt;
&lt;DIV id=cover&gt;
&lt;P&gt;&lt;A href="http://www.awprofessional.com/bookstore/product.asp?isbn=0321237706&amp;amp;rl=1"&gt;Essential ASP.NET 2.0&lt;/A&gt;&lt;BR&gt;By Fritz Onion, Keith Brown.&lt;/P&gt;&lt;/DIV&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV align=left&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV align=left&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;&lt;SPAN&gt;Stay tuned to &lt;A href="http://devlicio.us/" target=_blank&gt;&lt;FONT color=#3333ff&gt;devlicio.us&lt;/FONT&gt;&lt;/A&gt; and good luck!&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV align=left&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV align=left&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:Tahoma;"&gt;&lt;SPAN&gt;Billy&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;/FONT&gt;&lt;/DIV&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=575" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/.NET/default.aspx">.NET</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/Refactoring/default.aspx">Refactoring</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/Contests/default.aspx">Contests</category></item><item><title>Show User-Friendly enum Translations</title><link>http://devlicio.us/blogs/billy_mccafferty/archive/2006/10/16/Show-User_2D00_Friendly-enum-Translations.aspx</link><pubDate>Mon, 16 Oct 2006 20:39:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:330</guid><dc:creator>Billy McCafferty</dc:creator><slash:comments>22</slash:comments><description>&lt;p&gt;It&amp;#39;s common to&amp;nbsp;populate a drop-down box with enum values or, similarly,&amp;nbsp;to display an enum setting to the user.&amp;nbsp; The problem is that enum values usually&amp;nbsp;aren&amp;#39;t very pretty to look at.&amp;nbsp; (Memories&amp;nbsp;of hoping QA&amp;nbsp;wouldn&amp;#39;t spot &amp;quot;OrderShipped&amp;quot; come to mind.)&amp;nbsp; In a &lt;a href="http://devlicio.us/blogs/joe_niland/archive/2006/10/02/Dealing-with-data_2D00_driven-enums.aspx"&gt;previous post by Joe Niland&lt;/a&gt;, Joe&amp;nbsp;suggested that attributes be used to maintain the user-friendly version of enum values.&amp;nbsp; What follows is a solution for doing just that.&lt;/p&gt;
&lt;p&gt;What we need is a class that will satisfy the following unit-test:&lt;/p&gt;
&lt;p&gt;[TestFixture]
public class EnumDescriptionTests
{
    [Test]
    public void CanRetrieveEnumTextAndDescription() {
        // Simply uses the enum value itself as the text representation by default
        Assert.That(
            EnumDescription.TextRepresentation.GetTextRepresentationOf(OrderStatus.Delivered),
            Is.EqualTo(&amp;quot;Delivered&amp;quot;));
        Assert.That(
            EnumDescription.TextRepresentation.GetDescriptionOf(OrderStatus.Delivered),
            Is.EqualTo(String.Empty));
        Assert.That(
            EnumDescription.TextRepresentation.GetTextRepresentationOf(OrderStatus.InventoryDepleted),
            Is.EqualTo(&amp;quot;Out of Stock&amp;quot;));
        Assert.That(
            EnumDescription.TextRepresentation.GetDescriptionOf(OrderStatus.InventoryDepleted),
            Is.EqualTo(String.Empty));
        Assert.That(
            EnumDescription.TextRepresentation.GetTextRepresentationOf(OrderStatus.InventoryComing),
            Is.EqualTo(&amp;quot;More in Stock Soon&amp;quot;));
        Assert.That(
            EnumDescription.TextRepresentation.GetDescriptionOf(OrderStatus.InventoryComing),
            Is.EqualTo(&amp;quot;An order for more items has been placed with the supplier&amp;quot;));
    }
    private enum OrderStatus
    {
        Delivered,
        [EnumDescription.TextRepresentation(&amp;quot;Out of Stock&amp;quot;)]
        InventoryDepleted,
        [EnumDescription.TextRepresentation(&amp;quot;More in Stock Soon&amp;quot;, 
            &amp;quot;An order for more items has been placed with the supplier&amp;quot;)]
        InventoryComing
    }
}&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;When a description is provided for an enum value, via the &amp;quot;Description&amp;quot; attribute, then the provided description is returned.&amp;nbsp; When a description isn&amp;#39;t available, the ToString version of the enum value, with spaces put before each capital letter,&amp;nbsp;is returned, instead.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;So then to&amp;nbsp;satisfy the unit test:&lt;/p&gt;
&lt;p&gt;public class EnumDescription
{
    public class TextRepresentationAttribute : Attribute
    {
        public readonly string Text;
        public readonly string Description = &amp;quot;&amp;quot;;
        public TextRepresentationAttribute(string text) {
            Text = text;
            Description = &amp;quot;&amp;quot;;
        }
        public TextRepresentationAttribute(string text, string description) {
            Text = text;
            Description = description;
        }
    }
    public class TextRepresentation
    {
        public static string GetTextRepresentationOf(Enum enumType) {
            TextRepresentationAttribute textRepresentation = GetTextRepresentationAttributeFor(enumType);
            return textRepresentation != null 
                ? textRepresentation.Text 
                : enumType.ToString();
        }
        public static string GetDescriptionOf(Enum enumType) {
            TextRepresentationAttribute textRepresentation = GetTextRepresentationAttributeFor(enumType);
            return textRepresentation != null 
                ? textRepresentation.Description 
                : String.Empty;
        }
        private static TextRepresentationAttribute GetTextRepresentationAttributeFor(Enum enumType) {
            MemberInfo[] memberInfo = enumType.GetType().GetMember(enumType.ToString());
            if (memberInfo != null &amp;amp;&amp;amp; memberInfo.Length == 1) {
                object[] customAttributes =
                    memberInfo[0].GetCustomAttributes(typeof(TextRepresentationAttribute), false);
                if (customAttributes.Length == 1) {
                    return (TextRepresentationAttribute) customAttributes[0];
                }
            }
            return null;
        }
    }
}&lt;/p&gt;
&lt;p&gt;This&amp;nbsp;should&amp;nbsp;make a&amp;nbsp;useful&amp;nbsp;addition to any utility library.&lt;/p&gt;
&lt;p&gt;Billy&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=330" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/.NET/default.aspx">.NET</category></item><item><title>Examine XML of Web Service Response</title><link>http://devlicio.us/blogs/billy_mccafferty/archive/2006/10/09/Examine-XML-of-Web-Service-Response.aspx</link><pubDate>Mon, 09 Oct 2006 22:29:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:275</guid><dc:creator>Billy McCafferty</dc:creator><slash:comments>3</slash:comments><description>&lt;p&gt;While working on winning Netflix&amp;#39;&amp;nbsp;million, I came across a need to examine the raw XML returned by a third party web service.&amp;nbsp; After a&amp;nbsp;couple&amp;nbsp;desk-pounding hours, I finally found&amp;nbsp;a simple&amp;nbsp;solution which works equally well in both Web and Windows apps.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Install &lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=018a09fd-3a74-43c5-8ec1-8d789091255d&amp;amp;displaylang=en"&gt;Web Services Enhancements (WSE) 3.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Add a project reference to Microsoft.Web.Services3&lt;/li&gt;
&lt;li&gt;Modify the&amp;nbsp;web service proxy to inherit from Microsoft.Web.Services3.WebServicesClientProtocol instead of System.Web.Services.Protocols.SoapHttpClientProtocol.&amp;nbsp; (This augments the proxy&amp;#39;s capabilities.)&lt;/li&gt;
&lt;li&gt;The response&amp;#39;s raw XML may then be retrieved immediately after the call to Invoke&amp;nbsp;as ResponseSoapContext.Envelope.InnerXml&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Optionally, log4net may be employed so as not to interrupt the application while it goes about its business...&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Add a project reference to log4net&lt;/li&gt;
&lt;li&gt;Add&amp;nbsp;log4net configuration to app.config or web.config.&amp;nbsp; For example:&lt;br /&gt;
&lt;div style="font-size:10pt;background:white;color:black;font-family:Courier New;"&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;!--&lt;/span&gt;&lt;span style="color:green;"&gt; If you want to turn&amp;nbsp;log4net off completely,&lt;br /&gt;include threshold=&amp;quot;OFF&amp;quot; below &lt;/span&gt;&lt;span style="color:blue;"&gt;--&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;log4net&lt;/span&gt;&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;span style="color:red;"&gt;threshold&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;ON&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;appender&lt;/span&gt;&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;span style="color:red;"&gt;name&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;LogAllToFile&lt;/span&gt;&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;&lt;/span&gt;&lt;span style="color:red;"&gt;type&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;log4net.Appender.FileAppender&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;file&lt;/span&gt;&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;span style="color:red;"&gt;value&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;MyLog.log&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;/&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;appendToFile&lt;/span&gt;&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;span style="color:red;"&gt;value&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;false&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;/&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;layout&lt;/span&gt;&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;span style="color:red;"&gt;type&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;log4net.Layout.PatternLayout&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;conversionPattern&lt;/span&gt;&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:red;"&gt;value&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;%d [%t] %-5l - %m%n%n&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;/&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="color:maroon;"&gt;layout&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="color:maroon;"&gt;appender&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;root&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;span style="color:blue;"&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!--&lt;/span&gt;&lt;span style="color:green;"&gt; ALL, DEBUG, INFO, WARN, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ERROR, FATAL, OFF&lt;/span&gt;&lt;span style="color:blue;"&gt;--&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;span style="color:maroon;"&gt;priority&lt;/span&gt;&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;span style="color:red;"&gt;value&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;ALL&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;/&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;appender-ref&lt;/span&gt;&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;span style="color:red;"&gt;ref&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;LogAllToFile&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;/&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="color:maroon;"&gt;root&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:maroon;"&gt;log4net&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt; &lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;Initialize log4net when the application starts with a call to &lt;span style="color:teal;"&gt;XmlConfigurator&lt;/span&gt;.Configure();&lt;/li&gt;
&lt;li&gt;Add the following&amp;nbsp;code immediately after the call to Invoke in the proxy web service:&lt;br /&gt;
&lt;div style="font-size:10pt;background:white;color:black;font-family:Courier New;"&gt;
&lt;p style="margin:0px;"&gt;log4net.&lt;span style="color:teal;"&gt;ILog&lt;/span&gt; logger = log4net.&lt;span style="color:teal;"&gt;LogManager&lt;/span&gt;.GetLogger(&lt;span style="color:blue;"&gt;typeof&lt;/span&gt;(&lt;span style="color:teal;"&gt;MyProxyClassName&lt;/span&gt;));&lt;/p&gt;
&lt;p style="margin:0px;"&gt;logger.Info(ResponseSoapContext.Envelope.InnerXml);&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With log4net turned on, the&amp;nbsp;raw XML&amp;nbsp;within the web service response will get written out to the log file and the application will not be interrupted.&lt;/p&gt;
&lt;p&gt;Billy&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=275" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/.NET/default.aspx">.NET</category><category domain="http://devlicio.us/blogs/billy_mccafferty/archive/tags/Web+Services/default.aspx">Web Services</category></item></channel></rss>