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
Copy1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
Copy1
2
3
4
5
// Dependency interface
public interface IService
{
void GetHelp();
}
- Dependency implementation
Copy1
2
3
4
5
// Dependency implementation
public class MyService : IService
{
GetHelp() { // do something }
}
- Dependent service
Copy1
2
3
4
5
6
7
8
9
10
11
12
// 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
1
[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:
The following code sample illustrates how to access utility objects:
Copy
1
2
3
4
5
6
7
8
9
private readonly ILog _logger;
private readonly IHelper _helper;
//use the DI helper
public ExampleService(ILog logger, IHelper helper)
{
_logger = logger.ForContext<ExampleService>();
_helper = helper;
}