问题陈述:我有一个自定义IConfigurationProvider,它需要一个复杂的服务才能正常工作。这个复杂的服务自然会注册到应用程序IServiceProvider中。我希望将IServiceCollection/IServiceProvider设施与IConfigurationProvider结合使用,以避免这种复杂服务的手动更新,并重复使用本来可以在应用程序的DI容器构建部分的正常部分中编写的注册代码。
我已经找到了大量的文档,描述了在一个IServiceProvider中需要一个IConfigurationProvider的麻烦。这是最接近我的感觉是这篇文章的灵感来源。
这是我在一个高层次的方法
IServiceProviderIServiceProviderIConfigurationProvider构建配置的其余部分,通过intermediateServiceProvider.GetRequiredService<T>();检索。IServiceCollection/IServiceProvider传输到最终的IServiceCollection/IServiceProvider。这将有助于避免在步骤5中重新注册内容,并有助于避免在最终的IServiceProvider中出现第二个单例实例。IServiceProvider。#1,#2,#3,#5很简单。4号是我遇到路障的地方。我第一次尝试#4的尝试如下
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);
}
}如这里所记载的,不支持向工厂函数注册开放泛型类型.
在偶然发现这个限制之后,我的最新方法看起来如下:
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。
发布于 2022-11-03 07:08:20
如果您对中间服务提供者和最终服务提供者使用相同的配置提供程序,并且在最终服务提供者中需要与中间服务提供者中相同的服务,那么为什么不将中间提供程序的整个设置逻辑放入以目标生成器作为参数的方法中呢?然后,您可以首先调用它来设置您的中间提供程序,然后再调用它来设置您的最终提供程序。
在这种情况下,您不需要任何类型的反射,您可以使用所有可用的扩展助手类或自己的逻辑来设置配置提供程序。
https://stackoverflow.com/questions/74299048
复制相似问题