Modules | Composition Containers

Services

A service is name for an object that provides functionality to other components (the components can be in the same module or in another module) in a loosely coupled way. The software factory includes a set of basic services that you can use in your applications. You can also build your own services that provide infrastructure capabilities specific to your applications.
WebClientApplication loads default implementations of several services and places the services into the root container. These services are available to all modules in the application. Figure 1 illustrates the collection of default services available to all modules.

Note:
It is possible for a module to navigate the composition container hierarchy to access services in another module, but this is not recommended. A module should retrieve shared services from the root composition container (this means a module must place shared services in the root container).

ServicesAvailableToAllModules.png
Figure 1
Services available to all modules

These services include the following:
  • ModuleConfigurationLoaderService. This service locates the configuration information for a module.
  • VirtualPathUtilityService. This service contains useful methods for managing virtual paths and URLs.
  • AuthorizationRulesService. This service registers, and returns registered rules, for a URL.
  • SessionStateLocatorService. This service provides access to System.Web.HttpContext.Current.Session.
  • HttpContextLocatorService. This service provides access to System.Web.HttpContext.Current.
  • ModuleLoaderService. This service loads module assemblies.
  • WebModuleEnumerator. This service extracts module information from all Web.config files located the site folder hierarchy.
  • ModuleContainerLocatorService. This service locates the composition container for a module.
  • ServiceLoaderService. This service loads services into a composition container.
  • WebConfigModuleInfoStore. This service reads configuration files to retrieve modules metadata.

Registering a Service

You can programmatically register a service or register a service through configuration. To programmatically register a service, call the Add method or AddNew method of the Services collection of the composition container within which you want to use the service. This can be the root composition container or a module composition container. To use an existing service instance you have already created, use the Add method.

container.Services.AddNew<WebModuleEnumerator, IModuleEnumerator>(); 

Locating Services

Services are stored in the Services collection of composition containers. Each composition container exposes a Services property that you can use to register and locate services. A Services collection can have only one instance of a service type, but you can add multiple instances of the same type to the Services collection of different composition containers.
Figure 2 illustrates an example composition container hierarchy for an application that has two modules. In this figure, the root container contains two services. Every module has access to the root container; therefore, the services contained by the root container are global to all modules.
A container can contain only a single instance of a service type, but instances of the same service type can be placed in multiple containers. When a module attempts to locate a service, the Composite Web Application Block first examines the collection of services in the container for the module. If the service is not found, the application block looks in the collection of services in the root container. This means a module can override the global services available in the root container, yet leave the global service unchanged for use by other modules.
CompositionContainerHierarchy.PNG
Figure 2
Composition container hierarchy

The Services collection implements the IServiceCollection interface. This interface defines two methods you can use to register services:
  • Add. You use this method to register an existing instance of a service. The ObjectBuilder strategies will be executed on the instance and it will be added to the collection.
services.Add(myService); 
  • AddNew. You use this method to have ObjectBuilder create an instance of the service and register it in the services collection.
services.AddNew(typeof(MyService));

// using generics:
services.AddNew<MyService>(); 

Both the Add and AddNew methods provide overloaded versions that allow you to specify the type that will be used to register the service. This is the type developers use to obtain a reference to the service, as shown in the following code.

// AddNew method
services.AddNew(typeof(MyService), typeof(IMyService));
// AddNew method using generics:
services.AddNew<MyService, IMyService>();

// Add method
services.Add(typeof(IMyService), myService);
// Add method using generics:
services.Add<IMyService>(myService); 

The following code is typical of code that you write in a module; in this example, the module registers both a global service and a module service.

public override void Load(CompositionContainer moduleContainer)
{
  base.Load(moduleContainer);

  AddGlobalServices(moduleContainer.Parent.Services);
  AddModuleServices(moduleContainer.Services);
  RegisterSiteMapInformation(moduleContainer.Services.Get<ISiteMapBuilderService>(true));
}

protected virtual void AddGlobalServices(IServiceCollection globalServices)
{
  globalServices.AddNew<FindCustomerService, IFindCustomerService>();
}

protected virtual void AddModuleServices(IServiceCollection moduleServices)
{
  moduleServices.AddNew<OrdersService, IOrdersService>();
} 

It is also possible to register a service through configuration. This means you can change the registration without modifying code. To register a service through configuration, you add a service configuration element to a Web.config file (the main Web site Web.config or a module Web.config). In the following XML, the OrdersRepository.Services.CustomerService service is registered as a global service. (To register a service as a module service, change the scope attribute to Module).

<compositeWeb>
  <modules>
    <module name="Customers" assemblyName="Customers" virtualPath="~/Customers">
      . . .
      <services>
        <service registerAs="OrdersRepository.Interfaces.Services.ICustomerService, OrdersRepository.Interfaces" type="OrdersRepository.Services.CustomerService, OrdersRepository.Services" scope="Global" />
      </services>
    </module>
  </modules>
      . . .
</compositeWeb> 

Modules | Composition Containers

Last edited Jan 17, 2008 at 3:10 PM by siacomuzzi, version 4

Comments

No comments yet.