上下文
我有5个服务:
Service1 (no depends.)
Service2 (no depends.)
Service3 (Service1, Service2, IServiceProvider) : ISpecialService
Service4 (Service1, Service2, Service3) : ISpecialService
Service5 (Service1, Service3, Service4) : ISpecialService
它们都是每应用生命中一个实例的Singleton服务。通常,您只需将它们添加为单例和BuildServiceProvider。但是,在我的情况下,所有ISpecialService
都需要两次注册:作为工厂和自己的直接类型,因此通过ctor直接注入:
public SomeOtherService(Service3 s3, Service4 s4) { }
仍然有效。 问题是,如果我只是正常注册它们:
.AddSingleton<ISpecialService, Service3>()
.AddSingleton<Service3, Service3>()
这将给我2个不同的Service3实例,这些实例将使单例失败。要拥有一个实例,在注册Service3并将实例作为参数提供给AddSingleton方法之前,我需要手动创建实例。
var s3 = new Service3(s1, s2, ?isp?);
.AddSingleton<ISpecialService, Service3>(s3) // same instance for contract work
.AddSingleton<Service3, Service3>(s3) // same instance
...
.BuildProvider()
这是一个问题,因为Service3
具有IServiceProvider
作为依赖项。通常,它是由DI处理的,但是在这种情况下,我需要注册它的 SINGLE 实例两次,我似乎找不到找到向Service3提供完整ISP实例的方法。实例。如果我构建ISP,我将无法再添加任何服务,这是一个死胡同,因为Servcie3稍后将需要作为循环依赖项的变通方法,而中间没有99个中间的空无意义的服务:
private readonly Service1 service1;
private readonly Service2 service2;
private Service4 service4;
private readonly IServiceProvider ISP;
public Service3 (Service1 s1, Service2 s2, IServiceProvider isp)
{
//assign depenencies
}
public Startup()
{
//workaround for circular dependency
service4 = ISP.GetServic<Service4>()
}
我需要将Service 3,4,5注册为接口类型的原因是我希望他们以后做的一些常见的联系工作:
foreach (var srv in ISP.GetService<ISpecialService>())
{
serv.Startup();
}
有什么想法可以解决这个问题吗?
答案 0 :(得分:0)
您可以执行以下操作:
public class Answer
{
public Answer()
{
// Have your service collection, register everything you need
// before having to add your custom service.
var collection = new ServiceCollection()
.AddSingleton<ISpecialService, Service3>();
//---
// Build a disposable container without your custom service
var provider = collection.BuildServiceProvider();
// Use that container to call your instance of your custom service
var serviceInstanceWithDI = provider.GetService<ISpecialService>();
// This way the service is pulled from the DI container with all of its
// dependencies injected, assuming they are registered beforehand
// Add it back to the collection with its dependencies already injected
collection.AddSingleton<Service3, Service3>(serviceInstanceWithDI);
// Now you can build the IServiceProvider and have your 2 instances registered.
var serviceProvider = collection.BuildServiceProvider();
}
}