Использовать InstancePerLifetimeScope или InstancePerDependency при регистрации для контроллеров и размещенных служб? - PullRequest
2 голосов
/ 29 марта 2020

Я обновляю свой проект с classi c ASP. Net до Asp. Net Core 3.1. В старом проекте я использовал для регистрации своего UoW и сервисов, таких как:

builder.Register(x => new UnitOfWork())
    .As(typeof(IUnitOfWork))
    .InstancePerLifetimeScope();

builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
    .Where(t => t.Name.EndsWith("Service"))
    .AsImplementedInterfaces()
    .InstancePerLifetimeScope();

Теперь в новом проекте я использую размещенные сервисы, которые я вызываю в действии контроллера. Поэтому я создал реализацию BackgroundQueue и QueuedService и зарегистрировался так:

builder.RegisterType<BackgroundQueue>()
    .As<IBackgroundQueue>()
    .SingleInstance();

builder.RegisterType<QueuedService>()
    .As<IHostedService>()
    .InstancePerDependency();

Действие контроллера может использовать один конкретный сервис. В таких случаях достаточно срока действия, потому что экземпляры удаляются, когда запрос заканчивается. Теперь конкретное действие контроллера вызовет новую службу в очереди, такую ​​как:

backgroundQueue.QueueBackgroundWorkItem(async ct => { //Do stuff... });  

Задаче может потребоваться использовать экземпляр той же конкретной службы. В таком случае задача должна создать совершенно новый экземпляр, потому что задача будет продолжать выполняться еще долго после завершения запроса.

Итак, если я регистрирую UoW и все мои сервисы всегда как InstancePerDependency, это должно удовлетворить оба случая?

1 Ответ

2 голосов
/ 29 марта 2020

Если фоновое задание использует другие службы, например DbContext, зарегистрированное как InstancePerLifetimeScope, может потребоваться использование дочерней области с службами, зарегистрированными для области задания:

public class MyController
{
    public MyController(ILifetimeScope parentScope)
    {
        var builder = new ContainerBuilder();

        builder.RegisterType<MyDbContext>()
            .WithParameters(new[] { new TypedParameter(typeof(DbContextOptions), MasterDbContext.GetOptions(masterDbConnectionString)) })
            .InstancePerLifetimeScope()
           .AsSelf();
        [..other services]

        var container = builder.Build();

        backgroundQueue.QueueBackgroundWorkItem(async ct => 
        { 
            using(container)
            {
                //Do stuff...
            } 
        }); 
    }
}
...