是否“安全”缓存IServiceProvider以使应用程序的生命周期? [英] Is it "safe" to cache IServiceProvider for an app's lifetime?

查看:93
本文介绍了是否“安全”缓存IServiceProvider以使应用程序的生命周期?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我的 Foo 类有一个依赖(通过构造函数注入)。

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

但库缓存code> Foo 实例在应用程序的持续时间(这在我的控制之外)。这意味着它也缓存依赖。而且该依赖不能被缓存,因为它是一个应该被限定的EF上下文。



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

  public class Foo {

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

//等

public void bar(){
var context = _sp.GetService< IMyContext>();
//使用它
}

}

但是与以前一样, c $ c> IServiceProvider 实例将在应用程序的一生中被缓存。



这是安全?是否有负面影响我应该知道?

解决方案

你不想在任何地方注入你的IoC容器。这是一个糟糕的做法,允许马虎编码,并使单元测试更难,其他许多原因。



而是引入一个可以注入的工厂,并根据需要创建一个上下文:

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

public class DbContextFactory< TContext> :IDbContextFactory< TContext>
其中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())
{
//使用你刚刚实例化的上下文
}
}
}

任何体面的依赖注入框架可以解析 DbContextFactory Func< TContext> 参数,并传递一个创建一个每个请求的实例。


I'm using ASP.NET Core, and its builtin DI container. I'm using a third-party library (NLog) which I can't change.

My Foo class has a dependency (by constructor injection).

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

However the library caches the Foo instance for the duration of the app (that's outside my control). That means it also caches the dependency. And that dependency must not be cached, because it's an EF context which should be scoped.

An alternative is to inject IServiceProvider, and then to create instances myself.

public class Foo {

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

  // etc.

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

}

But as before, that IServiceProvider instance would be cached for the lifetime of the app.

Is that "safe"? Are there negative repercussions I should know about?

解决方案

You don't want to inject your IoC container anywhere. That's a bad practice that allows for sloppy coding, and makes unit testing harder, amongst many other reasons.

Instead introduce a factory that can be injected and create a context on demand:

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();
    }
}

Now if you inject this into your 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
        }
    }
}

Any decent dependency injection framework can resolve the Func<TContext> parameter of the DbContextFactory, and pass a func there that creates an instance per request.

这篇关于是否“安全”缓存IServiceProvider以使应用程序的生命周期?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