代码之家  ›  专栏  ›  技术社区  ›  szg1993

使残废NET Core IServiceProvider延迟注册

  •  0
  • szg1993  · 技术社区  · 2 年前

    我在用电脑。NET Core的ServiceCollection和ServiceProvider,用于在Xamarin Forms应用程序中进行依赖项注入。 我有一些单例实例,它们在构造函数/Init方法中做了很多运行缓慢的工作。 问题是,提供程序在第一次使用单例实例时会创建它们。我想重写这个功能,以便在注册这些类时对它们进行实例化。 例如,我的代码:

    services.AddSingleton<ILocalizationService, LocalizationService>();
    

    我尝试了以下方法,但如果类需要通过构造函数注入来传递实例(因为在这种情况下,需要手动传递实例),则该方法不起作用:

    services.AddSingleton<ILocalizationService>(new LocalizationService());
    

    我是否可以在没有任何解决方法的情况下以某种方式覆盖基本功能,比如在构建提供者时实例化所有这些功能?

    0 回复  |  直到 2 年前
        1
  •  2
  •   Steven    2 年前

    在MS.DI中没有办法覆盖或禁用该行为,据我所知,在中的任何其他DI容器中也没有此类功能。网络生态系统。

    但是,您可以做的是在服务提供商构建后立即解决该实例:

    provider.GetRequiredService<ILocalizationService>();
    

    这将构造该实例并运行其构造函数。

    一些DI容器提供者提供了一种“验证”机制,可以通过创建注册来测试所有注册。然而,在迪女士身上不存在这样的特征。

    但是,我建议移动初始化,而不是在类的构造函数中进行这种“缓慢运行的工作” 出来 并转换为一个 Init 某种方法,因为 Injection Constructors should be simple 除了存储其依赖项之外,不应该做任何工作。还要注意的是,如果您希望在将来使这个繁重的操作异步化,您肯定会运气不佳,因为这不可能使构造函数异步化(请参阅) this , this this ,以获取更多信息)。

    相反,将逻辑从构造函数移到 初始化 某种方法,例如:

    public class LocalizationService : ILocalizationService
    {
        private readonly IDependency1 dep1;
        private readonly IDependency2 dep2;
    
        public LocalizationService(IDependency1 dep1, IDependency2 dep2)
        {
            // Just pre-condition checks and storing dependencies.
            // Never use injected dependencies inside the constructor.
            this.dep1 = dep1 ?? throw new ArgumentNullException();
            this.dep2 = dep2 ?? throw new ArgumentNullException();
        }
    
        public void Init() => /* Do heavy initialization here */
    
        public Task InitAsync() => /* Or do async initialization here */
    }
    

    这可以让你解决问题 LocalizationService ServiceProvider 在startsup,并呼叫 初始化 方法:

    var service = provider.GetRequiredService<LocalizationService>();
    
    // Forces initialization at startup
    service.Init();
    // or
    await service.InitAsync();
    

    这需要 本地化服务 也要注册,就在它的旁边 ILocalizationService 接口:

    services.AddSingleton<LocalizationService>();
    services.AddSingleton<ILocalizationService>(c =>
        c.GetRequiredService<LocalizationService>>();
    

    最后一次注册有点偷偷摸摸,但它允许两次注册 iLocalization服务 本地化服务 指向完全相同的实例。