What is adapter pattern with example in c#

The Adapter pattern is a structural design pattern that allows two incompatible interfaces to work together. It involves creating a wrapper or adapter class that can translate the methods and properties of one interface to another, allowing objects that use one interface to work with objects that use a different interface.

Here’s an example of how the Adapter pattern can be used in C#:

// Adaptee interface
public interface ITarget
{
    void Request();
}

// Adaptee implementation
public class Adaptee
{
    public void SpecificRequest()
    {
        Console.WriteLine("Adaptee: SpecificRequest");
    }
}

// Adapter implementation
public class Adapter : ITarget
{
    private Adaptee _adaptee;

    public Adapter(Adaptee adaptee)
    {
        _adaptee = adaptee;
    }

    public void Request()
    {
        Console.WriteLine("Adapter: Request");
        _adaptee.SpecificRequest();
    }
}

// Client code
static void Main(string[] args)
{
    Adaptee adaptee = new Adaptee();
    ITarget target = new Adapter(adaptee);

    target.Request();
}

In this example, the ITarget interface defines the target interface that the client code expects to use. The Adaptee class represents an interface that is incompatible with ITarget. The Adapter class is the bridge between the two interfaces. It wraps an instance of Adaptee and exposes a method that matches the ITarget interface, while internally calling the appropriate method of Adaptee.

When the client code calls the Request method on the target object, it is actually calling the Request method of the Adapter object. The Adapter object, in turn, calls the SpecificRequest method of the wrapped Adaptee object, effectively translating the call from the ITarget interface to the Adaptee interface.

Response Caching in .Net 6

This post explains how to configure Response Caching Middleware in an ASP.NET Core app using .Net 6. The middleware determines when responses are cacheable, stores responses, and serves responses from cache.

Caching response helps improve the performance and response time of Web APIs where it is possible. But it takes some effort to build out a caching infrastructure and manage it. The Response caching middleware which comes out of the box simplifies the implementation significantly. And also it does not require building custom implementation for caching, plus provides clients the option to choose whether to use a cached value or not.

Create a .Net 6 API, and modify the Program.cs file as below:

using Polly;
using Polly.Extensions.Http;

var builder = WebApplication.CreateBuilder(args);
var httpRetryPolicy = Policy.HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
    //.CircuitBreakerAsync(2, TimeSpan.FromSeconds(30));
    .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(retryAttempt));

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddResponseCaching(x => x.MaximumBodySize = 1024);
builder.Services.AddHttpClient("errorApi", c => { c.BaseAddress = new Uri("https://localhost:7250"); });
builder.Services.AddSingleton<IAsyncPolicy<HttpResponseMessage>>(httpRetryPolicy);


var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

// UseCors must be called before UseResponseCaching
//app.UseCors();

app.UseResponseCaching();

app.Use(async (context, next) =>
{
    context.Response.GetTypedHeaders().CacheControl =
        new Microsoft.Net.Http.Headers.CacheControlHeaderValue()
        {
            Public = true,
            MaxAge = TimeSpan.FromSeconds(10)
        };

    context.Response.Headers[Microsoft.Net.Http.Headers.HeaderNames.Vary] = new string[] { "Accept-Encoding" };
    await next();
});

app.Run();

This API adds headers to control caching on subsequent requests:

  • Cache-Control: Caches cacheable responses for up to 10 seconds.
  • Vary: Configures the middleware to serve a cached response only if the Accept-Encoding header of subsequent requests matches that of the original request.

Add a ValuesController.cs and a simple Get endpoint:

[HttpGet]
public int Get()
{
    return DateTime.Now.Second;
}

Run the API and hit the Get endpoint through Postman and add Cache-Control Header with value “public” and you’ll observe the cached response for 10 seconds.

Retry and Circuit Breaker Policy example .Net 6 and Polly

In this example, we’ll implement the Wait and Retry and Circuit Breaker policy using .Net 6 Web API and Polly. For more details on what Circuit Breaker is, refer to the MSDN documentation.

