6

I'm trying to implement the Service Locator pattern. In the below diagram is my references between projects (.net projects), each box represents a project.

The arrows indicate the dependencies.

I am asking if this is a correct implementation of this pattern or is there a better way?

enter image description here

  • 2
    A service locator locates services. So instead of this, you have that. Is that what you're doing here? – Robert Harvey Jul 27 '16 at 23:46
  • Thanks Robert. I guess that is what is happening. I could probably put Service Locator and Repository Interface in the same project. My aim is Inversion of Control between Business and Data. – user1653400 Jul 28 '16 at 0:16
3

I am asking if this is a correct implementation of this pattern or is there a better way?

Not exactly. Your service locator, in an ideal scenario, doesn't depend on any interfaces - it's just a dumb container/map/factory. Something (reflection, manual coding, inheritance, some serialized form, etc) populates it, and then when consumers ask for an instance that satisfies some arbitrary interface, the service locator provides it. Depending on how it's implemented, it doesn't even depend on data - its consumers tell it where to go.

In an enterprise architecture, where is Service Locator most appropriately used, and why?

All that said, the service locator is commonly viewed as an anti-pattern since the contract it supplies (you ask for an arbitrary interface, I give you an instance that satisfies it) is very broad. It tends towards being a God Object. It tends to be a bit fragile since errors in use only show up at runtime.

Those downsides are true, but anti-pattern implies it always produces badness when used. That is not the case in my experience.

Service Locators are useful when you have many, dynamic components that need to be resolved at runtime - components that will vary depending on the context you're working in. For example, I've seen it used when emulating a variety of hardware devices, each with their own configuration and capabilities. It was just as easy to unit test as IoC containers, had similar runtime errors, but supplied the necessary flexibility that IoC containers could not.

But that sort of scenario is exceedingly rare. In general, having that sort of arbitrary type lookup isn't worth the cost.

3

I know that the question is about Service Locator, but

is there a better way?

Yes, allow me to suggest a better design for your solution.

First of all I suggest using Dependency Injection via Constructor + DI Container instead of Sevice Locator pattern. Service Locator has a number of downsides. Long story short:

  • Your code require reference to Service Locator class/project;
  • It is harder to unit test;
  • While changing/adding new dependencies it is easy to break/forget to add something in service locator. In other words - harder to maintain.

Here is more about Service Locator anti-pattern.

Alternative design:

enter image description here

High-level features:

  1. Your Business Layer (BL) - contains your business data and logic, aka entities and services - does not depend on lower-level code (such as Infrastructure or Data Access). It is a thing in itself, independent of infrastructure/DAL code.
  2. Data Access Contracts (DAC) - Repository Interface in your example - considered as a part of BL and contains only abstractions (interfaces) for data access layer that are used in BL. It can be part of BL project or in its own project. Please note that there is no outgoing arrows from BL/DAC box. This corresponds to Dependency Inversion Principle.
  3. Data Access (DA) - It references Business Logic and contains concrete implementation of interfaces from Data Access Contracts for your specific data storage.
  4. Composition Root - is a special project that references all other projects and composes DI container. You can use any popular DI container such as Ninject, Autofac, Unity...
  5. Your Application Root - for example ASP.Net app - should initialize the DI container at the Application_Start and register the container as default Dependency Resolver.
  6. Then everywhere in your code you should use Dependency Injection via Constructor

Benefits:

  • Classes are loosely coupled.
  • Easy to unit test.
  • Business logic is reusable - you can easily take it out and use it for Mobile App instead for example, with different Data Access and UI.
  • Changing/adding dependencies would require changing constructor, which gives you compile-time error feedback.

Btw, here is an excellent book about the subject: Dependency Injection in .NET

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.