Show / Hide Table of Contents

Static dependency injection

Static dependency injection refers to configuring your dependency injection such that when your service is resolved, typically via an interface, it always uses the same configuration of primary implementation class and decorator(s). This differs to using the decorator builder directly where instances are created via a factory and the implementation classes, including which decorators are used and in which order they wrap one another, may differ each time.

Note that the two examples shown below are functionally equivalent. The Autofac API is more powerful than the Microsoft.Extensions.DependencyInjection API, at the cost of being compatible only with Autofac. The Microsoft.Extensions.DependencyInjection API is compatible with any DI container that exposes an implementation of IServiceCollection.

With Microsoft.Extensions.DependencyInjection

When using any implementation of Microsoft.Extensions.DependencyInjection.IServiceCollection to configure your DI, you will want to use the extension methods present upon DecoratorServiceCollectionExtensions to configure your services. Here is an example of the technique; remember to also install the library into your dependency injection as described in the API docs.

using Microsoft.Extensions.DependencyInjection;

// All three of these classes are assumed to implement IServiceInterface.
// Both the 'decorator' classes would take a constructor dependency upon an
// instance of IServiceInterface in order to wrap its functionality.
serviceCollection.AddTransient<ServiceImplementation>();
serviceCollection.AddTransient<ServiceDecoratorOne>();
serviceCollection.AddTransient<ServiceDecoratorTwo>();

serviceCollection.AddTransientDecorator<IServiceInterface>(d =>
    d.UsingInitialImpl<ServiceImplementation>()
     .ThenWrapWith<ServiceDecoratorOne>()
     .ThenWrapWith<ServiceDecoratorTwo>()
);

Notice how each of the three classes ServiceImplementation, ServiceDecoratorOne & ServiceDecoratorTwo is added individually first, but without adding them 'as' their interface. Then, the AddTransientDecorator method is to used to add the assembled service, built via the decorator pattern, 'as' the interface.

Following the logic of this example, if IServiceInterface were injected as a constructor dependency elsewhere in the app, the object received as a dependency would be:

  • An instance of ServiceDecoratorTwo ...
  • ... wrapping an instance of ServiceDecoratorOne ...
  • ... wrapping an instance of ServiceImplementation

With Autofac

When using [Autofac] to configure your DI, you will want to use the extension methods present upon DecoratorContainerBuilderExtensions to configure your services. Here is an example of the technique; remember to also install the library into your dependency injection as described in the API docs.

using Autofac;

// All three of these classes are assumed to implement IServiceInterface.
// Both the 'decorator' classes would take a constructor dependency upon an
// instance of IServiceInterface in order to wrap its functionality.
builder.RegisterType<ServiceImplementation>();
builder.RegisterType<ServiceDecoratorOne>();
builder.RegisterType<ServiceDecoratorTwo>();

builder.RegisterDecoratedService<IServiceInterface>(d =>
    d.UsingInitialImpl<ServiceImplementation>()
     .ThenWrapWith<ServiceDecoratorOne>()
     .ThenWrapWith<ServiceDecoratorTwo>()
);

As with the previous example, each of the three classes ServiceImplementation, ServiceDecoratorOne & ServiceDecoratorTwo are registered individually, without .As<IServiceInterface>(). The RegisterDecoratedService method then handles the registstration for the interface, returning a service assembled via the decorator pattern.

This example would produce the same outcome as the example above, if IServiceInterface were injected as a constructor dependency elsewhere in the app.

  • Improve this Doc
In This Article
Back to top Generated by DocFX