2017-03-10 4 views
1

私はASP.NET Coreとその組み込みDIコンテナを使用しています。私は変更できないサードパーティライブラリ(NLog)を使用しています。IServiceProviderをキャッシュしてアプリの生存期間を確保するのは安全ですか?

私のFooクラスには(コンストラクタインジェクションによって)依存関係があります。ライブラリが(それは私のコントロール外です)アプリの期間Fooインスタンスをキャッシュしかし

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

。つまり、依存関係もキャッシュされます。そして、その依存関係は、スコープされるべき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インスタンスは、アプリケーションの寿命のためにキャッシュされるだろう。

「安全」ですか?私が知っておくべき悪影響はありますか?

答えて

4

あなたはどこにでもIoCコンテナを注入したくありません。これは悪いコーディングを可能にする悪い習慣であり、他の多くの理由の中でユニットテストを難しくしています。

代わりに注入し、オンデマンドでコンテキストを作成することができます工場紹介:あなたはFooにこれを注入した場合今

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

を:

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を渡します。

+0

これは素晴らしいです。私はそれを実装しましたが、動作させることができませんでした。組み込みのDIコンテナ[デリゲートをサポートしていません](http://stackoverflow.com/questions/35736070/how-to-use-funct-in-built-in-dependency-injection)をこのようにします。どのように不幸な、この答えは素晴らしいだろう。これは一般的なケースでは優れていますが、私にとってはうまくいきません。私は答えとしてマークするかどうかにかかわらず、他の人が私の環境のアドバイスを持っているかもしれないので、私は矛盾しています – grokky

+0

@grokky問題はありません。それはAutofacで動作します。例えば、それがオプションかどうかはわかりません。あなたは答えとしてマークする必要はありません、おそらく他の誰かが考えを持っています。 – CodeCaster

+0

工場を注入するのは解決策ですが、依存関係が 'IDisposable'かどうかは必ずしも分かりません。なぜなら、* Autofac *は' Owned 'を導入しているからです(私の知る限り、ネットフレームワーク :()。そのような場合、私のサービスはしばしば 'Func >' –

0

@ CodeCasterの優れた解決策の補足です。

Func<Dependency>Func<Owned<Dependency>>に変更することが重要です。それ以外の場合は、デリゲートファクトリを使用していても、コンテナは毎回新しいインスタンスを返しません。

おそらく、長命のコンポーネント(シングルトン)が短命のコンポーネント(トランザクションごと)に依存しているという事実と関係していると思われます。 Func<>は、キャプティブ依存のバグを防ぎますが、毎回新しいインスタンスを提供する工場では、Owned<>である必要があります。

私はなぜそれが理解できないのでしょうか、直感的ではないようですが、それはどのように動作するのですか?

関連する問題