Share via


Container and Services

Dependency injection containers, often referred to as just "containers," are used to satisfy dependencies between components; satisfying these dependencies typically involves registration and resolution. The Composite Application Library provides support for the Unity Application Block (Unity) container, but it is not container-specific. Because the library accesses the container through the IServiceLocator interface, the container can be replaced. To do this, your container must implement the IServiceLocator interface. Usually, if you are replacing the container, you will also need to provide your own container-specific bootstrapper. The IServiceLocator interface is defined in the Common Service Locator Library. This is an open source effort to provide an abstraction over IoC (Inversion of Control) containers, such as dependency injection containers, and service locators. The objective of using this library is to leverage IoC and Service Location without tying to a specific implementation.

The Composite Application Library provides the UnityServiceLocatorAdapter. The UnityServiceLocatorAdapter is an IUnityContainer adapter for the IServiceLocator interface. The UnityServiceLocatorAdapter is mapped to the IServiceLocator interface and the mapping is registered in the UnityBootstrapper class.

Although the Composite Application Library does not reference or rely on a specific container, it is typical that an application will rely on a specific container. This means that it is reasonable for a specific application to refer to the container, but the Composite Application Library will not refer to the container directly. For example, the Stock Trader Reference Implementation (Stock Trader RI) and the QuickStarts included with the Composite Application Guidance rely on the Unity Application Block (Unity) as the container.

IServiceLocator

The following code shows the IServiceLocator interface.

public interface IServiceLocator : IServiceProvider
{
    object GetInstance(Type serviceType);
    object GetInstance(Type serviceType, string key);
    IEnumerable<object> GetAllInstances(Type serviceType);
    TService GetInstance<TService>();
    TService GetInstance<TService>(string key);
    IEnumerable<TService> GetAllInstances<TService>();
}

The Service Locator is extended in the Composite Application Library with the extension methods shown in the following code. You can see that IServiceLocator is used only for resolving, meaning it is used to obtain an instance; it is not used for registration.

    public static class ServiceLocatorExtensions
    {
        public static object TryResolve(this IServiceLocator locator, Type type)
        {
            try
            {
                return locator.GetInstance(type);
            }
            catch (ActivationException)
            {
                return null;
            }
        }

        public static T TryResolve<T>(this IServiceLocator locator) where T: class
        {
            return locator.TryResolve(typeof(T)) as T;
        }
    }

The TryResolve extension method—which the Unity container does not support—returns an instance of the type to be resolved if it has been registered; otherwise, it returns null.

The ModuleInitializer uses IServiceLocator for resolving the module during module loading, as shown in the following code examples.

IModule moduleInstance = null;
try
{
    moduleInstance = this.CreateModule(moduleInfo.ModuleType);
    moduleInstance.Initialize();
}
...



protected virtual IModule CreateModule(string typeName)
{
    Type moduleType = Type.GetType(typeName);
    return (IModule)this.serviceLocator.GetInstance(moduleType);
}

UnityServiceLocatorAdapter

The following code shows the implementation of the UnityServiceLocatorAdapter adapter, used to adapt the Unity container to the Common Service Locator interface.

public class UnityServiceLocatorAdapter : ServiceLocatorImplBase
{
    private readonly IUnityContainer _unityContainer;

    public UnityServiceLocatorAdapter(IUnityContainer unityContainer)
    {
        _unityContainer = unityContainer;
    }

    protected override object DoGetInstance(Type serviceType, string key)
    {
        return _unityContainer.Resolve(serviceType, key);
    }

    protected override IEnumerable<object> DoGetAllInstances(Type serviceType)
    {
        return _unityContainer.ResolveAll(serviceType);
    }
}

Notice that the adapter derives from the ServiceLocatorImplBase class. This class, which is included in the Common Service Locator Library, provides standard implementations of various methods on the IServiceLocator interface; therefore, only the DoGetInstance and DoGetAllInstances methods have to be implemented.

The Unity container's Resolve method returns an instance that satisfies the type requested if the requested type has been registered or the requested type has not been registered but is a concrete type. It will raise an exception in all other scenarios. The ResolveAll method returns a list of type instances if there are one or more registrations; it returns an empty list otherwise.

Considerations for Using IServiceLocator

IServiceLocator is not meant to be the general-purpose container. Containers have different semantics of usage, which often drives the decision for why that container is chosen. Bearing this in mind, the Stock Trader RI uses Unity directly instead of using the IServiceLocator. This is the recommend approach for your application development.

In the following situations, it may be appropriate for you to use the IServiceLocator:

  • You are an independent software vendor (ISV) designing a third-party service that needs to support multiple containers.
  • You are designing a service to be used in an organization where they use multiple containers.

Composite Application Library Services

Applications based on the Composite Application Library are composed through a set of services that the application consumes. These services are injected through the container. In addition to these core services, you may have application-specific services that provide additional functionality as it relates to composition.

Core Services

The following table lists the core non-application specific services in the Composite Application Library.

Service interface

Description

IModuleManager

Defines the interface for the service that will retrieve and initialize the application's modules.

IModuleCatalog

Contains the metadata about the modules in the application. The Composite Application Library provides several different catalogs. For more information, see the Module technical concept.

IModuleInitializer

Initializes the modules.

IRegionManager

Registers and retrieves regions, which are visual containers for layout.

IEventAggregator

A collection of events that is loosely coupled between the publisher and the subscriber.

ILoggerFacade

A wrapper for a logging mechanism. The Stock Trader RI uses the Enterprise Library Logging Application Block, so you can choose your own logging mechanism.

IServiceLocator

Allows the Composite Application Library to access the container. If you want to customize or extend the library, this may be useful.

Application-Specific Services

The following table lists the application-specific services used in the Stock Trader RI. This can be used as an example to understand the types of services your application may provide.

Services in the Stock Trader RI

Description

IMarketFeedService

Provides real-time (mocked) market data. The PositionSummaryPresentationModel updates the position screen based on notifications it receives from this service.

IMarketHistoryService

Provides historical market data used for displaying the trend line for the selected fund.

IAccountPositionService

Provides the list of funds in the portfolio.

IOrdersService

Handles persisting submitted buy/sell orders.

INewsFeedService

Provides a list of news items for the selected fund.

IWatchListService

Handles when new watch items are added to the watch list.

More Information

For more information about other Composite Application Guidance technical concepts, see the following topics:

Home page on MSDN | Community site