Create a WebAPI with ValuesController in .Net 6 which will always return an Exception in the Get call.

using Microsoft.AspNetCore.Mvc;

namespace ExternalAPI.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class ValuesController : ControllerBase
    {

        private readonly ILogger<ValuesController> _logger;

        public ValuesController(ILogger<ValuesController> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public ActionResult<IEnumerable<string>> Get()
        {
            throw new Exception("Error");
        }

    }
}

Let’s call this ExternalAPI and running on https://localhost:7250/.

Create another .Net 6 WebAPI called CircuitBreaker.Demo and install Polly and Newtonsoft.json Nuget packages.

Configure Polly and HttpClient in Program.cs file as shown below:

using Polly;
using Polly.Extensions.Http;

var builder = WebApplication.CreateBuilder(args);
var httpRetryPolicy = Policy.HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
    
    .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(retryAttempt));

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddHttpClient("errorApi", c => { c.BaseAddress = new Uri("https://localhost:7250"); });
builder.Services.AddSingleton<IAsyncPolicy<HttpResponseMessage>>(httpRetryPolicy);


var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Now add the PollyController to call the ExternalAPI using the HttpClient:

using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Polly;

namespace CircuitBreaker.Demo.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class PollyController : ControllerBase
    {

        private readonly ILogger<PollyController> _logger;
        private readonly IHttpClientFactory _httpClientFactory;
        private readonly IAsyncPolicy<HttpResponseMessage> _policy;

        public PollyController(ILogger<PollyController> logger, IHttpClientFactory httpClientFactory, IAsyncPolicy<HttpResponseMessage> policy)
        {
            _logger = logger;
            _httpClientFactory = httpClientFactory;
            _policy = policy;
        }

        [HttpGet(Name = "GetApiResult")]
        public async Task<ActionResult<IEnumerable<string>>> Get()
        {
            var client = _httpClientFactory.CreateClient("errorApi");
            var response = await _policy.ExecuteAsync(() => client.GetAsync("values"));
            response.EnsureSuccessStatusCode();
            return JsonConvert.DeserializeObject<string[]>(await response.Content.ReadAsStringAsync());
        }

    }
}

When you run both the APIs, the call to External APIs is automatically made using Wait and Retry policy after every retryAttempt number of seconds 3 times. After that, the calls are stopped as the ExternalAPI keeps giving 500 error.

CircuitBreaker example:

Now change the Http Retry Policy line in the Program.cs file to:

var httpRetryPolicy = Policy.HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
    .CircuitBreakerAsync(2, TimeSpan.FromSeconds(30));

The above line will open the circuit and will start giving Circuit Open Exception after 2 attempts and keep the circuit Open for 30 seconds, which means you cannot make further calls to the API for that duration. The Exception will now be shown as below:

Call .Net core API from Console with App Bearer token

In the following example, we’re using a .Net Core 3.1 Console App that will call API with POST request that requires Authentication with a bearer token in Authrorization Header. The token is generated by passing credentials to another API endpoint.

For more details on how to use appSettings.json file in Console App, check this post.

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;

namespace ConsoleApp1
{

    class Credentials
    {
        public string username { get; set; }
        public string password { get; set; }
    }

