是否“安全”缓存IServiceProvider以使应用程序的生命周期? [英] Is it "safe" to cache IServiceProvider for an app's lifetime?
问题描述
我的 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屋!