Antonio Nakic Alfirevic Antonio Nakic Alfirevic - 28 days ago 12
C# Question

Simple injector - can I intercept object creation

I know I can use

container.Options.RegisterResolveInterceptor
to get notified each time an object is resolved, but for my scenario, I'd like to get notified only when the object was created.

For instance, if the type was registered as
Lifestyle.Singleton
, I'd want my delegate to run the first time the type is resolved (when the singleton instance gets created) but not on subsequent calls to resolve.

Is there an easy way to do this?

Answer

As you already found, the RegisterResolveInterceptor allows intercepting a type that gets resolved directly from the container. This means if you call GetInstance<ILogger>(), the RegisterResolveInterceptor allows to be wrapped around the ILogger, but it won't go off do any of its dependencies.

To hook onto the creation of a type, you can use one of the RegisterInitializer overloads. RegisterInitializer is primarily means to add some additional initialization to a type that is created by Simple Injector, but there are other interesting use cases for it.

In case you have a specific type you want to get notified about, you can use the RegisterInitializer<T>(Action<T>) overload, where you specify the type or abstraction you are interested in. For instance:

container.RegisterInitializer<ILogger>(logger =>
{
    System.Console.WriteLine(logger.ToString());
});

In this case, the initializer will get hooked to any registration that is assignable from ILogger, for instance:

container.Register<ILogger>(() => new DbLogger());
container.Register<ILogger, FileLogger>();
container.Register<EventLogLogger>();

All three registrations (assuming EventLogLogger implements ILogger) will get enriched with the initializer.

If however there isn't a particular type or abstraction you want to hook onto, but rather a wide range of types, or you need to have more information about the type (such as its lifestyle), you can use the second RegisterInitializer overload. This overload takes in an action that will be executed and a predicate that allows you to specify to which registrations the action will be supplied to. For instance:

container.RegisterInitializer(
    data => System.Console.WriteLine(data.Registration.ImplementationType.Name),
    context => context.Registration.Lifestyle == Lifestyle.Singleton);

The previous code snippet registers an initializer that will writes the name of the type created to the console, in case that registration is a Singleton. An example what you can do with this can be found in the Glimpse plugin for Simple Injector. The Glimpse plugin uses this RegisterInitializer overload so it can inform the user which types are created during a particular request.

Comments