    class Token
    {
        public string token { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            string ResponseString = "";
            HttpWebResponse response = null;
            HttpWebResponse response2 = null;
            IConfiguration Config = new ConfigurationBuilder()
                .AddJsonFile("appSettings.json")
                .Build();

            try
            {
                var baseURL = Config.GetSection("baseURL").Value;
                var request = (HttpWebRequest)WebRequest.Create(baseURL + "/token");
                request.Accept = "application/json"; //"application/xml";
                request.Method = "POST";

		//Get credentials from config.
                var dusername = EncryptionService.Decrypt(Config.GetSection("credentials")["username"]);
                var dpassword = EncryptionService.Decrypt(Config.GetSection("credentials")["password"]);

                Credentials cred = new Credentials()
                {
                    username = dusername,
                    password = dpassword
                };

                var myContent = JsonConvert.SerializeObject(cred);

                var data = Encoding.ASCII.GetBytes(myContent);

                request.ContentType = "application/json";
                request.ContentLength = data.Length;

                using (var stream = request.GetRequestStream())
                {
                    stream.Write(data, 0, data.Length);
                }

                using (response = (HttpWebResponse)request.GetResponse())
                {
                    ResponseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
                }

		//Get the token from the /token end-point and call another end-point.
                Token token = JsonConvert.DeserializeObject<Token>(ResponseString);

                var request2 = (HttpWebRequest)WebRequest.Create(baseURL + "/ProcessData");
                request2.Accept = "application/json"; //"application/xml";
                request2.Method = "POST";
				
		//Pass token in Authorization Header.
                request2.Headers["Authorization"] = "Bearer " + token.token;

                using (response2 = (HttpWebResponse)request2.GetResponse())
                {
                    ResponseString = new StreamReader(response2.GetResponseStream()).ReadToEnd();
                }

                Console.WriteLine(ResponseString);
                Environment.Exit(0);
            }
            catch (WebException ex)
            {
                if (ex.Status == WebExceptionStatus.ProtocolError)
                {
                    response = (HttpWebResponse)ex.Response;
                    ResponseString = "Some error occured: " + response.StatusCode.ToString();
                }
                else
                {
                    ResponseString = "Some error occured: " + ex.Status.ToString();
                }
            }

        }
    }

}

Dependency Injection example C#

Dependency Injection is decoupling the usage of an object from it’s creation. An abstraction is created between a higher level class and it’s dependencies.

In the below example, the Notification service (lower level module) is abstracted from the higher level class User.

Create Interface as below:

public interface INotification
{
    void SendNotification(User user);
}

Create a class that implements the above interface:

public class ConsoleNotification: INotification
{   
    public void SendNotification(User user)
    {
        Console.WriteLine($"Changed name to: {user.username}");
    }
}

There can be other classes like EmailNotification that implements this interface.

Now, create a class called User that would require to send notification to a user:

public class User
{
    public string username { get; private set; }
    INotification _notify;

    public User(string name, INotification notify)
    {
        username = name;
        _notify = notify;
    }

    public void changeName(string name)
    {
        username = name;
        _notify.SendNotification(this);
    }
}

In the above code, if the User class was itself creating the ConsoleNotification object, that would have been tight coupling between the 2 classes. So, if we wanted to change the Notification service to EmailNotification, we would have to change the User class directly.

The client which in our case is the Program.cs code, will pass the ConsoleNotification object to the user object in the Constructor which is called Constructor injection.

class Program
{
    static void Main(string[] args)
    {
        var notify = new ConsoleNotification();

        //Passing ConsoleNotification type, could be any other type implementing INotification..
        var user1 = new User("Tim", notify);

        Console.WriteLine($"User Name: {user1.username}");
        user1.changeName("Jim");
        Console.ReadKey();
    }
}

Output:

User Name: Tim
Changed name to: Jim

So, the User class is not directly creating a dependency on a particular type of notification Service. Rather the client is telling at run-time what instance of notification service the User class should use which is also called inversion of control (IoC). We’re creating the object of the dependency first and then injecting it into the higher level object.

Facade Pattern C#

This is a structural design pattern that only exposes a simplified interface to the outside world while hiding the complex subsystems. The facade keeps the unwanted dependencies to one place. Its own behaviour takes care of the internal complexities of the subsystems.

A car acts like a facade to the outside world which exposes it’s own behaviour like on, accelerate, brake, off etc. But you are not aware of how it all works internally.

Let’s take a small example of an online Shopping cart where you add an item to a cart which is the only behaviour exposed for the Client. Once you add the item to the cart, a few things happen internally which are not directly controlled by the user action like checking availability of item, calculation of tax, locking the item for availability and calculating the cost etc.

