如果我通过
ServiceCollection
注册所有服务,那么我就能够在重用此集合的不同 DI 实现之间进行切换:Autofac
、Simple Injector
或 Microsoft.Extensions.DependencyInjection
。
但是当我尝试通过
ServiceCollection
重用 Autofac
时,它会处置 外部 服务。这是一个问题...
一些外部服务:
namespace DI_Sandbox.Models
{
public interface IMessageWriter
{
void Write(string message);
}
public class ConsoleMessageWriter: IMessageWriter, IDisposable
{
public void Dispose()
{
Console.WriteLine($"The {GetType().Name} instanse is disposed.");
}
public void Write(string message)
{
Console.WriteLine(message);
}
}
}
可以防止直接在Autofac中注册的处置服务(即不使用
ServiceCollection
):
using Autofac;
using Autofac.Extensions.DependencyInjection;
using DI_Sandbox.Models;
using Microsoft.Extensions.DependencyInjection;
var externalService = new ConsoleMessageWriter();
var builder = new ContainerBuilder();
builder.RegisterInstance<IMessageWriter>(externalService).ExternallyOwned();
var container = builder.Build();
using(var serviceProvider = new AutofacServiceProvider(container))
{
var messageWriter = serviceProvider.GetRequiredService<IMessageWriter>();
messageWriter.Write("Hello DI!");
}
Console.Write("THE END");
预期输出:
Hello DI!
THE END
我尝试在
Autofac
中重用服务是通过ServiceCollection
注册的:
using Autofac;
using Autofac.Extensions.DependencyInjection;
using DI_Sandbox.Models;
using Microsoft.Extensions.DependencyInjection;
var externalService = new ConsoleMessageWriter();
var services = new ServiceCollection();
services.AddSingleton<IMessageWriter>(externalService);
var builder = new ContainerBuilder();
builder.Populate(services);
var container = builder.Build();
using(var serviceProvider = new AutofacServiceProvider(container))
{
var messageWriter = serviceProvider.GetRequiredService<IMessageWriter>();
messageWriter.Write("Hello DI!");
}
Console.Write("THE END");
结果:
Hello DI!
The ConsoleMessageWriter instanse is disposed.
THE END
如何防止处置服务通过
ServiceCollection
注册并被Autofac
重复使用?
本期描述了您遇到的问题:
显然,autofac 适配器在从
IServiceCollection
加载服务注册时不会尝试区分单例注册,并且最终不会对它们应用 ExternallyOwned
标志或其他内容。
作者建议采用以下解决方法:直接注册到 Autofac: https://github.com/autofac/Autofac.Extensions.DependencyInjection/issues/15#issuecomment-314425353
现在的解决方法是直接向 Autofac 注册,而不是适配器。
就我个人而言,我认为这个解决方法很糟糕,而且 Autofac 的实现只是有问题,但他们继续解决了这个问题。显然,从他们的角度来看,这是设计使然。
我知道这有点偏离主题,但我真诚地建议在这里放弃 Autofac,并坚持使用
Microsoft.Extensions.DependencyInjection
(如果可以的话)。