Is it “safe” to cache IServiceProvider for an app's lifetime?

后端 未结 2 1650
余生分开走
余生分开走 2021-01-16 09:08

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

相关标签:
2条回答
  • 2021-01-16 09:28

    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.

    0 讨论(0)
  • 2021-01-16 09:30

    Addendum to @CodeCaster's excellent solution.

    It's important to change Func<Dependency> to Func<Owned<Dependency>>. Otherwise the container won't return new instances each time, even though you're using a delegate factory.

    Probably has something to do with the fact that a long-lived component (singleton) depends on a short-lived component (per-transaction). The Func<> prevents the captive dependency bug, but for the factory to also give you new instances each time, it needs to be Owned<>.

    I don't understand why, and it seems counter-intuitive, but that's how it works.

    0 讨论(0)
提交回复
热议问题