Practical Design Patterns in C# – Proxy

Intent

The intent of this pattern is to substitute an object with a placeholder for any reason, such as to transform the input or output or to provide an alternative representation of the original. This pattern is similar in intent to the adapter pattern. But an adapter changes the interface to suit the client’s needs, whereas a proxy mirrors the interface of its underlying object.

Problem

This example uses the SOAP client services tools that ship as a part of .NET. SOAP messages are encoded as XML and can be transmitted over any transport, such as HTTP or SMTP. But parsing XML gets tedious and is prone to errors. And SOAP itself is a gargantuan pile of specifications that few people understand. That’s why vendors sell tooling to generate language-specific bindings that abstract away the XML documents behind types and methods that mirror the web API. As a result, programmers can consume the service by writing statically-typed imperative methods.

This example uses the Number Conversion Service available at the link below.

https://www.dataaccess.com/webservicesserver/numberconversion.wso?WSDL

This service exposes an operation called NumberToWords, that takes an instance of NumberToWordsSoapRequest as a parameter and returns a NumberToWordsSoapResponse. The request object has a Body property of type NumberToWordsRequestBody, which in turn encapsulates an unsigned integer that holds the number to be converted. The operation responds with the type NumberToWordsResponse, containing the string that denotes the value of the number in words.

PlantUML Syntax:</p>
<p>!theme vibrant</p>
<p>interface INumberConversionService {<br />
+NumberToWords(number:ulong)<br />
}</p>
<p>NumberConversionServiceClient .up.|> INumberConversionService</p>
<p>NumberConversionService .up.|> INumberConversionService</p>
<p>NumberConversionServiceClient o-right-> NumberConversionService</p>
<p>class Client #palegreen</p>
<p>Client –> INumberConversionService</p>
<p>

Solution

This entire hierarchy is easily represented in classes that the wsdl.exe utility can generate automatically. The client consumes this API using C# language statements without having to directly interact with the service, XML or network protocols.

try
{
  var client = new NumberConversionSoapTypeClient();
  var response = await client.NumberToWordsAsync(100); // Returns the string "one hundred"
}
catch (Exception)
{
  // Handle the exception.
}

If you were to inspect the contents of the NumberConversionSoapTypeClient, you would see that it has a corresponding method for each operation that is described in the WSDL document for the service.

public class NumberConversionSoapTypeClient
{
  …
  public Task<NumberToWordsResponse> NumberToWordsAsync(ulong ubiNum)
  {
    NumberToWordsRequest inValue = new NumberToWordsRequest();
    inValue.Body = new NumberToWordsRequestBody();
    inValue.Body.ubiNum = ubiNum;
    return ((NumberConversionSoapType(this)).NumberToWordsAsync(inValue);
  }
  …
}

The framework itself provides a general purpose implementation of the method that invokes the API over the network, awaits its response, deserializes its contents into class instances and throws an exception in case an error occurs.

The proxy has a 1:1 parity with the methods, and the request and response types that the service exposes.

Practical Design Patterns in C# – Adapter

Intent

The intent of this pattern is to convert the API to an existing library, usually to encapsulate legacy code, simplify its use or provide an alternative output format, into a different interface that a client expects.

The source code for this design pattern, and all the others, can be viewed in the Practical Design Patterns repository.

Solution

There are many examples of this interface in the real world. Cross-platform GUI toolkits are adapters around the underlying API for each supported platform. Clients can continue to use the API provided by GTK+, Windows Forms or Qt, for their applications that run on Windows, macOS or GNOME. The library takes care of translating the API invocations into native equivalents.

There are many simpler examples of the adapter pattern. A data-driven website is an adapter. It lets web browsers retrieve contents from a database over HTTP instead of running SQL queries on the database engine. It converts the API from SQL to HTTP.

PlantUML Syntax:</p>
<p>!theme vibrant</p>
<p>class DiskInfoProvider {<br />
+CollectAsync()<br />
}</p>
<p>class Completed <<event>></p>
<p>DiskInfoProvider –> ManagementClass : create<br />
DiskInfoProvider –> ManagementOperationObserver : create<br />
DiskInfoProvider ..> Completed : handle</p>
<p>class Client #palegreen</p>
<p>Client -right-> DiskInfoProvider : uses</p>
<p>ManagementOperationObserver -right-> Completed : dispatch</p>
<p>ManagementClass –> ManagementOperationObserver : notify<br />

Modern-day C# applications are often built around the task-based asynchronous pattern, but may need to utilise legacy frameworks or libraries that do not have task-based APIs. The Windows Management Instrumentation (WMI) API is a good example. The ManagementClass and ManagementOperationObserver types work collectively to query the WMI database and raise an event when the results are retrieved.

public class WmiClient
{
  public void GetDiskData()
  {
    var management = new ManagementClass("Win32_LogicalDisk");
    var watcher = new ManagementOperationObserver();
    watcher.Completed += WatcherCompletedHandler;
    management.GetInstances(watcher);
  }

