Design Pattern
.NET .NET Core C# Patterns Visual Studio

Using Design Patterns in .NET Core – Part 6 – Singleton

Welcome to today’s post.

In today’s post I will be discussing the Singleton Design Pattern and how we use this pattern in .NET Core.

The singleton design pattern is commonly used in applications where we need to ensure that only one instance of a particular object Is required throughout the running of the application instance.

One common scenario is when we want to maintain one instance of the application settings throughout the application. If the application settings are unchanged throughout the lifetime of the application instance, there should only be one instance of the application settings available for read access.

Whenever the application instance is started or any requests to the application are executing methods, any access to the application configuration by the running thread within any method refers to one existing object instance to the configuration. This is the essence of how a single instance would work in the context of a running application.

In the first section I will explain what the singleton design pattern is.

Explaining the Singleton Design Pattern

The singleton design pattern is a creational pattern, which is responsible for generation of class instances.

Of all the design patterns that I have discussed, the singleton design pattern is the simplest pattern to implement within an application. As I will discuss in this post, there are a few ways we can use the singleton pattern.

Below is the diagram for the Singleton pattern, and it is solely one class that generates instances of itself:

For a class to qualify as a singleton pattern the instance of the class should be in the same scope of the application. The instance of the singleton class is in a global context.

However, we do not get anything for free with a singleton design pattern. There are restrictions on how we can use a singleton class. I will explain these now.

Singleton classes cannot be inherited as they are declared as static or sealed. Non-singleton base classes can be inherited by derived classes which are additional instances of the base class.

In an application framework where we do not use an IOC framework to create instances the class would look something like this:

public sealed class SomeSingletonClass
{
    public static SomeSingletonClass Instance 
    { 
        get { return new SomeSingletonClass(); 
    }
    private SomeSingletonClass () { }
}

And to instantiate a static singleton class we use:

var singletonInstance = SomeSingletonClass.Instance;

When the instance of the class is of global scope and we directly control the creation of the instance, we are unable to use test driven development (TDD). Test driven development relies on being able to create mocks and fakes of classes that we are created using Dependency Injection by an IOC framework.

In addition, being unable to create derived instances makes the singleton class unable to comply with the SOLID principle of separation of concerns. We know that being able to add functionality into additional interfaces requires being able to instantiate a derived instance of a class. If we cannot instantiate an instance of a sealed class, then we are unable to separate out functionality from the class into another derived class.

So, a class that is SOLID compliant and can have inheritances of its base class can have at least one interface as shown:

Public class SomeCompliantClass: IInterface1, ..  IInterfaceN
{
    …
}

Whereas a class that is a singleton class that is not SOLID compliant cannot be inherited. The following does not make a genuine singleton class:

Public sealed class SomeSingletonClass: IInterface1, ..  IInterfaceN
{
    …
}

Whereas a class that is a singleton class that is not SOLID compliant cannot be inherited. The following does not make a genuine singleton class:

Public sealed class SomeSingletonClass: IInterface1, ..  IInterfaceN
{
    …
}

The only possibility for a singleton class is the following declaration:

Public sealed class SomeSingletonClass
{
    …
}

In the final section I will show how to use singleton classes in .NET Core applications.

Using Singleton Classes in .NET Core Applications

To instantiate the class in .NET Core we can use the application start up extension method as shown:

services.AddSingleton<SomeSingletonClass>();

This guarantees any injected instance of the class SomeSingletonClass will always give the same instance throughout the application scope.

The singleton class then serves its ultimate purpose in enforcing the singleton design pattern.

I have showed in previous posts how useful the singleton design pattern can be utilized within .NET Core to implement application configuration or retrieving user context.

For application configuration we have the application configuration defined in a sealed class as shown:

namespace BookLoan.Services
{
    public sealed class AppConfiguration
    {
        public AppConfiguration() { }
        public string AppName { get; set; } 
        public string AppVersion { get; set; } 
    }
}

Then instantiating the application configuration is done using the service collection extension method as shown:

services.Configure<AppConfiguration>(Configuration.GetSection("AppSettings"));

From the above we now know what a singleton pattern is, how we use it within our application and what its limitations are. Despite that this pattern is not SOLID compliant, we can still create an instance of a singleton that can still be injected into classes and is useful for configuration functionality. Being able to extend sealed configuration classes with additional properties and / or methods would require us having to violate the separation of concerns principle and the open closed principles.

That is all for today’s post.

I hope you found this post useful and informative.

Social media & sharing icons powered by UltimatelySocial