在应用程序的生命周期内缓存 IServiceProvider 是否“安全”?

2023-12-04

我正在使用 ASP.NET Core 及其内置 DI 容器。我正在使用无法更改的第三方库(NLog)。

My Foo类具有依赖关系(通过构造函数注入)。

public class Foo {
  private readonly IMyContext _context;
  public Foo(IMyContext context) { _context = context; }
  // etc.
}

然而该库缓存了Foo实例在应用程序的持续时间内(这超出了我的控制范围)。这意味着它还缓存依赖项。并且该依赖项不得被缓存,因为它是一个应该限定范围的 EF 上下文。

另一种方法是注入IServiceProvider,然后自己创建实例。

public class Foo {

  private readonly IServiceProvider _sp;
  public Foo(IServiceProvider sp) { _sp = sp; }

  // etc.

  public void bar() {
    var context = _sp.GetService<IMyContext>();
    // use it
  }

}

但和之前一样,那IServiceProvider实例将在应用程序的生命周期内被缓存。

这样“安全”吗?我应该了解哪些负面影响吗?


您不想将 IoC 容器注入到任何地方。这是一种不好的做法,它会导致草率的编码,并使单元测试变得更加困难,还有其他许多原因。

相反,引入一个可以注入的工厂并按需创建上下文:

public interface IDbContextFactory<TContext>
{
    TContext Create();
}

public class DbContextFactory<TContext> : IDbContextFactory<TContext>
    where TContext : DbContext
{
    private readonly Func<TContext> _contextCreator;

    public DbContextFactory(Func<TContext> contextCreator)
    {
        _contextCreator = contextCreator;
    }

    public TContext Create()
    {
        return _contextCreator();
    }
}

现在如果你将其注入你的Foo:

public class Foo 
{
    private readonly IDbContextFactory<MyContext> _contextFactory;
    public Foo(IDbContextFactory<MyContext> contextFactory)
    { 
        _contextFactory = contextFactory;
    }

    public void bar() {
    {
        using (var context = _contextFactory.Create())
        {
            // use your freshly instantiated context
        }
    }
}

任何像样的依赖注入框架都可以解决Func<TContext>的参数DbContextFactory,并传递一个 func 来为每个请求创建一个实例。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在应用程序的生命周期内缓存 IServiceProvider 是否“安全”? 的相关文章

随机推荐