  private void WatcherCompletedHandler(object sender, CompletedEventArgs e)
  {
    // Consume the results of the operation.
    …
  }
}

The code below illustrates how an adapter can convert this into a task-based asynchronous interface.

public class DiskInfoProvider
{
  public async Task<PropertyDataCollection> CollectAsync()
  {
    var tcs = new TaskCompletionSource<PropertyDataCollection>();
    var watcher = new ManagementOperationObserver();

    // The event handler that gets invoked by the watcher.
    var completedHandler = default(CompletedEventHandler);
    completedHandler = new CompletedEventHandler((sender, e) =>
    {
      var tcsLocal = tcs;
      try
      {
        if (e.Status == ManagementStatus.NoError)
        {
          // The operation was completed without any errors.
          tcsLocal.SetResult(e.StatusObject.Properties);
          return;
        }

        if (e.Status == ManagementStatus.CallCanceled || e.Status == ManagementStatus.OperationCanceled)
        {
          // The task was cancelled before it could be completed.
          tcsLocal.SetCanceled();
          return;
        }

        // An exception occurred during the operation.
        tcsLocal.SetException(new Exception($"Runtime error {e.Status}"));
        return;
      }
      finally
      {
        // Clean up the event handlers.
        watcher.Completed -= completedHandler;
      }
    });

    // Wire up the event handler and begin the operation.
    watcher.Completed += completedHandler;
    var management = new ManagementClass("Win32_LogicalDisk");
    management.GetInstances(watcher);
    return tcs.Task;
  }
}

DiskInfoProvider encapsulates ManagementOperationObserver and ManagementClass. The client instantiates DiskInfoProvider and awaits the results from CollectAsync().

public class WmiClient
{
  public void GetDiskData()
  {
    var provider = new DiskInfoProvider();
    var diskProperties = await provider.CollectAsync();
  }
}

Many structural patterns serve similar roles, but have a singular differentiator between themselves. Adapters and proxies are at parallel purpose to each other. A proxy provides a matching replacement to all or most of its underlying API. An adapter changes the API to meet the client’s requirement.

Practical Design Patterns in C# – Singleton

Intent

The Singleton pattern is one of the simplest and most commonly used in practice. Its purpose is to restrict a class to only one instance throughout the lifetime of the application. This is desirable in cases when there is one or only a few resources available and access has to be controlled.

Problem

A common use case is resource pools to objects which are expensive to acquire. Some examples are a database connection pool or a local cache of the results of a network operation. The object pool itself is a design pattern worthy of its own detailed discussion. In this article, however, I will limit myself to describing its implementation as a singleton.

The source code for this design pattern, and all the others, can be viewed in the Practical Design Patterns repository.

Solution

This pattern has multiple possible implementations in C#. The ones shown below are built purely on the language features. There are still other ways of limiting a class to single instance through the use of dependency injection frameworks. Those techniques are not covered here.

PlantUML Syntax:<br />
!theme vibrant</p>
<p>class ConnectionPool {<br />
-{static}instance:ConnectionPool<br />
-released:ISet<br />
-acquired:ISet<br />
+Acquire()<br />
+Release(connection:IDbConnection)<br />
+{static}Instance:ConnectionPool<br />
}<br />

Single-threaded, Lazy Initialisation

The first example is the simplest possible implementation of this pattern. This version is not thread-safe, but can use lazy initialisation in a single-threaded scenario. If there are multiple threads attempting to invoke the Instance property of this class, many or all of them will cause an invocation of the constructor. In this case, it has to be eagerly initialised.

public sealed class ConnectionPool
{
    private static ConnectionPool _instance;

    private ISet<IDbConnection> _released;

