title: Avoiding default constructors and public property setters
body: <p>I'm working on a project with SignalR, and I've got some objects that I'm going to be passing along through it.  These objects are only explicitly created in my back-end code, and I'd really like to be able to enforce immutability and invariants on them.  I'm running into the issue that SignalR requires me (well, really NewtonSoft.Json), to have a default, no-args constructor and public setters on my properties in order for it to serialize and deserialize them over the wire.</p>
  
  <p>Here's a contrived example:</p>
  
  <pre><code>public class Message{
      public string Text {get;set;}
      public int Awesomeness {get;set;}
  }
  </code></pre>
  
  <p>What I'd like, is something more along these lines (it should probably have readonly private fields and getter-only properties to be fully immutable, but for something that is just a POCO with no methods, good enough)</p>
  
  <pre><code>public class Message {
      public string Text {get;private set;}
      public int Awesomeness {get;private set;}
      public Message( string msg, int awesome){
          if (awesome &lt; 1 || awesome &gt; 5){
              throw new ArgumentOutOfRangeException("awesome");
          }
          Text = msg;
          Awesomeness = awesome;
      }
  }
  </code></pre>
  
  <p>If I do that, though, my object can't get deserialized by the SignalR .NET client library.  I can just chuck a default constructor in there, and make my setters public, but then I have to remember to not use them in my code, and make sure no one else on the team uses them without understanding.</p>
  
  <p>I've kicked around the idea of doing this, to mark the default constructor as something that should never be explicitly used:</p>
  
  <pre><code>[Obsolete("Bad! don't do this!")
  public Message(){}
  </code></pre>
  
  <p>But I can't use the Obsolete attribute on just the setter of a property.</p>
  
  <p>If I really wanted to, I could separate out the "real" object from a DTO representation and convert between them, but I'm not really psyched up to write a bunch of boilerplate to do that and introduce another layer.</p>
  
  <p>Is there something I'm overlooking, or do I just need to bite the bullet and deal with it?</p>