Sunday, March 18, 2012

Never Explicitly Call DateTime.Now

In order to evoke certain scenarios from your application testing, it is often necessary to make your system think the current time is some point in the past or future.  Traditionally, this is done by modifying the Windows system date/time.  But a change like this affects ALL applications, not just your own -- with potentially nasty results.

At the heart of this issue is the fact that accessing the property DateTime.Now is typically scattered everywhere across an application's code base.  Fetching the value in this manner - explicitly - tightly couples your code to the system clock.

A better way would be to treat the system clock as a separate concern.  Instead of accessing DateTime.Now directly, create an interface, called IClock for example, that indirectly retrieves the current time.  By using IClock, objects would be loosely coupled to the system clock.  In fact, a sophisticated implementation if IClock would allow for the current time to be offset by a certain amount, allowing an application to be tested "in the past" or "in the future", all without having to adjust the actual system time.
 


Tuesday, March 13, 2012

Avoid Custom .NET Exception Boilerplate Code

In order to guarantee a custom .NET exception will work in all scenarios, Microsoft recommends the exception class observe certain conventions.  Specifically, the class should implement certain constructors and serialization methods.  This means each of an application's custom exceptions will likely end up with the same boilerplate code.  If an application has dozens of unique exceptions this can add up to a lot of code duplication, with each exception having to implement the same constructors and serialization code.

This code duplication can be avoided by using a single, generic exception used application-wide.  This solution involves the creation of a single DomainException<T> class with one or more serialization exception details classes:

[Serializable]
public class DomainException<T> : Exception
{
    public DomainException(T exceptionDetails) : base(default(String))
    {
        Details = exceptionDetails;
    }

    public T Details
    {
        get;
        private set;
    }

    public DomainException()
    {
        // no argument constructor required for serialization
    }

    public DomainException(T exceptionDetails, Exception innerexception) : base(default(String), innerexception)
    {
        Details = exceptionDetails;
    }

    protected DomainException(SerializationInfo si, StreamingContext sc) : base(si, sc)
    {
        if (si == null)
            throw new NullReferenceException("si");

        Details = (T)si.GetValue("exceptionDetails", typeof(T));
    }
}
This exception class acts as a container for another simple property-only class that includes the exception details:
[Serializable]
public class MyExceptionDetails
{
    public MyExceptionDetails(int failureCode)
    {
        FailureCode = failureCode;
    }

    public int FailureCode
    {
        get;
        private set;
    }
}
A specific error details class like this one would be created where, in the past, an entire exception would have been created. Only the [Serialization] attribute is required to make it serialize-able/compatible with DomainException<T>.  Throwing this exception would look like:
throw new DomainException<MyExceptionDetails>(new MyExceptionDetails(1001));
And because the exception is a concrete type it can be explicitly caught:
try
{
    // some code here
}
catch(DomainException<MyExceptionDetails> ex)
{
    // examine ex.Details
}

Friday, March 9, 2012

Alternative to Visual Studio Solution Folders

Visual Studio provides solution folders as a means to organize items in a hierarchical fashion, especially items that are not part of any one project. This works when existing items are added to solution folders, but not new items. This is because solution folders are virtual - the hierarchy of folders as they appear within the solution is not mirrored on disk. In fact, no folders are created on the physical disk and an item that is added to a solution folder is simply placed in the root solution directory.

To work around the solution folder deficiency I simply created a new project to hold ancillary items. Specifically: 
  • Create a new C# class library project called "Accessories".  
  • Remove all classes from the new project.
  • From the solution configuration manager, un-check the project's build flag for all configurations.
  • Add folders and items to the project, setting each item's build action property to "None".
Viola, now the hierarchy of the folders and items within the project will be mirrored on disk.

Friday, February 24, 2012

C# Socket Hello World Example

Often a better understanding of a programming concept can be had by looking at a bare bones example.  Below is such an example of using .NET sockets to establish communication between a server and one or more clients that does without the fluff.  The server code:

class Server
{
 static void Main(string[] args)
 {
  // create the listener socket
  IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
  Socket serverSocket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
  IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 52000);
  serverSocket.Bind(ipEndPoint);
  serverSocket.Listen(100);

