Autofac - How to access IRegistrationBuilder from IResolvePipelineBuilder & ResolveRequestContext?

178 views Asked by At

I would like to extend my service registration [e.g. EnableInterfaceInterceptors] from Autofac Pipeline. However, I couldn't find a way to achieve that. Is there any entrypoint for me to access the registration as IRegistrationBuilder?

Provided codes below for your reference

containerBuilder.RegisterGeneric(typeof(CredentialService<>)).InstancePerDependency()
.ConfigurePipeline(p =>
{
    p.Use(PipelinePhase.RegistrationPipelineStart, (context, next) =>
    {
        // WHAT SHOULD I DO HERE TO GET BACK THE IRegistrationBuilder IN ORDER TO EXTEND MY REGISTRATION?

        next(context);
    });
});

Thanks in advance

1

There are 1 answers

3
Gabor On BEST ANSWER

Autofac docs

The context object passed into all middleware is an instance of ResolveRequestContext. This object stores the initial attributes of a resolve request, and any properties updated while the request executes.

You can use this context to:

  • Check the service being resolved with the Service property.
  • Check the Registration being used to provide the service.
  • Get or set the result of the resolve operation with the Instance property.
  • Access the parameters of the request with the Parameters property and change those parameters with the ChangeParameters method.
  • Resolve another service (using any of the normal Resolve methods).

In short

Although it is called registration pipeline, it is actually used when a resolve request occurs.

Instances of IRegistrationBuilder are not stored anywhere except in the configuration callback (see details below), hence you cannot access them in the pipeline in any way.

By the time your pipeline delegate is being executed, IRegistrationBuilder instances are already gone. You have only the IComponentRegistration instance in the ResolveRequestContext.Registration property.

In detail

  • When an instance of IRegistrationBuilder is created then
    • It will have an instance of RegistrationData that contains the Lifetime, Metadata, Options, Ownership and Sharing properties. The extension methods of IRegistrationBuilder actually configures these properties.
    • It will also have an instance of IResolvePipelineBuilder field you actually configure with the .ConfigurePipeline() extension method.
    • It will register a configuration callback into the current ContainerBuilder instance with the IRegistrationBuilder instance.
  • These callbacks are executed by the ContainerBuilder.Build() method.
  • When the callback is executed then it will create an instance of IComponentRegistration from the IRegistrationBuilder instance.
  • This IComponentRegistration contains the same properties that come from the RegistrationData and also gets the configured IResolvePipelineBuilder.
var registrationBuilder =
    containerBuilder
        .RegisterType<ServiceWithDependency>()
        .AsSelf()
        .InstancePerDependency();

registrationBuilder.ConfigurePipeline(
    resolvePipelineBuilder =>
    {
        resolvePipelineBuilder.Use(
            PipelinePhase.RegistrationPipelineStart,
            (context, next) =>
            {
                // context is ResolveRequestContext
                // context.Registration is IComponentRegistration

                next(context);

                // Autofac.Extras.DynamicProxy
                // EnableInterfaceInterceptors() extension method actually uses
                // - context.Registration
                // - context.Instance (this will be overridden with the generated proxy)
                // - context.ResolveService(...)

                // You may also use these properties from context.Registration
                // - context.Registration.Lifetime
                // - context.Registration.Metadata
                // - context.Registration.Options
                // - context.Registration.Ownership
                // - context.Registration.Sharing
            }
        );
    }
);