Create a Console Application which is the Client in this example that will only add the Item to cart. Also, add a class library Shopping that will do all of the above described operations but only expose the Cart to the Client.

public interface IShoppingCart
    {
        bool addItemToCart(int itemid, int qty);
    }

internal interface IStock
    {
        bool checkStockItemsByID(int itemID);
        bool lockItemsTemp(int itemID, int qty);
    }

internal interface IItemCost
    {
        string getItemCostByID(int itemid);
    }

internal interface ITaxes
    {
        string getStateTax(string statecode);
    }

Now, implement the above behaviours while keeping only the ShoppingCart class public:

internal class Stock : IStock
    {
        public bool checkStockItemsByID(int itemID)
        {
            Console.WriteLine($"Item Id: {itemID} is available");
            return true;
        }

        public bool lockItemsTemp(int itemID, int qty)
        {
            Console.WriteLine($"Item Id: {itemID}, quantity: {qty} is locked");
            return true;
        }
    }


internal class ItemCost : IItemCost
    {
        public string getItemCostByID(int itemid)
        {
            Console.WriteLine($"Item Id: {itemid} cost is $25");
            return "25";
        }
    }


internal class Taxes : ITaxes
    {
        public string getStateTax(string statecode)
        {
            Console.WriteLine($"{statecode} state tax is 3.5%");
            return string.Empty;
        }
    }

//Exposed class
public class ShoppingCart : IShoppingCart
    {
        public bool addItemToCart(int itemid, int qty)
        {
            IStock stock = new Stock();
            stock.checkStockItemsByID(itemid);
            stock.lockItemsTemp(itemid, qty);

            IItemCost itemCost = new ItemCost();
            itemCost.getItemCostByID(itemid);

            ITaxes taxes = new Taxes();
            taxes.getStateTax("NY");

            return true;
        }
    }

The console Application only performs the action to add the Item to the cart:

class Program
    {
        static void Main(string[] args)
        {
            IShoppingCart item = new ShoppingCart();
            item.addItemToCart(123, 2);
            Console.ReadKey();
        }
    }


Output:
Item Id: 123 is available
Item Id: 123, quantity: 2 is locked
Item Id: 123 cost is $25
NY state tax is 3.5%

Singleton pattern C#

A Singleton class in OOP allows only one instance of itself to be created. While a conventional class can have any number of instances created. Below is the thread-safe implementation of Singleton class.

using System;
namespace SingletonPattern
{
    // thread-safe way.
    public sealed class Singleton
    {
        private static Singleton obj = null;
        // mutex lock used for thread-safety.
        private static readonly object mutex = new object();
        private int var = 0;

        private Singleton()
        {
        }

        public static Singleton getObj
        {
            get
            {
                lock (mutex)
                {
                    //lazy loading..
                    if (obj == null)
                    {
                        obj = new Singleton();
                    }
                    return obj;
                }
            }
        }

        public void doSomething()
        {
            var += 1;
            Console.WriteLine($"Current Value: {var}");
        }
    }
}

Now, when we call the Singleton class object using getObj from anywhere, it’ll return the same instance of obj.

using System;

namespace SingletonPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            Singleton instance = Singleton.getObj;
            instance.doSomething();
            instance.doSomething();
        }
    }
}

Output:

Current Value: 1
Current Value: 2

An example of a Singleton class can be a Database which returns only 1 instance of itself from wherever we connect to it.

How is it different from a Static class?

  1. A Singleton class can inherit other classes and can also implement interfaces.
  2. A Singleton can be initialized lazily or asynchronously and loaded automatically by the .NET Framework CLR when the program or namespace containing the class is loaded. While a static class is generally initialized when it is first loaded.

Abstract Factory pattern C#

Let’s begin with a story of 2 brothers Bill and Steve. Both love Pizza and Ice Cream. They go to a Food Court which has Pizza outlets like Pizza Hut and Dominos Pizza and Ice Cream Parlours like Baskin Robbins and Mikey.

