当为使用AddScoped或AddSingleton添加的服务使用DI时,服务是否需要实现IDisposable (即使它不使用任何非托管资源,如文件)?
下面是来自Microsoft Docs的示例:
// Services that implement IDisposable:
public class Service1 : IDisposable {}
public class Service2 : IDisposable {}
public class Service3 : IDisposable {}
public interface ISomeService {}
public class SomeServiceImplementation : ISomeService, IDisposable {}
public void ConfigureServices(IServiceCollection services)
{
// The container creates the following instances and disposes them automatically:
services.AddScoped<Service1>();
services.AddSingleton<Service2>();
services.AddSingleton<ISomeService>(sp => new SomeServiceImplementation());
// The container doesn't create the following instances, so it doesn't dispose of
// the instances automatically:
services.AddSingleton<Service3>(new Service3());
services.AddSingleton(new Service3());
}如果我有这样的代码,会发生什么:
public class Service0 // (doesn't implement Disposable)
services.AddScoped<Service0>(); // what happens to it when request scope ends? Does it stay on the heap?
services.AddSingleton<Service0>(); // it lives till application dies
services.AddSingleton(new Service0()); // ??
services.AddSingleton<IConfigureOptions<Service0>>((ctx) =>
{
return new ConfigureNamedOptions<Service0>(null, (config) =>
{
// Do something here -- in debug mode it is executing this logic for each request
}} // it is returning "new Service0" when a request is made. Does it mean for each request it returns new object and keeps in heap memory or returns same previously created object?发布于 2019-08-11 17:42:39
确实需要服务实现IDisposable(即使它没有使用任何非托管资源,如文件)
通常不会,因为IDisposable的主要目的是允许释放非托管资源。然而,实现IDisposable还有一个额外的原因。Dispose()方法有时用作完成在构造函数中启动的操作的钩子。例如,构造函数开始持续时间测量,而Dispose()停止测量并将持续时间报告给某个监控机制。
关于IDisposable的一些背景知识
如果一个对象没有实现IDisposable,并不意味着它停留在堆中。事实上,GC甚至不知道IDisposable是什么。这个接口只是一个模式。但是,编译器知道IDisposable,并且在using语句作用域的末尾发出对Dispose()的调用。
此外,在许多情况下,基础架构层或库(如ASP.NET核心中的DI )会检查对象是否实现了IDisposable,如果实现了,则对其调用Dispose()。
因此,对象实现IDisposable本身并不能保证Dispose()会在GC之前被调用。这取决于对象的用户。为了在GC之前实际确保Dispose(),一次性模式的完整实现包括从“析构函数”调用Dispose()。
当请求作用域结束时,它会发生什么?会留在堆里?当请求作用域结束时,它会发生什么?
AddScoped<Service0>():在请求的末尾,对对象的引用被“遗忘”( GC可以随时删除它)。就在忘记引用之前,检查对象是否实现了IDisposable,如果实现了,将在web主机生命周期结束时在it.AddSingleton<Service0>():上调用Dispose(),对对象的引用被“忘记”( GC可以随时删除它)。就在忘记引用之前,检查对象是否实现了IDisposable,如果实现了,将在web主机生命周期结束时在it.AddSingleton(new Service0()):上调用Dispose(),对对象的引用被“忘记”( GC可以随时删除它)。但是因为这个对象是从外部提供的,而不是由DI实例化的,所以不会检查它是否有IDisposable,也不会调用Dispose。发布于 2019-08-11 16:36:32
IDisposable只是一个接口,它为实现者类提供了对对象销毁进行清理的机会,它本身并不做任何事情。DI将销毁实例取决于它们的生命周期,如作用域、瞬态、单例,对象在销毁后是否在堆上存在是Gorbagge收集器的职责。如果您在Singleton中定义了一个新实例,则该对象将随Singleton实例一起销毁,且由于Singleton的生命周期一直到应用程序生命周期的末尾,因此它将遵循其父实例的生命周期,除非您在其中执行一些非托管操作。
https://stackoverflow.com/questions/57447881
复制相似问题