Design of the SharePoint Service Locator

The SharePoint Guidance Library contains the SharePointServiceLocator class. With this class, you can do the following:

  • Request instances of services by providing the interface for that particular service.
  • Register a mapping between an interface and a class that implements that interface.
  • Read and write the type mappings from the SPFarm property bag.
  • Substitute a different service locator implementation, such as the Microsoft patterns & practices Unity dependency injection container.
  • Use the service locator to inject mock objects into your unit tests.

Implementation Overview

The SharePoint service locator defines the following classes:

  • SharePointServiceLocator. This static class is the main entry point for the service locator and is responsible for managing the singleton IServiceLocator instance.
  • ActivatingServiceLocator. This class provides an implementation of the IServiceLocator interface. This class will create instances of the requested services if required.
  • ServiceLocatorConfig. This class allows you to save type mappings as configuration properties. The service locator creates instances at run time based on the type mappings that are saved using this class.
  • ActivatingServiceLocatorFactory. This class implements the IServiceLocatorFactory interface. This class is responsible, by default, for instantiating the current service locator.

The following diagram shows the design of the SharePoint service locator.

Design of the SharePoint service locator

Ff648949.7e5f46a7-8d10-411d-a53e-2637c9f8f69a(en-us,PandP.10).png

The main entry point to the service locator is the SharePointServiceLocator static class. This class creates, initializes, and exposes the singleton instance of the service locator. It uses the Current property to expose the instance. The singleton instance implements the IServiceLocator interface and has both generic and non-generic methods named GetInstance for retrieving services from a service locator.

Relationship to the Common Service Locator

This IServiceLocator interface is defined by the Common Service Locator library, which is available on CodePlex. The goal of the Common Service Locator is to provide a shared interface for inversion of control (IOC) containers and service locators. Because the SharePoint service locator relies on the Common Service Locator interface, it is possible to use service location without being dependent on a specific implementation. The SharePoint Guidance Library provides an IServiceLocator implementation with the ActivatingServiceLocator class, but the Common Service Locator Library provides several other IServiceLocator adapters, such as one for the Microsoft patterns & practices Unity Application Block and one for the Spring.NET Framework.

Note

The Common Service Locator project's ServiceLocator class cannot be used inside of SharePoint because it requires bootstrapping that is not possible in the SharePoint environment. The SharePoint Guidance Library ensures that calling this class throws a NullReferenceException or a NotSupportedException.

Creation of the Service Locator Instance

The IServiceLocator instance is created the first time that the Current property of the SharePointServiceLocator class is retrieved. The SharePoint service locator calls into an IServiceLocatorFactory instance that creates and configures an IServiceLocator instance. This process works as follows:

  1. The SharePointServiceLocator calls the ServiceLocatorConfig class to retrieve the type mappings that are stored in configuration using SharePoint property bags.
  2. To create an IServiceLocator instance, the SharePointServiceLocator class looks to see if a custom IServiceLocatorFactory is configured.
  3. If no custom IServiceLocatorFactory is configured, the ActivatingServiceLocatorFactory class is used as the default class factory responsible for producing the IServiceLocator instance.
  4. If a custom IServiceLocatorFactory is configured, the SharePointServiceLocator will use the IServiceLocatorFactory to create a new IServiceLocator instance and populate it with the type mappings that it has read using the ServiceLocatorConfig class.

By default, the Current property returns an instance of the ActivatingServiceLocator class. This is a service locator that can create instances for services that have a constructor with no parameters.

The ActivatingServiceLocator class allows you to specify that a single instance of the implementation class is used for all service location requests. However, it is recommended that you not use a singleton instance unless you are comfortable with writing thread-safe services and if you have a real need for a single shared instance of your service.

Note

The ActivatingServiceLocator class does not perform dependency injection. If you need this functionality, consider plugging in a dependency injection container such as the Microsoft patterns & practices Unity Application Block.

Configuring Type Mappings

You can add and remove custom type mappings by using the RegisterTypeMapping and RemoveTypeMapping methods of the ServiceLocatorConfig class. This class uses the HierarchicalConfig class to store the type mappings as properties of the current SharePoint farm's property bag.

Note

The configuration information is stored as a farm-level property because the SPFarm.Local property is always present when code is executed on a SharePoint server. This means that the service locator can also be used from command line utilities and feature receivers. However, the SharePoint service locator needs to have read access to the SPFarm.Local. Typically, adding type mappings is done by a feature receiver in the FeatureActivated method. By default, type mappings are not removed when a feature is deactivated.

Passing the InstantiationType.AsSingleton enumerated value as an argument to the RegisterTypeMapping method allows you to specify that a single instance of the implementation class is used for all service location requests. The default value, InstantiationType.NewInstanceForEachRequest, creates new instances with each request.

The SharePointServiceLocator includes some default type mappings, so that it can work "out of the box." The following services are available without further configuration:

  • Logging. By default, the ILogger interface is mapped to the SharePointLogger class. By default, this logging implementation logs to the event log and to the Unified Logging Service (ULS), but this behavior can also be overwritten by registering custom type mappings for the IEventLogLogger or ITraceLogger interfaces.
  • Configuration management. By default, the IConfigManager and IHierarchicalConfig interfaces are mapped to the HierarchicalConfig class.

These default services can be overwritten by registering custom type mappings using the ServiceLocatorConfig class.

Using Service Location in Unit Testing

You can use the SharePoint service locator in your unit tests. To do this, you have to replace the current service locator with a custom service locator that has the type mappings that you need to run your unit tests. You can do this by calling the ReplaceCurrentServiceLocator method of the SharePointServiceLocator class. Calling this method before using the Current property prevents the SharePointServiceLocator class from trying to read type mappings from configuration and creating the new service locator. You can replace the service locator with a mock object, or you can also create an instance of the ActivatingServiceLocator class and fill it with the type mappings that you need for your tests.

After your test completes, call the Reset method of the SharePointServiceLocator class. This ensures that the next call of the SharePointServiceLocator.Current property creates a new service locator instance.

The SharePoint service locator raises an exception of type ActivationException if an error occurs during the process of service location. It may also raise .NET Framework exceptions for assembly and class load errors and exceptions of type NoSharePointContextException when a SharePoint context is required but not present.

Note

Each SharePoint Web application runs in its own application domain. Calling the ReplaceCurrentServiceLocator and Reset methods only affects the SharePointServiceLocator.Current instance in the current application domain. These methods do not have an effect in other application domains. Therefore, the ReplaceCurrentServiceLocator and Reset methods should only be used within unit tests. If you want to change the type of service locator for your application, you should register a custom IServiceLocatorFactory interface, as described earlier.

Versioning Type Registrations

When registering types with the ServiceLocator, the fully qualified assembly name is used. This name contains the name of the class or interface, the name of the assembly that contains the class, the version, and a hash of the public key. You will not have versioning issues for the following reasons:

  • You can register a new implementation of an interface without recompiling the clients.
  • If you change the interface, you need to also recompile the consumers.

You are also able to install several versions of interfaces side by side. However, having side by side versions of assemblies is an advanced .NET Framework topic that goes beyond the scope of this guidance.

Please consider the following recommendations when designing your features:

  • It is recommended that the feature that contains an implementation of an interface also registers the type mapping. When the feature is installed, you should register the type mapping.
  • Consider unregistering the type mapping when the feature is uninstalled. Although this is not required, it does keep the registration database clean.
  • It is not recommended to override type mappings that have been made by a different feature. If feature A installs a type mapping for interface 1 and feature B overrides that type mapping, there is no built-in way to get the original type mapping back if feature B is uninstalled.

Home page on MSDN | Community site