    private ISet<IDbConnection> _acquired;

    private ConnectionPool()
    {
        // Initialise the collection objects
    }

    public IDbConnection Acquire()
    {
        // Retrieve a free connection instance
        // Instantiate a new one if there are no free instances
        // Move the connection instance into the acquired collection
    }

    public void Release(IDbConnection connection)
    {
        // Remove the connection from the acquired collection
        // Add it into the released collection
    }

    public static ConnectionPool Instance
    {
        get
        {
            if (null == _instance)
            {
                _instance = new ConnectionPool();
            }

            return _instance;
        }
    }
}

This could be an acceptable solution for simple situations where multiple threads are not involved. But with multi-threaded applications being more or less the norm in a language like C#, the actual number of situations where this code will be safe to use are very limited. This is truer than ever before with the advent of opaque multi-threading as supported by TPL. In my experience, it is safer to err on the side of caution and not use this implementation in production.

In multi-threaded situations, the risk of invoking the constructor multiple times can be mitigated by calling the Instance property immediately on startup before launching any additional threads, i.e. by using eager initialisation. But the cost of eager initialisation and high risk of introducing synchronisation bugs in the future makes it an unattractive option.

If you need thread-safety in your singleton, you need a different solution. The simplest way is to use a lock.

Multi-threaded, Lazy Initialisation

public sealed class ConnectionPool
{
    private static ConnectionPool _instance;

    …

    private readonly object padlock = new { };

    private ConnectionPool()
    {
        // Initialise the collection objects
    }

    public IDbConnection Acquire()
    {
        …
    }

    public void Release(IDbConnection connection)
    {
        …
    }

    public static ConnectionPool Instance
    {
        get
        {
            lock (padlock)
            {
                if (null == _instance)
                {
                    _instance = new ConnectionPool();
                }

                return _instance;
            }
        }
    }
}

The drawback to this technique is that every invocation of Instance has to acquire a lock. This is an unnecessary performance hit after an instance has been created once, because the property does not modify the instance ever afterwards.

Again, this is not incorrect. The code will perform exactly according to the pattern specification, and can be used if bleeding-edge performance is not an absolute must-have or the instance is not being referenced frequently. In practice, locking impacts performance by a single-digit percentage.

Lock-free, Multi-threaded, Lazy Initialisation

But faster it can get. The advantages of ease in maintaining and reasoning about lock-free code are a bonus.

public class ConnectionPool
{
    private static readonly ConnectionPool _instance = new ConnectionPool();

    static ConnectionPool()
    {
    }

    private ConnectionPool()
    {
    }

    public IDbConnection Acquire()
    {
        …
    }

    public void Release(IDbConnection connection)
    {
        …
    }

    public static ConnectionPool Instance
    {
        get
        {
            return _instance;
        }
    }
}

The above example contains a static constructor along with the regular instance constructor. The static constructor itself does not require any code. But as a side-effect of its presence in the code, the type initialiser method of this class is only executed when a static or instance field is accessed for the first time, or when a static, instance or virtual method of the type is invoked for the first time.

This is a by-product of the language design and described in detail by Jon Skeet on his website. The runtime runs this check before creating a new type, and guarantees that this executes only once. This implementation leverages this behaviour to constrain the class instantiation to just once, only when the Instance property of the class is invoked for the first time.

Practical Design Patterns in C# – Prototype

Intent

The prototype pattern simplifies creating instances of a class by copying the contents of an existing instance to create a new one. This alleviates the cost of any expensive computation or I/O being performed in the constructor, or simply copies over the state of an existing object to the new instance for further modification.

The source code for this design pattern, and all the others, can be viewed in the Practical Design Patterns repository.

Problem

This article demonstrates a document editor that has the ability to make and display multiple concurrent snap shots of a document. Each can be reviewed and edited individually and compared with each other. The process begins with a single document in memory, which the user can edit before cloning. When a draft is ready, the user duplicates the object by invoking a command from the UI. This copies the contents of the document over into a new instance. The document also contains a date and time field which is modified to match the time when the duplicate is created.

PlantUML Syntax:<br />
!theme vibrant</p>
<p>interface ICloneable<T> {<br />
+ Clone()<br />
}</p>
<p>class Document {<br />
-version<br />
+CreatedOn<br />
+Text<br />
+Clone()<br />
}</p>
<p>class Client #palegreen</p>
<p>Document .up.|> ICloneable</p>
<p>Document -down-> Document : clones</p>
<p>Client -right-> Document</p>
<p>

Both versions now exist in memory simultaneously and the user can cycle between them as needed.

Solution

For this, there must be a way for the document class to be duplicated. The .NET framework already defines an interface called System.ICloneable with a method called Clone() for just this purpose. The caveat of this technique is that the return type of the Clone() method is an object, thus requiring type-casting of the object instance which is returned. It is quite easy to declare a generic version of the ICloneable interface to avoid this problem.

public interface ICloneable<T>
{
    T Clone();
}

The Document class implements this interface as shown below. This snippet also shows the CreatedOn and Text properties that the Document class exposes.

[Serializable]
public class Document : ICloneable<Document>
{
    private int _version = 0;

