7

私はこのninjectバインドを使用しています:

kernel.Bind<ICurrentUser>().To<CurrentUser>()
    .InRequestScope()
    .WithConstructorArgument("principal", 
        context => (RolePrincipal HttpContext.Current.User);

サービス レイヤーのデコレーターの 1 つで、コンストラクターに "ICurrentUser currentUser" を追加するだけで、オブジェクトとその機能を取得できます。

この実装による欠点はありますか、それとも彼のアンビエント コンテキストを実装するためのより良い方法はありますか? リクエストごとに、ユーザー オブジェクトが作成されます (匿名ユーザーの場合も同様です)。

4

1 に答える 1

6

アンビエント コンテキストの使用は非常に限定されており、コンストラクター インジェクションを使用すると、通常は最良の結果が得られます。

たとえば、アンビエント コンテキストを使用すると単体テストがどのように複雑になるかを考えてみてください。アンビエント コンテキストを使用すると、通常、テスト セットアップでそのコンテキストを変更し、テスト ティアダウンで削除する必要があることを意味します。ただし、単体テスト フレームワークは通常、複数のスレッドで一連のテストを実行します (たとえば、MSTest が行うように)。このように静的変数を使用すると、テストが互いに影響を与えることになります。

[更新] この理由やその他の理由から、書籍Dependency Injection in .NET, Second EditionAmbient Contextをアンチパターンと呼んでいます。

これはすべて、コンストラクターにすべての依存関係を注入することで簡単に克服できます。あるいは別の視点から見てみましょう。クラスがこのサービスに依存している場合、コンストラクターに注入してみませんか?

私が心配しているのは、明示的なコンストラクター引数の登録だけです。これにより、構成がより脆弱になります。あなたCurrentUserは a に依存しているのでRolePrincipal、これはそれを直接登録することを正当化します:

kernel.Bind<ICurrentUser>().To<CurrentUser>().InRequestScope();

kernel.Bind<RolePrincipal>()
    .ToMethod(c => (RolePrincipal)HttpContext.Current.User);
于 2012-10-22T10:18:00.770 に答える