Skip to content

DIInstrumentationWithAutofac

Michael Powell edited this page Jan 30, 2017 · 2 revisions

Autofac reasoning

I am using Autofac for a number of projects whereby I would benefit from exposing diagnostic performance measurements. Thus, the reason why I am providing Autofac support out of the gate.

Dependency Injected Instrumentation with Autofac

The basics exposing performance measurements via Autofac are a bit different from Castle Windsor in that first a ContainerBuilder is prepared, through which necessary services are registered, then followed on up by resolution via IContainer of said services, either explicitly by user request or implicitly via constructor, property, or other injection.

Otherwise, the fundamentals are the same as with ad-hoc instrumentation. The only difference is, you are telling Autofac that measurements should be enabled.

Package References
MeasureIt.Autofac
Autofac.Extras.DynamicProxy
MeasureIt.Castle.Interception
MeasureIt.Castle.Interception
MeasureIt.Core
Castle.Core

There are a couple things that you can do once you adopt this library. We will discuss each one briefly.

Enabling the measurements

You have a couple different choices available to you from which to decide, depending on how specific you want to be when enabling measurements.

The first choice assumes InstrumentationDiscoveryOptions and MeasurementInterceptor as default options and interceptor. For most runtime usage you will want the IRuntimeInstrumentationDiscoveryService and RuntimeInstrumentationDiscoveryService, but there may be times when you also want the IInstallerInstrumentationDiscoveryService and InstallerInstrumentationDiscoveryService. You may provide an options factory as necessary, the default for which simply creates a new default instance.

public static ContainerBuilder EnableMeasurements<TInterface, TService>(
    this ContainerBuilder builder
    , Func<InstrumentationDiscoveryOptions> createOptions = null)
    where TInterface : class, IRuntimeInstrumentationDiscoveryService
    where TService : class, TInterface;

This version allows you to also specify the TOptions.

public static ContainerBuilder EnableMeasurements<TInterface, TService, TOptions>(
    this ContainerBuilder builder
    , Func<TOptions> createOptions = null)
    where TInterface : class, IRuntimeInstrumentationDiscoveryService
    where TService : class, TInterface
    where TOptions : class, IInstrumentationDiscoveryOptions, new();

Last but not least, you may also specify the TInterceptor.

public static ContainerBuilder EnableMeasurements<TInterface, TService, TOptions, TInterceptor>(
    this ContainerBuilder builder
    , Func<TOptions> createOptions = null)
    where TInterface : class, IRuntimeInstrumentationDiscoveryService
    where TService : class, TInterface
    where TOptions : class, IInstrumentationDiscoveryOptions, new()
    where TInterceptor : class, IMeasurementInterceptor;

Example:

ContainerBuilder Builder { get; }

That you have initialized:

Builder = new ContainerBuilder();

Now you want to enable measurements:

Builder.EnableMeasurements<IRuntimeInstrumentationDiscoveryService
    , RuntimeInstrumentationDiscoveryService
    , InstrumentationDiscoveryOptions
    , MeasurementInterceptor>();

And since this is Autofac you are using, don't forget to build the IContainer.

IContainer Container { get; set; }
Container = Builder.Build();

With this, now your container will be configured with the necessary resources to support measuring performance.

Then register your injectible services

This will register your service type with the builder as well as the interception plumbing that is required to support interception.

public static ContainerBuilder EnableMeasurementInterception<TInterface, TService, TInterceptor>(
    this ContainerBuilder builder
    , Func<AutofacProxyGenerationOptions> createGeneratorOptions = null)
    where TInterface : class
    where TService : class, TInterface
    where TInterceptor : class, IMeasurementInterceptor;

When you resolve the service TInterface, then you will have a service instance wired for interception.

Measure free standing instances

Although most times you will want to leverage your container, sometimes you may have a free standing instance.

In this case, you need to know your container and have the obj instance in hand. After that, you may optionally specify the ProxyGenerationOptions.

public static T AsMeasuredInstance<T, TInterceptor>(this IContainer container, T obj
    , Func<ProxyGenerationOptions> createGeneratorOptions = null)
    where T : class
    where TInterceptor : class, IMeasurementInterceptor;

Now you may measure your instance.

Example:

var service = Container.Resolve<MyService>();

And now connect the measurement with the service.

service = service.MeasureInstance();

Or with more specificity if you prefer:

service = service.MeasureInstance<MyService, MeasurementInterceptor>();