Taking this real world pattern into our Software design by creating classes. In this context, Food Court will be our FoodFactory abstract class that creates 2 abstract Products Pizza and Ice Cream. The Food Court has 2 sections Fun and Frolic. Bill goes for Fun and Steve goes to Frolic.

public abstract class FoodFactory
{
    public abstract Pizza BakePizza();
    public abstract IceCream MakeIceCream();
}

Create an Abstract Products folder and add the following 2 classes:

public class Pizza {

}

public class IceCream {

}

Create a Products Folder and add the following classes:

public class DominosPizza: Pizza
{
    public DominosPizza()
    {
    }
}
public class PizzaHut: Pizza
{
    public PizzaHut()
    {
    }
}
public class Mikey: IceCream
{
    public Mikey()
    {
    }
}
public class BaskinRobbins: IceCream
{
    public BaskinRobbins()
    {
    }
}

Now, suppose Fun section has Pizza Hut and Mikey and Frolic has Dominos Pizza and Baskin Robbins. Create a folder Factories and under that add the following classes:

class FunFoodFactory : FoodFactory
{
    public override Pizza BakePizza()
    {
        return new PizzaHut();
    }

    public override IceCream MakeIceCream()
    {
        return new Mikey();
    }
}
public class FrolicFoodFactory : FoodFactory
{
    public override Pizza BakePizza()
    {
        return new DominosPizza();
    }

    public override IceCream MakeIceCream()
    {
        return new BaskinRobbins();
    }
}

Now the 2 Good brothers start having fun. Create a class called GoodBrothers as below:

public class GoodBrothers
{
    private readonly Pizza _pizza;
    private readonly IceCream _icecream;

    public GoodBrothers(FoodFactory factory)
    {
        _pizza = factory.BakePizza();
        _icecream = factory.MakeIceCream();
    }

    public string WhatDidYouHaveToday()
    {
        return $"Today I ate at {_pizza.GetType().Name} and {_icecream.GetType().Name}";
    }
}

From the main class we ask them What did you have today?

class Program
{
    static void Main(string[] args)
    {
        GoodBrothers Bill = new GoodBrothers(new FunFoodFactory());
        Console.WriteLine($"Bill: {Bill.WhatDidYouHaveToday()}");

        GoodBrothers Steve = new GoodBrothers(new FrolicFoodFactory());
        Console.WriteLine($"Steve: {Steve.WhatDidYouHaveToday()}");

        Console.ReadKey();
    }
}

Output:

Bill: Today I ate at PizzaHut and Mikey
Steve: Today I ate at DominosPizza and BaskinRobbins

A similar example for Abstract Factory pattern can be for a Clothes Factory abstract class which creates abstract Products like Shirts and Trousers. A Businessman may buy from ElegantFactory and a student may buy from CasualFactory. Shirts can be of types Formal and PoloTs and Trousers can be of type Suit and Jeans.

The ElegantFactory will return types Formal Shirt and Suit Trousers. CasualFactory will return types PoloTs and Jeans. We can create a Client class like GoodBrothers that receives the ClothesFactory reference in it’s constructor to create a Shirt and Trouser for the Businessman and Student and so on.

Factory Pattern C#

Factory Design Pattern falls under the category of creational design pattern. It deals with the problem of creating objects without specifying the exact class of object that will be created. It is abstracting the process of object generation which is determined at run-time.

The behavior of a PizzaFactory class is to Bake a Pizza. So, the PizzaFactory class will create the object based on the choice provided by the customer of whether it is a Dominos Pizza or Pizza Hut.

interface IBake
{
    void Pizza();
}

public class DominosPizza: IBake
{
    public void Pizza()
    {
        Console.WriteLine("Dominos Pizza is Served!");
    }
}


public class PizzaHut: IBake
{
    public void Pizza()
    {
        Console.WriteLine("Pizza Hut is Served!");
    }
}

