.NET Core 依赖注入 - 如何处理手动创建的实例?

Posted

技术标签:

【中文标题】.NET Core 依赖注入 - 如何处理手动创建的实例?【英文标题】:.NET Core dependency injection - How to dispose manually created instances? 【发布时间】:2022-01-01 14:54:21 【问题描述】:

像下面的代码一样,我必须使用工厂/函数注册容器的方式,因为我不知道“userId”属性的值提前但只在运行时。这是有效的,功能方面没有问题。

container.AddSingleton<IBLogic, BLogic>(); //explicitly registration 'BLogic' service object

container.AddSingleton<Func<string, IDBCache>>
        (p=> (userId) => new IDBCache(userId, p.GetService<IBLogic>()));

由于这里我使用的是“new IDBCache”,根据link 框架不会自动处理服务。

问题

    要让框架自动处理服务,有什么办法吗?

    container.AddSingleton> (p=> (userId) => new IDBCache(userId, p.GetService()));

由于我只是注册 func/factory 的定义而不是服务对象(如“BLogic”),AddSingleton 是否比使用下面的“AddScoped”或“AddTransisent”有任何优势?

container.AddTransisent<Func<string, IDBCache>>
        (p=> (userId) => new IDBCache(userId, p.GetService<IBLogic>()));

【问题讨论】:

【参考方案1】:

对此没有简单的解决方法。 MS.DI 不包含您可以调用的RegisterForDisposal 方法。您将必须创建一个单独的包装器来实现一次性的,您可以将创建的实例挂接到该包装器上。例如:

services.AddSingleton<IBLogic, BLogic>();

services.AddScoped<DisposeWrapper>();
services.AddScoped<Func<string, IDBCache>>(p => (userId) =>

    var cache = new IDBCache(userId, p.GetRequiredService<IBLogic>());
    p.GetRequiredService<DisposeWrapper>().Add(cache);
    return cache;
);

DisposeWrapper 如下所示:

public sealed class DisposeWrapper : List<IDisposable>, IDisposable

    public void Dispose()
    
        // Dispose in reverse order as creation.
        for (int i = this.Count - 1; i >= 0; i--) this[i].Dispose();
    

然而,这样的实现带有相当多的警告,因为DisposeWrapper 应该使用与您想要缓存IDBCache 相同的范围注册。这就是为什么在上面的示例中,我将DisposeWrapper 和工厂都注册为Scoped

DisposeWrapper 注册为单例,意味着创建的IDBCache 实例只会在应用程序结束时被释放。如果您在应用程序的生命周期内创建了许多IDBCache 实例,则会导致内存泄漏。在您的场景中,这不太可能是个好主意。

另一方面,将两者都注册为瞬态仍然可能(令人困惑地)导致内存泄漏,因为工厂可能被注入到单例中,导致它(及其DisposeWrapper)变成Captive Dependency。

由于这种设计的复杂性,我建议更改您的设计。

如果你以runtime data isn't required during object construction的方式重新设计IDBCache,你可以允许IDBCache在没有工厂的容器中注册(例如AddTransient&lt;IDBCache&gt;()),这使得它可以被容器正常处理。这将消除上述所有复杂性。

【讨论】:

以上是关于.NET Core 依赖注入 - 如何处理手动创建的实例?的主要内容,如果未能解决你的问题,请参考以下文章

如何处理未满足的对等依赖?

MediatR CQRS - 如何处理不存在的资源(asp.net core web api)

ASP.NET Core MVC 502 bad gateway 超时如何处理

ASP.NET Core管道深度剖析:管道是如何处理HTTP请求的?

ASP.NET Core Web API - 如何处理 URL 查询字符串中的“null”与“undefined”?

如何处理高度和中等明显的依赖问题?