Search code examples
c#.netinversion-of-controlautofac

autofac resolve issue for keyed values


I am currently working on a feature and added the builder code like this in the Autofac

builder.RegisterType<ILTLoPublisher<ScheduleUpdateEvent>>()
           .AsImplementedInterfaces()
           .InstancePerRequest()
           .Keyed<IILTLoPublisher<ScheduleUpdateEvent>>(AuditType.Schedule);

builder.RegisterType<ILTLoPublisher<ScheduleUpdatePart>>()
           .AsImplementedInterfaces()
           .InstancePerRequest()
           .Keyed<IILTLoPublisher<ScheduleUpdatePart>>(AuditType.Part);

builder.RegisterType<ILTLoPublisher<ScheduleUpdateTest>>()
           .AsImplementedInterfaces()
           .InstancePerRequest()
           .Keyed<IILTLoPublisher<ScheduleUpdateTest>>(AuditType.Test);

This code is run as a console app service and the call to this is made from an api service.I want it to be called as below


AutoFacModule autofac = new AutoFacModule();
            var builder = new ContainerBuilder();
            autofac.LoadBuilder(builder);
            Container = builder.Build();
            using (var scope = Container.BeginLifetimeScope())
            {
var _publisher1 = scope.ResolveKeyed<IILTLoPublisher<ScheduleUpdateEvent>>(AuditType.Schedule);

var _publisher2 = scope.ResolveKeyed<IILTLoPublisher<ScheduleUpdatePart>>(AuditType.Part);

var _publisher2 = scope.ResolveKeyed<IILTLoPublisher<ScheduleUpdateTest>>(AuditType.Test);
}

When i am trying to resolve it using the below code in my implementation class

var _publisher = scope.ResolveKeyed<IILTLoPublisher<ScheduleUpdateEvent>>(AuditType.Schedule);

I am getting the following error

Unable to resolve the type Apiconnector.Integrations.Vilt.Service.Providers.Custom.Publish.ILTLoPublisher`1[LMS.ILT.ScheduleUpdateEvent]' because the lifetime scope it belongs in can't be located

Solution

  • You can't use InstancePerRequest unless the object being resolved is part of a web request (as noted by the comments on the question). More specifically:

    • The executing application must be a web application.
    • The executing application needs to have the Autofac web integration in place.
    • The resolution must be happening in that web application as part of a response to an inbound web request - for example, as part of an MVC controller or ASP.NET Core middleware.

    The "per request" semantics have nothing to do with the client making the request - it's about the server handling the request.

    You might want to spend some time with the documentation on the topic. There is a section in there about how to implement custom per-request semantics for your app.

    If what you are creating is a console app that takes in requests from clients (e.g., a self-hosted web application) then you need to:

    • Add the existing Autofac web integration for your app type (we do support ASP.NET Web API and ASP.NET Core self hosted scenarios); OR
    • Implement something custom if you're not using ASP.NET (see that doc I linked).

    If what you are creating is a console app that issues requests as a client then you should ignore InstancePerRequest. Instead:

    • Create a new lifetime scope around each request (like you're doing) and treat that as a unit of work.
    • Register components as InstancePerLifetimeScope so there will be just one for the duration of that lifetime scope.

    That said, without a minimal repro it's hard to see what you're doing beyond that to provide any sort of guidance.

    Since you mentioned you're pretty new to all this, it would be very worth your time checking out the Autofac documentation to start understanding concepts like this as well as looking in the Examples repo where there are working examples of many different application types to show you how things work.