The ServiceLocator design pattern builds loosely coupled modules that can be independently developed, tested, and deployed seamlessly Design patterns are solutions to recurring problems and complexities in software design. The ServiceLocator design pattern promotes loose coupling but sans the need of injecting dependencies through constructors, properties or interfaces. This is a popular design pattern that can be used to decouple the service consumers from the concrete classes implementing such services. The ServiceLocator is responsible for returning instances of services when they are requested for by the service consumers or the service clients. In essence, the service consumers or the service clients are not aware of the types that have the service actually implemented in them, rather, the service clients need to take advantage of the service locator to retrieve a reference object to the actual service implementation class. The components participating in the ServiceLocator design pattern include the following: ServiceLocator — The ServiceLocator abstracts the creation of the dependencies and if might also act as a repository of service objects that have already been created and initialized. Initializer — This is responsible for initializing the service instances at runtime. Once these objects have been initialized, they are stored in the ServiceLocator. Client — This represents the service consumer or the service client. Service(s) — This represents the actual service contracts and their implementations. Implementing the ServiceLocator pattern In this section we will explore how we can implement the ServiceLocator design pattern in C#. Let’s now dig into a bit of code. To get started, create a WCF Application Project in Visual Studio IDE. Next, create two services named, CustomerService and ProductService. Here’s how the service contracts look like — I’ve incorporated a simple OperationContract (service operation) in each of these services. [ServiceContract] public interface ICustomerService { [OperationContract] string GetText(); } [ServiceContract] public interface IProductService { [OperationContract] string GetText(); } The implementation of the ProductService and CustomerService classes is given below. Note that these service implementation classes implement the IProductService and ICustomerService interfaces (service contracts) respectively. public class ProductService : IProductService { public string GetText() { return "This is the Product Service..."; } } public class CustomerService : ICustomerService { public string GetText() { return "This is the Customer Service..."; } } And, now, we would create the ServiceLocator class. This class would be static in nature and would contain a Dictionary to store the service instances. Besides, the ServiceLocator class would also contain the GetService and RegisterService methods. While the former will be used to retrieve a particular service instance, the latter would be used to store services instances inside the ServiceLocator’s Dictionary instance named “registeredServices”. Here’s the complete source code of the ServiceLocator class. public static class ServiceLocator { private static readonly Dictionary<Type, object> registeredServices = new Dictionary<Type, object>(); public static T GetService<T>() { return (T)registeredServices[typeof(T)]; } public static void RegisterService<T>(T service) { registeredServices[typeof(T)] = service; } public static Int32 Count { get { return registeredServices.Count; } } } Now that we have created a simple ServiceLocator class, let’s explore how we can take advantage of it to locate and use services. Here’s how you can use the ServiceLocator class we just created — I’ve used a console application here to demonstrate how the services can be located with simplicity. You can feel free to use the same code anywhere in your application where you would need to register and then locate services. static void Main(string[] args) { ICustomerService customerService = new CustomerService(); IProductService productService = new ProductService(); ServiceLocator.RegisterService(customerService); ServiceLocator.RegisterService(productService); ICustomerService testService = ServiceLocator.GetService<ICustomerService>(); string msg = testService.GetText(); Console.WriteLine(msg); Console.Read(); } Note that in this example I’ve not used a separate class to represent the Initializer component we discussed earlier since the initialization code has been embedded inside the ServiceLocator class. The ServiceLocator design pattern is a good choice when you would want to decouple your classes from their dependencies but with minimal change in your application’s source code. Another good candidate for implementing this design pattern is when you would want to isolate the dependencies and especially when these dependencies are not known at the compile time. In other words, you can leverage the ServiceLocator design pattern when you need to design classes that in turn depend on classes whose concrete implementations aren’t known at compile time. Related content feature 14 great preprocessors for developers who love to code Sometimes it seems like the rules of programming are designed to make coding a chore. Here are 14 ways preprocessors can help make software development fun again. By Peter Wayner Nov 18, 2024 10 mins Development Tools Software Development feature Designing the APIs that accidentally power businesses Well-designed APIs, even those often-neglected internal APIs, make developers more productive and businesses more agile. By Jean Yang Nov 18, 2024 6 mins APIs Software Development news Spin 3.0 supports polyglot development using Wasm components Fermyon’s open source framework for building server-side WebAssembly apps allows developers to compose apps from components created with different languages. By Paul Krill Nov 18, 2024 2 mins Microservices Serverless Computing Development Libraries and Frameworks news Go language evolving for future hardware, AI workloads The Go team is working to adapt Go to large multicore systems, the latest hardware instructions, and the needs of developers of large-scale AI systems. By Paul Krill Nov 15, 2024 3 mins Google Go Generative AI Programming Languages Resources Videos