猿问

当 ASP.NET Core 应用程序关闭时,如何正确且安全地处理在容器中注册的单例实例

我正在寻找有关如何在我的 ASP.NET Core 2.0 应用程序关闭时正确和安全地处理已注册的单例实例的指导。


根据以下文档,如果我注册一个单例实例(通过 IServiceCollection),容器将永远不会尝试创建一个实例(它也不会处理该实例),因此当应用程序关闭时,我只能自己处理这些实例.


https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.0(2.1有相同的指导)


我附上了一些伪代码来说明我想要实现的目标。


注意我必须维护对 IServiceCollection 的引用,因为提供给 OnShutDown 方法的 IServiceProvider 是一个简单的服务定位器,并且不能执行复杂的查询。


当应用程序关闭时,我想要一种通用的方法来确保所有的单例实例都被处理掉。我可以直接维护对所有这些单例实例的引用,但这不能很好地扩展。


我最初使用工厂方法来确保 DI 管理我的对象的生命周期,但是,工厂方法的执行发生在运行时处理请求的管道中,这意味着如果它抛出异常,则响应为 500 InternalServerError并记录了一个错误。通过直接创建对象,我正在努力获得更快的反馈,以便启动时的错误导致部署期间的自动回滚。这对我来说似乎并不合理,但同时我不会滥用 DI。


有没有人对我如何更优雅地实现这一目标有任何建议?


namespace MyApp

{

    public class Program

    {

        private static readonly CancellationTokenSource cts = new CancellationTokenSource();


        protected Program()

        {

        }


        public static int Main(string[] args)

        {

            Console.CancelKeyPress += OnExit;

            return RunHost(configuration).GetAwaiter().GetResult();

        }


        protected static void OnExit(object sender, ConsoleCancelEventArgs args)

        {

            cts.Cancel();

        }


        static async Task<int> RunHost()

        {

            await new WebHostBuilder()

                .UseStartup<Startup>()

                .Build()

                .RunAsync(cts.Token);

        }

    }


    public class Startup

    {

        public Startup()

        {

        }


        public void ConfigureServices(IServiceCollection services)

        {

            // This has been massively simplified, the actual objects I construct on the commercial app I work on are

            // lot more complicated to construct and span several lines of code.

            services.AddSingleton<IDisposableSingletonInstance>(new DisposableSingletonInstance());


            // See the OnShutdown method below

            this.serviceCollection = services;

        }


汪汪一只猫
浏览 306回答 3
3回答

慕姐4208626

那是不准确的。单身设置在应用程序关闭,虽然这有点不实际所有的相关的,因为该过程停止时,一切都与它去反正。一般的经验法则是,在使用 DI 时,您应该一直使用 DI,这意味着您几乎永远不会在任何地方自行处理。这一切都与所有权有关。当您自己添加新东西时,您还要负责处理它。然而,当使用 DI 时,容器是新事物,因此,容器并且只有容器应该处理这些东西。

慕村9548890

两个带走点是这样的:始终努力让容器管理对象的生命周期,以便在应用程序关闭时容器将自动处理所有对象。在容器中注册的对象使用之前,在应用程序启动时验证所有配置。这允许您的应用程序快速失败并保护您的 DI 在创建新对象时不会抛出异常。
随时随地看视频慕课网APP
我要回答