Dependency Injection

The Kepler framework supports dependency injection, which you can use to facilitate testing the classes implemented for your custom services. It is integrated with the Castle Windsor framework to provide this functionality. The Kepler framework follows the common practice of using a constructor for the injection of a dependent object. For general information, see Dependency injection on Wikipedia, and Castle Windsor on GitHub.

Dependency injection in the Kepler

In the Kepler framework, the dependency injection occurs through your service controller. Your dependency objects must be registered with the injection framework, so they can be supplied to your controllers. Use the following steps to register your dependent objects through Windsor installer:

  • Create a class that implements the IWindsorInstaller interface. This class is now a Windsor installer. For more information, see Windsor installers on GitHub.
  • Perform the registration in an Install method on this class. For more information, see Registering components one-by-one on GitHub.

The Kepler framework installs all Windsor installers in your service assemblies to the dependency injection framework. When an inbound request instantiates a service controller, the dependency injection framework works as follows:

  • It instantiates any objects specified as an input parameters to the constructor for the controller.
  • It injects these parameters into the controller for use during a service call.

The following code samples illustrate the implementation of the ExampleService that has a dependency on the IService interface. The helper is registered in a Windsor installer and injected into the constructor of ExampleService.

  • Windsor installer class
    Copy

    using Castle.MicroKernel.Registration;

    // The iInstaller class must be public.
    public class MyWindsorInstaller : IWindsorInstaller
    {
        // Installers must have public default constructors.

        // IWindsorInstaller contains only one method.
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            // Register an implementation for a dependency's interface.
            container.Register(
                Component.For<IService>()
                    .ImplementedBy<MyService>()
                        .LifeStyle.Transient;
                        // In most cases, use LifeStyle.Transient.
        }
    }
  • Dependency interface
    Copy
    // Dependency interface
    public interface IService
    {
        void GetHelp();
    }
  • Dependency implementation
    Copy
    // Dependency implementation
    public class MyService : IService
    {
        GetHelp() { // do something }
    }
  • Dependent service
    Copy
    // Dependent service
    public class ExampleService : IExampleService
    {
        private readonly IService Service;

        // The dependency injection framework sees the dependency on IService
        // and injects an instance of MyService.
        public ExampleService(IService service)
        {
            Service = service;
        }
    }

Assemblies without a Kepler service

In certain use cases, you may want to run the Windsor installer on an assembly that doesn't contain a Kepler service. You must add the following attribute to your assembly for the Kepler framework to detect it:

Copy
[assembly: Relativity.Kepler.Services.KeplerServiceDependency]

When this attribute is missing, the Kepler framework doesn't detect your assembly and won't run the Windsor installer for it.

Dependency injection through ADS

The dependency injection framework provides Kepler services hosted in Relativity with several utility objects. Add any of the following interfaces to the constructor of your service controller to obtain an implementation of that interface:

  • ILog - in Relativity Server, you can write messages, warnings, and errors to SQL in the eddsdbo.RelativityLogs table.
  • IHelper - use the helper to get an instance of the ADS IHelper, which provides several objects that simplify programming against Relativity. See the following examples:
    • Get an IDBContext object to interact with SQL via the GetDBContext() method. See Obtain a database context.
    • Get an ISecretStore object via the GetSecretStore() method, which is used as a client to interact with the Secret Store for Relativity. See Work with the Secret Store.

    For more information, see Relativity API Helpers.

The following code sample illustrates how to access utility objects:

Copy
private readonly ILog _logger;
private readonly IHelper _helper;

//use the DI helper
public ExampleService(ILog logger, IHelper helper)
{
    _logger = logger.ForContext<ExampleService>();
    _helper = helper;
}