    public Document()
    {
        CreatedOn = DateTime.UtcNow;
        Text = string.Empty;
        _version = 1;
    }

    public DateTime CreatedOn
    {
        get;
        private set;
    }

    public string Text
    {
        get;
        set;
    }

    public Document Clone()
    {
        Document clone;

        using (var stream = new MemoryStream())
        {
            var formatter = new BinaryFormatter();
            formatter.Serialize(stream, this);
            var self = stream.ToArray();

            stream.Seek(0, SeekOrigin.Begin);
            clone = (Document)formatter.Deserialize(stream);
            clone.CreatedOn = DateTime.UtcNow;
            clone._version++;
        }

        return clone;
    }
}

When the document instance has to be duplicated, the client calls the Clone method to create a whole new instance of the object based on the contents of the original.

The implementation of the Clone method itself is highly specific to the language and platform in use. The example above demonstrates a straightforward binary copy by serializing the class into a byte array, then immediately serializing it back into a new object instance. This mandates that the Document class be decorated with the Serializable attribute.

This technique works in C# and other .NET languages which implement the BinaryFormatter and MemoryStream APIs.

Another technique to create a duplicate is calling the constructor and setting each property and field individually. Since the Clone method is a part of the same class, it has access to the private members of the new instance as well.

private Document Clone()
{
    var clone = new Document();
    clone.CreatedOn = DateTime.UtcNow;
    clone.Text = Text;
    clone._version++;

    return clone;
}

Finally, the .NET Framework provides a built-in method called MemberwiseClone, which creates a shallow object copy.

private Document Clone()
{
    var clone = (Document)base.MemberwiseClone();
    clone.CreatedOn = DateTime.UtcNow;
    clone._version++;

    return clone;
}

All methods shown above create a shallow copy of the object. In order to create a deep copy, each reference type that the Document class uses must implement a similar Clone method which is invoked when the instance has to be cloned. This can quickly escalate out of hand if these classes further reference other types. For this reason, this pattern is best applied to classes that use value types only.

Practical Design Patterns in C# – Builder

Intent

The builder pattern abstracts multiple steps required to create a complex object into a coherent interface. Objects that need several input parameters are prime candidates for refactoring behind a builder object.

The source code for this design pattern, and all the others, can be viewed in the Practical Design Patterns repository.

Problem

To understand the benefits of this pattern, we must first analyse some code that does not utilise it.

var message = new MailMessage("john@example.com",
                "jane@example.com",
                "101 Ways to Refactor",
                "Lorem ipsu…");

Quick, can you identify what is each parameter in this statement? Is John the sender or recipient? How do you add more than one recipient? How does one create HTML-formatted email? These questions are not immediately obvious. And adding more configurability into the MailMessage class would make for ever longer constructor calls.

A more readable alternative is clearly required, at least to retain the maintenance programmer’s sanity for the future. And there’s our hook for the builder pattern.

PlantUML Syntax:<br />
!theme vibrant</p>
<p>interface IMessageBuilder<TMessage> {<br />
+AddressedTo(recipient:string):EmailBuilder<br />
+From(sender:string):EmailBuilder<br />
+WithBody(body:string):EmailBuilder<br />
+WithSubject(subject:string):EmailBuilder<br />
+GetResults():TMessage<br />
}</p>
<p>class EmailBuilder<MailMessage><br />
EmailBuilder ..|> IMessageBuilder<br />
EmailBuilder -left-> MailMessage : builds</p>
<p>class JsonBuilder<string><br />
JsonBuilder ..|> IMessageBuilder<br />
JsonBuilder -right-> string : builds</p>
<p>class Client #palegreen</p>
<p>Client –> EmailBuilder : calls<br />
Client –> JsonBuilder : calls<br />

Solution

The fundamental type in this example is the builder itself, EmailBuilder in this case. This class separates the components of the message into discrete methods.

public class EmailBuilder
{
    private MailMessage _message;

