首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >构建用于自定义IConfigurationProvider的中间IConfigurationProvider

构建用于自定义IConfigurationProvider的中间IConfigurationProvider
EN

Stack Overflow用户
提问于 2022-11-03 06:54:51
回答 1查看 41关注 0票数 0

问题陈述:我有一个自定义IConfigurationProvider,它需要一个复杂的服务才能正常工作。这个复杂的服务自然会注册到应用程序IServiceProvider中。我希望将IServiceCollection/IServiceProvider设施与IConfigurationProvider结合使用,以避免这种复杂服务的手动更新,并重复使用本来可以在应用程序的DI容器构建部分的正常部分中编写的注册代码。

我已经找到了大量的文档,描述了在一个IServiceProvider中需要一个IConfigurationProvider的麻烦。这是最接近我的感觉是这篇文章的灵感来源。

这是我在一个高层次的方法

  1. 构建足够多的配置,以构造中间IServiceProvider
  2. 构建中间IServiceProvider
  3. 通过需要特殊服务的自定义IConfigurationProvider构建配置的其余部分,通过intermediateServiceProvider.GetRequiredService<T>();检索。
  4. 将注册,特别是单例对象从中间的IServiceCollection/IServiceProvider传输到最终的IServiceCollection/IServiceProvider。这将有助于避免在步骤5中重新注册内容,并有助于避免在最终的IServiceProvider中出现第二个单例实例。
  5. 使用步骤4中注入的配置注册最后一组服务以完成最终的IServiceProvider

#1,#2,#3,#5很简单。4号是我遇到路障的地方。我第一次尝试#4的尝试如下

代码语言:javascript
复制
    foreach (var sd in intermediateServiceCollection)
    {
        if (sd.Lifetime == ServiceLifetime.Singleton)
        {
            // Externally owned
            if (sd.ImplementationInstance != null)
            {
                finalServiceCollection.AddSingleton(sd.ServiceType, sd.ImplementationInstance);
            }
            // Provide a factory function to delegate to intermediate service provider
            else
            {
                finalServiceCollection.AddSingleton(sd.ServiceType, 
                    s => intermediateServiceProvider.GetRequiredService(sd.ServiceType));
            }
        }
        // Transient/scoped service descriptors can be forwarded along without issue
        else
        {
            finalServiceCollection.Add(sd);
        }
    }

如这里所记载的,不支持向工厂函数注册开放泛型类型.

在偶然发现这个限制之后,我的最新方法看起来如下:

代码语言:javascript
复制
    foreach (var sd in intermediateServiceCollection)
    {
        if (sd.Lifetime == ServiceLifetime.Singleton)
        {
            // Externally owned
            if (sd.ImplementationInstance != null)
            {
                finalServiceCollection.AddSingleton(sd.ServiceType, sd.ImplementationInstance);
            }
            // Provide a factory function to delegate to intermediate service provider
            else if (!sd.ServiceType.IsGenericType)
            {
                finalServiceCollection.AddSingleton(sd.ServiceType, 
                    s => intermediateServiceProvider.GetRequiredService(sd.ServiceType));
            }
            else
            {
                // Simply adding the service descriptor to the final service collection
                // opens the door for singleton instances to be created again
                //
                // In reality, this may be configurable to raise an exception to signal
                // to our developers they need to avoid registering open-generics in the 
                // bootstrapping portion of the app.  But, this may serve it's purpose
                // if you can live with multiple instances of a singleton.
                finalServiceCollection.Add(sd);
            }
        }
        // Transient/scoped service descriptors can be forwarded along without issue
        else
        {
            finalServiceCollection.Add(sd);
        }
    }

显然,我当前的实现并不完美,因为如果单例注册为开放泛型,它允许多个单例实例。但是,由于引导注册的限制是非开放的泛型类型,我可以“成功地”创建一个中间IServiceProvider,以便在IConfigurationProvider中使用,并将其转移到最终的IServiceProvider

  1. 谁能提供灵感,可以导致一个完整的实现#4,特别是围绕转让开放-通用注册?
  2. 假设这种方法是合理的,完全是胡说八道,我应该选择一个不同的模式来配置我的应用程序吗?
EN

回答 1

Stack Overflow用户

发布于 2022-11-03 07:08:20

如果您对中间服务提供者和最终服务提供者使用相同的配置提供程序,并且在最终服务提供者中需要与中间服务提供者中相同的服务,那么为什么不将中间提供程序的整个设置逻辑放入以目标生成器作为参数的方法中呢?然后,您可以首先调用它来设置您的中间提供程序,然后再调用它来设置您的最终提供程序。

在这种情况下,您不需要任何类型的反射,您可以使用所有可用的扩展助手类或自己的逻辑来设置配置提供程序。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74299048

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档