//The type of object created is determined at run-time.
class PizzaFactory
{
    public static IBake makePizza(int choice)
    {
        IBake objPizza = null;

        switch (choice)
        {
            case 1:
                objPizza = new DominosPizza();
                break;
            case 2:
                objPizza = new PizzaHut();
                break;
            default:
                objPizza = new DominosPizza();
                break;
        }
        return objPizza;
    }
}

Now suppose your Client is a Console Application in this case. The code will be as below:

class Program
{
    static void Main(string[] args)
    {
        IBake objPizza = null;
        Console.WriteLine("Enter your choice of Pizza!");
        int choice = Convert.ToInt32(Console.ReadLine());

        objPizza = PizzaFactory.makePizza(choice);
        objPizza.Pizza();
    }
}

Binary Search with C# and Python

It is a divide and conquer approach to search an element in the Array. At each step, the search space is reduced to half. The input array would be already be sorted.

The first part of the program is a recursive approach to write the Binary Search algorithm. The second approach focuses on the iterative model. The code will spit out the index of the element if found.

public class BinarySearch
    {
        //space and time complexity: O(log2 (n)).
        public int? fnRecursiveBinarySearch(int[] Arr, int k, int low, int high)
        {
            int mid = 0;
            if (low > high)
            {
                return null;
            }
            else
            {
                mid = (high + low) / 2;
                if (k==Arr[mid])
                {
                    return mid;
 //return position of found.
                }
                else if (k < Arr[mid])
                {
                    return fnRecursiveBinarySearch(Arr, k, low, mid - 1);
 //search in first half.
                }
                else
                {
                    return fnRecursiveBinarySearch(Arr, k, mid + 1, high);
 //search in second half.
                }
            }
        }

        //space complexity: O(1) and time complexity: O(log2 (n))
        public int? fnIterativeBinarySearch(int[] Arr, int k, int low, int high)
        {
            int mid = 0;
            do
            {
                mid = (low + high) / 2;
                if(k==Arr[mid]) { return mid; //return position of found. }
                else if(k<Arr[mid]) {
                    high = mid - 1;
 //search in first half.
                }
                else
                {
                    low = mid + 1;
 //search in second half.
                }
            } while (low <= high);
            return null;
        }

    }

To test the above 2 approaches, we use a simple call to both the functions:

class Program
    {
        static void Main(string[] args)
        {
            BinarySearch bs = new BinarySearch();
            int[] Arr = { 5, 6, 3, 1, 8, 10 };

            Console.WriteLine("Recursively Found element at index: {0}", bs.fnRecursiveBinarySearch(Arr, 8, 0, Arr.Length - 1));
            Console.WriteLine("Iteratively Found element at index: {0}", bs.fnIterativeBinarySearch(Arr, 8, 0, Arr.Length - 1));
        }
    }

Time complexity is log2 (n), for both approaches. For the space complexity,
Recursive may reach to log2 (n) space because of the stack, but in the iterative approach, it should be O(1) space complexity.

Python implementation for Binary Search Recursive approach:

Space and time complexity: O(log2 (n))

def binarySearch(array, target):
   return binarySearchHelper(array, target, 0, len(array) - 1)
	
def binarySearchHelper(array, target, left, right):
	if left > right:
		return -1
	middle = (left + right) // 2
	potentialMatch = array[middle]
	if target == potentialMatch:
		return middle
	elif target < potentialMatch:
		return binarySearchHelper(array, target, left, middle - 1)
	else:
		return binarySearchHelper(array, target, middle + 1, right)

Python implementation for Binary Search Iterative approach:

Space complexity: O(1) and time complexity: O(log2 (n))

def binarySearch(array, target):
    left = 0
	right = len(array) - 1
	while left <= right:
		middle = (left + right) // 2
		potentialMatch = array[middle]
		if target == potentialMatch:
			return middle
		elif target < potentialMatch:
			right = middle - 1
		else:
			left = middle + 1
	return -1