    public EmailBuilder()
    {
        _message = new MailMessage();
    }

    public EmailBuilder AddressedTo(string recipient)
    {
        …
    }

    public EmailBuilder From(string sender)
    {
        …
    }

    public EmailBuilder WithBody(string body)
    {
        …
    }

    public EmailBuilder WithSubject(string subject)
    {
        …
    }

    public MailMessage GetResults()
    {
        return _message;
    }
}

The client code consumes this interface by invoking each method one after the other. All methods in the builder class return the instance itself (i.e. this) so that multiple methods can be chained together into a single, fluid statement.

var builder = new EmailBuilder();
var message = builder.From("john@example.com")
    .AddressedTo("jane@example.com")
    .AddressedTo("jim@example.com")
    .WithSubject("101 Ways to Refactor")
    .WithBody("Lorem ipsu…")
    .GetResults();

This simple class already makes the code exponentially readable and maintainable. But there’s more!

What if the program has to create multiple types of messages, such as an email plus a browser notification encoded into a JSON object? The API from the EmailBuilder can be easily extracted into an IMessageBuilder interface, then applied to different types of builders.

public interface IMessageBuilder<T>
{
    IMessageBuilder WithSubject(string subject);

    IMessageBuilder<T> WithBody(string body);

    IMessageBuilder<T> From(string sender);

    IMessageBuilder<T> AddressedTo(string recipient);

    T GetResults();
 }

This is a generic interface as the return type of each builder differs, depending on the type of message it creates. As a result, the EmailBuilder class definition and method signatures change as shown below. Any code that consumes this class is not affected.

public class EmailBuilder : IMessageBuilder<MailMessage>
{
    private MailMessage _message;

    public EmailBuilder()
    {
        _message = new MailMessage();
    }

    public IMessageBuilder<MailMessage> AddressedTo(string recipient)
    {
        …
    }

    public IMessageBuilder<MailMessage> From(string sender)
    {
        …
    }

    public IMessageBuilder<MailMessage> WithBody(string body)
    {
        …
    }

    public IMessageBuilder<MailMessage> WithSubject(string subject)
    {
        …
    }

    public MailMessage GetResults()
    {
        return _message;
    }
}

This done, we can move on to the JSON builder. For this example, we use types defined in the wildly popular Json.NET library from Newtonsoft.

public class JsonBuilder : IMessageBuilder<string>
{
    private StringBuilder _builder;

    private JsonTextWriter _writer;

    public JsonBuilder()
    {
        _builder = new StringBuilder();
        var sw = new StringWriter(_builder);
        _writer = new JsonTextWriter(sw);
        _writer.WriteStartObject();
    }

    public IMessageBuilder<string> AddressedTo(string recipient)
    {
        _writer.WritePropertyName("AddressedTo");
        _writer.WriteValue(recipient);
        return this;
    }

    public IMessageBuilder<string> From(string sender)
    {
        _writer.WritePropertyName("From");
        _writer.WriteValue(sender);
        return this;
    }

    public IMessageBuilder<string> WithBody(string body)
    {
        _writer.WritePropertyName("Body");
        _writer.WriteValue(body);
        return this;
    }

    public IMessageBuilder<string> WithSubject(string subject)
    {
        _writer.WritePropertyName("Subject");
        _writer.WriteValue(subject);
        return this;
    }

    public string Build()
    {
        _writer.WriteEndObject();
        return _builder.ToString();
    }
}

The client code must instantiate the JsonBuilder and invoke the same methods on it as it does on any other builder. Each builder can have its own customisations, such as only storing a single recipient’s name in the JSON object, which gets overwritten by any subsequent call to AddressedTo().

var builder = new JsonBuilder();
var message = builder.From("john@example.com")
    .AddressedTo("jane@example.com")
    .AddressedTo("jim@example.com")
    .WithSubject("101 Ways to Refactor")
    .WithBody("Lorem ipsu…")
    .GetResults();