One of my dependencies (DbContext) is registered using the WebApiRequestLifestyle scope.
Now, my background job uses IoC and depends on the service that was registered above using the WebApiRequestLifestyle. I'm wondering how this works when Hangfire calls the method i registered for the background job. Will the DbContext be treated like a transistent object since the web api is not involved?
Any guidance would be great!
Here is my initialize code that occurs during start up:
public void Configuration(IAppBuilder app)
{
var httpConfig = new HttpConfiguration();
var container = SimpleInjectorWebApiInitializer.Initialize(httpConfig);
var config = (IConfigurationProvider)httpConfig.DependencyResolver
.GetService(typeof(IConfigurationProvider));
ConfigureJwt(app, config);
ConfigureWebApi(app, httpConfig, config);
ConfigureHangfire(app, container);
}
private void ConfigureHangfire(IAppBuilder app, Container container)
{
Hangfire.GlobalConfiguration.Configuration
.UseSqlServerStorage("Hangfire");
Hangfire.GlobalConfiguration.Configuration
.UseActivator(new SimpleInjectorJobActivator(container));
app.UseHangfireDashboard();
app.UseHangfireServer();
}
public static Container Initialize(HttpConfiguration config)
{
var container = new Container();
container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle();
InitializeContainer(container);
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.RegisterWebApiControllers(config);
container.RegisterMvcIntegratedFilterProvider();
container.Register<Mailer>(Lifestyle.Scoped);
container.Register<PortalContext>(Lifestyle.Scoped);
container.RegisterSingleton<TemplateProvider, TemplateProvider>();
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
config.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);
return container;
}
Here is my code that kicks off the background job:
public class MailNotificationHandler : IAsyncNotificationHandler<FeedbackCreated>
{
private readonly Mailer mailer;
public MailNotificationHandler(Mailer mailer)
{
this.mailer = mailer;
}
public Task Handle(FeedbackCreated notification)
{
BackgroundJob.Enqueue<Mailer>(x => x.SendFeedbackToSender(notification.FeedbackId));
BackgroundJob.Enqueue<Mailer>(x => x.SendFeedbackToManagement(notification.FeedbackId));
return Task.FromResult(0);
}
}
Finally here is the code that runs on the background thread:
public class Mailer
{
private readonly PortalContext dbContext;
private readonly TemplateProvider templateProvider;
public Mailer(PortalContext dbContext, TemplateProvider templateProvider)
{
this.dbContext = dbContext;
this.templateProvider = templateProvider;
}
public void SendFeedbackToSender(int feedbackId)
{
Feedback feedback = dbContext.Feedbacks.Find(feedbackId);
Send(TemplateType.FeedbackSender, new { Name = feedback.CreateUserId });
}
public void SendFeedbackToManagement(int feedbackId)
{
Feedback feedback = dbContext.Feedbacks.Find(feedbackId);
Send(TemplateType.FeedbackManagement, new { Name = feedback.CreateUserId });
}
public void Send(TemplateType templateType, object model)
{
MailMessage msg = templateProvider.Get(templateType, model).ToMailMessage();
using (var client = new SmtpClient())
{
client.Send(msg);
}
}
}
I'm wondering how this works when Hangfire calls the method i registered for the background job. Will the DbContext be treated like a transistent object since the web api is not involved?
As the design decisions describe, Simple Injector will never allow you to resolve an instance outside an active scope. So that DbContext will neither be resolved as transient or singleton; Simple Injector will throw an exception when there's no scope.
Every application type requires its own type of scoped lifestyle. Web API requires the AsyncScopedLifestyle (in previous versions WebApiRequestLifestyle), WCF an WcfOperationLifestyle and MVC the WebRequestLifestyle. For Windows Services you will typically use an AsyncScopedLifestyle.
If your Hangfire jobs run in a Windows Service, you will have to use either a ThreadScopedLifestyle or the AsyncScopedLifestyle. Those scopes require explicit starting.
When running the jobs on a background thread in a web (or Web API) application, there is no access to the required context and this means that Simple Injector will throw an exception if you try to do so.
You however are using the Hangfire.SimpleInjector integration library. This library implements a custom JobActivator implementation called SimpleInjectorJobActivator and this implementation will create start a Scope for you on the background thread. Hangfire will actually resolve your Mailer within the context of this execution context scope. So the Mailer constructor argument in your MailNotificationHandler is actually never used; Hangfire will resolve this type for you.
The WebApiRequestLifestyle and AsyncScopedLifestyle are interchangeable; the WebApiRequestLifestyle uses an execution context scope in the background and the SimpleInjectorWebApiDependencyResolver actually starts an execution context scope. So the funny thing is that your WebApiRequestLifestyle can be used for background operations as well (although it can be a bit confusing). So your solution works and works correctly.
When running in MVC, however, this will not work, and in that case you would have to create a Hybrid lifestyle, for instance:
var container = new Container();
container.Options.DefaultScopedLifestyle = Lifestyle.CreateHybrid(
new AsyncScopedLifestyle(),
new WebRequestLifestyle());
You can register your DbContext as follows:
container.Register<DbContext>(() => new DbContext(...), Lifestyle.Scoped);
Here's some feedback on your application's design, if you don't mind.
Prevent letting application code, such as your MailNotificationHandler, from taking a direct dependency on an external library such as Hangfire. This is a direct violation of the Dependency Inversion Principle and makes your application code very hard to test and maintain. Instead, let solely your Composition Root (the place where you wire your dependencies) take a dependency on Hangfire. In your case, the solution is really straightforward and I would even say pleasant, and it would look as follows:
public interface IMailer
{
void SendFeedbackToSender(int feedbackId);
void SendFeedbackToManagement(int feedbackId);
}
public class MailNotificationHandler : IAsyncNotificationHandler<FeedbackCreated>
{
private readonly IMailer mailer;
public MailNotificationHandler(IMailer mailer)
{
this.mailer = mailer;
}
public Task Handle(FeedbackCreated notification)
{
this.mailer.SendFeedbackToSender(notification.FeedbackId));
this.mailer.SendFeedbackToManagement(notification.FeedbackId));
return Task.FromResult(0);
}
}
Here we added a new IMailer abstraction and made the MailNotificationHandler dependent on this new abstraction; unaware of the existence of any background processing. Now close to the part where you configure your services, define an IMailer proxy that forwards the calls to Hangfire:
// Part of your composition root
private sealed class HangfireBackgroundMailer : IMailer
{
public void SendFeedbackToSender(int feedbackId) {
BackgroundJob.Enqueue<Mailer>(m => m.SendFeedbackToSender(feedbackId));
}
public void SendFeedbackToManagement(int feedbackId) {
BackgroundJob.Enqueue<Mailer>(m => m.SendFeedbackToManagement(feedbackId));
}
}
This requires the following registrations:
container.Register<IMailer, HangfireBackgroundMailer>(Lifestyle.Singleton);
container.Register<Mailer>(Lifestyle.Transient);
Here we map the new HangfireBackgroundMailer to the IMailer abstraction. This ensures that the BackgroundMailer is injected into your MailNotificationHandler, while the Mailer class is resolved by Hangfire when the background thread is started. The registration of the Mailer is optional, but advisable, since it has become a root object, and since it has dependencies, we want Simple Injector to be aware of this type to allow it to verify and diagnose this registration.
I hope you agree that from perspective of the MailNotificationHandler, the application is much cleaner now.
Related
In my Asp.Net Core App I need a singleton service that I can reuse for the lifetime of the application. To construct it, I need a DbContext (from the EF Core), but it is a scoped service and not thread safe.
Therefore I am using the following pattern to construct my singleton service. It looks kinda hacky, therefore I was wondering whether this is an acceptable approach and won't lead to any problems?
services.AddScoped<IPersistedConfigurationDbContext, PersistedConfigurationDbContext>();
services.AddSingleton<IPersistedConfigurationService>(s =>
{
ConfigModel currentConfig;
using (var scope = s.CreateScope())
{
var dbContext = scope.ServiceProvider.GetRequiredService<IPersistedConfigurationDbContext>();
currentConfig = dbContext.retrieveConfig();
}
return new PersistedConfigurationService(currentConfig);
});
...
public class ConfigModel
{
string configParam { get; set; }
}
What you're doing is not good and can definitely lead to issues. Since this is being done in the service registration, the scoped service is going to be retrieve once when your singleton is first injected. In other words, this code here is only going to run once for the lifetime of the service you're registering, which since it's a singleton, means it's only going to happen once, period. Additionally, the context you're injecting here only exists within the scope you've created, which goes away as soon as the using statement closes. As such, by the time you actually try to use the context in your singleton, it will have been disposed, and you'll get an ObjectDisposedException.
If you need to use a scoped service inside a singleton, then you need to inject IServiceProvider into the singleton. Then, you need to create a scope and pull out your context when you need to use it, and this will need to be done every time you need to use it. For example:
public class PersistedConfigurationService : IPersistedConfigurationService
{
private readonly IServiceProvider _serviceProvider;
public PersistedConfigurationService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public async Task Foo()
{
using (var scope = _serviceProvider.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<IPersistedConfigurationDbContext>();
// do something with context
}
}
}
Just to emphasize, again, you will need to do this in each method that needs to utilize the scoped service (your context). You cannot persist this to an ivar or something. If you're put off by the code, you should be, as this is an antipattern. If you must get a scoped service in a singleton, you have no choice, but more often than not, this is a sign of bad design. If a service needs to use scoped services, it should almost invariably be scoped itself, not singleton. There's only a few cases where you truly need a singleton lifetime, and those mostly revolve around dealing with semaphores or other state that needs to be persisted throughout the life of the application. Unless there's a very good reason to make your service a singleton, you should opt for scoped in all cases; scoped should be the default lifetime unless you have a reason to do otherwise.
Although Dependency injection: Service lifetimes documentation in ASP.NET Core says:
It's dangerous to resolve a scoped service from a singleton. It may cause the service to have incorrect state when processing subsequent requests.
But in your case this is not the issue. Actually you are not resolving the scoped service from singleton. Its just getting an instance of scoped service from singleton whenever it requires. So your code should work properly without any disposed context error!
But another potential solution can be using IHostedService. Here is the details about it:
Consuming a scoped service in a background task (IHostedService)
Looking at the name of this service - I think what you need is a custom configuration provider that loads configuration from database at startup (once only). Why don't you do something like following instead? It is a better design, more of a framework compliant approach and also something that you can build as a shared library that other people can also benefit from (or you can benefit from in multiple projects).
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureAppConfiguration((context, config) =>
{
var builtConfig = config.Build();
var persistentConfigBuilder = new ConfigurationBuilder();
var connectionString = builtConfig["ConnectionString"];
persistentStorageBuilder.AddPersistentConfig(connectionString);
var persistentConfig = persistentConfigBuilder.Build();
config.AddConfiguration(persistentConfig);
});
}
Here - AddPersistentConfig is an extension method built as a library that looks like this.
public static class ConfigurationBuilderExtensions
{
public static IConfigurationBuilder AddPersistentConfig(this IConfigurationBuilder configurationBuilder, string connectionString)
{
return configurationBuilder.Add(new PersistentConfigurationSource(connectionString));
}
}
class PersistentConfigurationSource : IConfigurationSource
{
public string ConnectionString { get; set; }
public PersistentConfigurationSource(string connectionString)
{
ConnectionString = connectionString;
}
public IConfigurationProvider Build(IConfigurationBuilder builder)
{
return new PersistentConfigurationProvider(new DbContext(ConnectionString));
}
}
class PersistentConfigurationProvider : ConfigurationProvider
{
private readonly DbContext _context;
public PersistentConfigurationProvider(DbContext context)
{
_context = context;
}
public override void Load()
{
// Using _dbContext
// Load Configuration as valuesFromDb
// Set Data
// Data = valuesFromDb.ToDictionary<string, string>...
}
}
I have a multi tenant system with background job. The tenancy details are stored in database and based on the tenant adding request in service bus, I want to resolve the dependencies based on tenant.
For this I would have to add dependencies to service collection before creating scope. When trying to inject IServiceCollection, it gives me error.
I am looking for the best way to inject dependencies from HostedService
public async Task MessageHandler(object sender, Message message)
{
// Inject dependencies
services.AddScoped<IMyService,Myservice>(); // No way to get services here
using (var scope = serviceProvider.CreateScope())
{
var ... = scope.ServiceProvider.GetService<...>();
//...
}
}
I had a similar need a while back. I created my own service bus handler.
You could try something like the below, where you inject a service (here as an example I'm using IMessageService) to the ServiceeBusHandler that itself has a dbcontext injected.
Then where ever you implement IServiceBusHandler you can specify for which tenant (and their queues) you want the connection built.
public class ServiceBusHandler : IServiceBusHandler
{
private readonly ServiceBusSender _serviceBusSender;
private readonly IMessageService _messageService;
public ServiceBusHandler(
ServiceBusSender serviceBusSender,
IMessageService messageService)
{
_serviceBusSender = serviceBusSender;
_messageService = messageService;
}
public async Task PublishMessageAsync<T>(T message)
{
var jsonString = JsonConvert.SerializeObject(message);
var serviceBusMessage = new ServiceBusMessage(jsonString);
await _serviceBusSender.SendMessageAsync(serviceBusMessage);
}
internal static IServiceBusHandler Create(ServiceBusSender sender)
{
return new ServiceBusHandler(sender);
}
}
public class ServiceBusHandlerFactory : IServiceBusHandlerFactory
{
private readonly IAzureClientFactory<ServiceBusClient> _serviceBusClientFactory;
public ServiceBusHandlerFactory(
IAzureClientFactory<ServiceBusClient> serviceBusClientFactory)
{
_serviceBusClientFactory = serviceBusClientFactory;
}
public IServiceBusHandler GetClient(string tenantId)
{
var tenantDetails = _messageService.GetTenantDetails(tenantId); // Call to your DB to get details about the Tenant
var client = GetServiceBusClient(tenantDetails.QueueName);
var sender = client.CreateSender(tenantDetails.QueueName);
return ServiceBusHandler.Create(sender);
}
protected virtual ServiceBusClient GetServiceBusClient(string queueName)
{
var client = _serviceBusClientFactory.CreateClient(queueName);
return client;
}
}
What you are trying to achieve is to change the set of registrations after the Container was built. MS.DI does not support this, and while historically, more mature DI Containers tended to support this behavior, most modern DI Containers stopped supporting this, because there are too many negative consequences in allowing this. Autofac, for instance, obsoleted its Update method in 2016 and described the issues with updating the Container in details. Ninject has gone through a similar process, although development stopped before the final release that removed the possibility to update the Container. The Simple Injector DI Container never supported updating, and its documentation has some clear texts that describe what the issue is.
You might find a DI Container that supports this, but I would urge you to abbondon this path, because of the negative consequences that it can (and probably will) cause, as the previous links described.
Instead, you will have to find a different way to get tenant-specific behavior, with one single set of registrations. The trick here, typically lies in creating a Proxy implementation of your IMyService that can forward the call to the correct tenant implementation.
This might look something like this:
public class ProxyMyService : IMyService
{
public IMyService Service { get; set; }
// IMyService methods
public void SomeMethod() => this.Service.SomeMethod();
}
This proxy class can be registered at startup, together with other IMyService implementations, as follows:
services.AddScoped<IMyService, ProxyMyService>();
services.AddTransient<MyServiceTenant1>();
services.AddTransient<DefaultMyServiceTenant>();
With this, your hosted service can become the following:
private ProxyMyService service;
public MyHostedService(IMyService service)
{
this.service = (ProxyMyService)service;
}
public async Task MessageHandler(object sender, Message message)
{
using (var scope = serviceProvider.CreateScope())
{
var p = scope.ServiceProvider;
var proxy = (ProxyMyService)p.GetRequiredService<IMyService>();
proxy.Service = IsTentant1
? p.GetRequiredService<MyServiceTenant1>()
: p.GetRequiredService<DefaultMyServiceTenant>();
var ... = p.GetRequiredService<...>();
//...
}
}
A more evolved solution would entail a Proxy implementation that allows to switch between tenant-specific implementations internally. That would likely mean moving part of the logic that's currently inside MessageHandler into the ProxyMyService.
Do notice that the solutions I suggested do not require an abstract factory. Abstract factories are typically not needed.
Is it possible to run an IHostedService on a service provider that is not the one provided by ConfigureServices?
I am working on a library that helps configure various environments and each one has its own context (the environment context is driven by service providers). I can call .AddHostedService<>(); just fine, it doesn't throw, but the service constructor never gets called and the service doesn't start.
Edit:
I can manually kick off the services like Andy suggests in the answers, but where would that happen?
All IHostedService implementations are executed by the IWebHost that holds on to the IServiceProvider which is passed in to ConfigureServices.
The internal WebHost object holds on to an internal HostedServiceExecutor that is responsible for instantiating and running IHostedService objects.
Since you are running outside of the WebHost, you are the one responsible for instantiating, starting and stopping the services.
What you would have to do is emulate what HostedServiceExecutor does: Instantiate then iterate all services that implement IHostedService and finally call StartAsync and StopAsync
For example:
var serviceCollection = new ServiceCollection();
serviceCollection.AddHostedService<TestHostedService>();
var serviceProvider = serviceCollection.BuildServiceProvider();
// this will instantiate the services
var myHostedServices = serviceProvider.GetService<IEnumerable<IHostedService>>();
// or: var myHostedServices = serviceProvider.GetServices<IHostedService>();
// start the services up
foreach (var hostedService in myHostedServices)
{
await hostedService.StartAsync(token);
}
// ...
// Shutting down: stop the services
foreach (var hostedService in myHostedServices)
{
await hostedService.StopAsync(token);
}
This is extremely simplified code. No exception handling is done. This is just to give you the gist of how you'd do it. You should really study HostedServiceExecutor's code.
As alternative to Andy's suggested solution, you can make the IHostedService into an adapter that forward the call to its own private IServiceProvider:
public class IsolatedHostedService : IHostedService
{
private IServiceProvider provider;
// Functions as Composition Root
public IsolatedHostedService()
{
var services = new ServiceCollection();
services.AddXXX();
provider = services.BuildServiceProvider(validateScopes: true);
}
public Task StartAsync(CancellationToken t)
{
provider.GetRequiredService<YourStuff>().DoSomething();
}
}
Core issue
Every example I see for dependency injection is paired with MVC for some reason as if nothing else exists outside of web projects. I take issue with this because there is a contradiction going on with MVC utilizing dependency injection but it delivers those dependencies through a Dependency Resolver which to me is just another name for a Service Locator.
DI in a simple console application
With all that being said, how do you use DI with a simple console application?
When there isn't a convenient Dependency Resolver ready to use. How do I actually perform the injection part of DI?
I see the disapproving tone around Service Locators, but what else can you do?
You cannot pass the container because that's also bad practice, but again what else can be done?
Common confusion/frustration
I see a lot of programmers making these mistakes and honestly I can't blame them for it. There isn't a clear solution outside of MVC which is clearly using the dreaded Service Locator.
DI introduces its own problems
Something I don't feel good about doing is pass a dependency through a chain of objects to use it in a deeply nested piece of code. This just feels wrong.
Example
This is a watered down example of something I am working on to demonstrate my concern. I don't like passing the SMTP client dependency through a class, just to give it to another class. You might be compelled to say "Inject the SmtpClient into ServiceClass then into EntryPoint". In my example I cannot inject ServiceClass because it actually comes from a Factory pattern.
public static void Main(string[] args)
{
var smtpClient = _container.GetDependency<ISmtpClient>();
//When I do this manually I feel like it defeats the purpose of DI
var ep = new EntryPoint(smtpClient);
ep.RunAProcess();
}
public class EntryPoint
{
private readonly ISmtpClient _smtpClient;
public EntryPoint(ISmtpClient smtpClient)
{
//EntryPoint doesn't use this dependency
_smtpClient = smtpClient;
}
public void RunAProcess()
{
/* More code here */
//ServiceClass actually comes from a Factory, but I didn't
//want to make this example too long
var svc = new ServiceClass(_smtpClient);
svc.Send();
}
}
public class ServiceClass
{
private readonly ISmtpClient _smtpClient;
public ServiceClass(ISmtpClient smtpClient)
{
//ServiceClass uses this dependency
_smtpClient = smtpClient;
}
public void Send()
{
using (var mail = CreateMailMessage(message))
{
_smtpClient.Send(mail);
}
}
}
Almost related existing question
This is the closest SO question I found in relation to my query:
DbContext Dependency Injection outside of MVC project
Outside of MVC you can use HostBuilder see https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-2.2
The general idea is that it works pretty much like the web version ( and will support console, windows services, and linux daemons etc )
public static async Task Main(string[] args)
{
var host = new HostBuilder() .
.ConfigureServices(ConfigureServices)
.UseConsoleLifetime()
.Build();
await host.RunAsync();
}
private static void ConfigureServices(HostBuilderContext context, IServiceCollection services)
{
services
.AddTransient<IThing, Thingy>()
.AddTransient<Stuff>()
.AddHostedService<MyService>();
}
Your Hosted Service is like your main entry point and things from there will be injected....
internal class MyService : IHostedService
{
public MyService(Stuff stuff) // injected stuff
{
}
public Task StartAsync(CancellationToken cancellationToken)
{
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
This is more a matter of misunderstanding the design principles.
Something I don't feel good about passing a dependency through a chain of objects to use it in a deeply nested piece of code. This just feels wrong.
The core of your issue is about understanding how to apply a clean design which allows loose coupling and high cohesion. Whether it is Asp.Net MVC or console application is an implementation detail.
The watered down example in this case is not following a clean design as EntryPoint is tightly coupling to ServiceClass and also violates the Explicit Dependencies Principle.
EntryPoint in this example is not being genuine about its dependencies. If it does not use ISmtpClient directly then it should not explicitly depend on it just to pass it on.
And if ServiceClass is coming from a factory then the factory should be applied at the composition root and then explicitly injected into EntryPoint
Review the following refactoring to see what I am referring to
public static void Main(string[] args) {
//ISmtpClient should be injected into ServiceClass
//when resolved by the container or factoty
IService service = _container.GetDependency<IService>();
var ep = new EntryPoint(service);
ep.RunAProcess();
}
public class EntryPoint {
private readonly IService service;
public EntryPoint(IService service) {
this.service = service;
}
public void RunAProcess() {
/* More code here */
service.Send(message);
}
}
public class ServiceClass : IService {
private readonly ISmtpClient _smtpClient;
public ServiceClass(ISmtpClient smtpClient) {
//ServiceClass uses this dependency
_smtpClient = smtpClient;
}
public void Send(Message message) {
using (var mail = CreateMailMessage(message)) {
_smtpClient.Send(mail);
}
}
}
So even if you apply pure dependency injection at the composition root, only the actual dependencies are injected into the target dependent.
Here's my simple WCF service which was integrated with Autofac.Wcf:
[ServiceContract]
public class MyService
{
private readonly IResponseBuilder _responseBuilder;
private readonly IEnumerable<IOperation> _operations;
public MyService(IResponseBuilder responseBuilder, IEnumerable<IOperation> operations)
{
_responseBuilder = responseBuilder;
_operations = operations;
}
[OperationContract]
public object Execute()
{
foreach (var operation in _operations)
{
operation.Execute();
}
return _responseBuilder.Build();
}
}
I want all operations to use the same instance of IResponseBuilder to build the result. Example of an operation:
public class AlwaysFailOperation : IOperation
{
private readonly IOperationResultBuilder _resultBuilder;
public AlwaysFailOperation(IOperationResultBuilder resultBuilder)
{
_resultBuilder = resultBuilder;
}
public void Execute()
{
_resultBuilder.Fail();
}
}
I know that it can be achieved with ILifetimeScope or IContainer inside MyService, but I want to keep all container work in composition root.
Please help me with this requirements. Here's my current registrations:
public static void AppInitialize()
{
var builder = new ContainerBuilder();
builder.RegisterType<MyService>();
builder.RegisterType<ResponseBuilder>()
.AsImplementedInterfaces();
builder.RegisterType<AlwaysFailOperation>()
.AsImplementedInterfaces();
AutofacHostFactory.Container = builder.Build();
}
InstancePerLifetimeScope should work, but you'll have to test it in your particular scenario.
Due to restrictions with the internals of WCF there is no per request lifetime in WCF. See the bold comment at top of docs. WCF is very limiting with respect to its DI integration points.
Autofac creates an instance context for each instance of the service. That context contains a lifetime scope from which the service instance is resolved. The scope is not named because for singleton services the instance context lives for the life of the service - that's controlled by WCF, not Autofac.
So, hypothetically, if you made your service instance per request in WCF and registered the dependency as instance per lifetime scope you should get the result you want. But, as always, test, test, test. Sometimes getting the right WCF setup with the right Autofac lifetime registrations can be tricky, especially in a complex system.