  AutoResetEvent connectedSignal = new AutoResetEvent(false);
  // establish connections with clients
  while (true)
  {
   serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), new Tuple<Socket, AutoResetEvent>(serverSocket, connectedSignal));
   // wait here until we've established a connection
   connectedSignal.WaitOne();
  }
 }

 // asynchronous callback to accept a connection
 static void AcceptCallback(IAsyncResult acceptAsynchResult)
 {
  var connectionObject = (Tuple<Socket, AutoResetEvent>)acceptAsynchResult.AsyncState;
  // signal to the loop in Main that we've established a connection
  connectionObject.Item2.Set();

  Socket receiveSocket = connectionObject.Item1.EndAccept(acceptAsynchResult);

  // receive the data
  var readData = new Tuple<Socket, byte[]>(receiveSocket, new byte[1024]);
  receiveSocket.BeginReceive(readData.Item2, 0, readData.Item2.Length, SocketFlags.None, new AsyncCallback(ReadCallback), readData);
 }

 // asynchronous callback to read socket data
 static void ReadCallback(IAsyncResult readAsyncResult)
 {
  var readData = (Tuple<Socket, byte[]>)readAsyncResult.AsyncState;

  // handle SocketException where SocketErrorCode == SocketError.ConnectionReset 
  // to gracefully handle sudden client disconnects
  int read = readData.Item1.EndReceive(readAsyncResult);

  if (read > 0)
  {
   // write received data to the console
   Console.WriteLine(Encoding.UTF8.GetString(readData.Item2, 0, read));
   // set up to receive more data
   readData.Item1.BeginReceive(readData.Item2, 0, readData.Item2.Length, SocketFlags.None, new AsyncCallback(ReadCallback), readData);
  }
 }
}

The server will establish connections as often as their are clients.  An AutoResetEvent is used to signal when the server has established a connection with a client and should ready itself for another connection.  The client:

IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 52000);
clientSocket = new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
clientSocket.Connect(ipe);

clientSocket.Send(Encoding.UTF8.GetBytes("Hello World"));
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Disconnect(false);

Adding blogger syntax highlighting

Blogger doesn't support syntax highlighting for code by default - you have to add it.  But it's a snap with the instructions here: http://heisencoder.net/2009/01/adding-syntax-highlighting-to-blogger.html.  Plus, it's all inline.  There is a newer version, but it requires you add a link to javascript at alexgorbatchev.com which I wanted to avoid if I could.

Wednesday, February 22, 2012

PowerShell's Read-Host returns immediately

If you're like me and to save time copy and paste a command line you use repeatedly into the PowerShell command window, you could cause issues for the Read-Host cmdlet.  For example, say I pasted these commands:

    cd c:\somedirectory
    .\MyScript.ps1 someparameters

If I, when I copied that text, included the trailing carriage return/line feed at the end, that would cause those two commands to execute the instant I pasted them into the PowerShell window.  The problem is that if MyScript.ps1 contains a call to Read-Host it will trick it into thinking the enter key was pressed, when it was not, and your first Read-Host will fail to block.

To get around this I either 1) make sure I manually enter the command or 2) make sure I don't include the trailing newline when I copy the command text.

System.NotSupportedException instantiating a .NET IpcChannel

Instantiating a System.Runtime.Remoting.Channels.Ipc.IpcChannel was throwing a System.NotSupportedException.  In Visual Studio, hovering over the exception showed it to be a plain System.Exception containing a property _COMPlusExceptionCode with a value of -532462766.  I've also seen a RemotingException, "Failed to create an IPC Port: Access is denied", so the error message you receive may be inconsistent as well.

The problem appears to be a lingering, identical IpcChannel within the same process, even one that is no longer registered but has not yet been completely cleaned up.  The _COMPlusExceptionCode threw me off for a while, but it appears a solution has been found here:

http://social.msdn.microsoft.com/Forums/en/netfxremoting/thread/d154e4a9-3e31-41a5-944c-db867ca77e9e

However this solution will permit multiple connections to be open with potentially undesirable consequences.  A loop that makes several attempts to create the IpcChannel may be a more appropriate solution.