4

いくつかのログ機能を子クラスに公開する基本コントローラー クラスがあります。このロギング依存関係は、コンストラクターによって注入されます。単純化されたコードを提供するために、これはすべてがどのように見えるかです:

public abstract class LogControllerBase : Controller
{
    private readonly ILogger logger = null;

    protected LogControllerBase(ILogger logger)
    {
        this.logger = logger;
    }
}

私の子コントローラーにも独自の依存関係があるため、次のようになります。

public class SomeController : LogControllerBase
{
    private readonly IService service = null;

    [ImportingConstructor]
    public SomeController(ILogger logger, IService service)
        : base(logger)
    {
        this.service = service;
    }
}

これらのコンストラクターを使用して、単体テストで依存性注入を簡単に実行できるようにしていますが、本番環境では、すべての構成は MEF によって行われます (する必要があります)。MEF を使用してコントローラーをインスタンス化するカスタム コントローラー ファクトリ クラスを使用しています。

要約すると:

  1. 独自の依存関係を持つ基本抽象コントローラー クラスがあります。
  2. インポートを使用して MEF によって注入されたパラメーターを取得する子孫コントローラーがあります (つまり、依存関係と基本クラスの依存関係です)。
  3. 単体テストは MEF を使用しないため、コンストラクター パラメーターにモックが挿入されます。

問題

これはすべて私に水を与えますが、MEF の考え方は異なります。このコードをコンパイルして実行すると、次の例外が発生します。

GetExportedValue は、前提条件のインポート 'SomeController..ctor (Parameter="logger", ContractName="ILogger")' が設定される前に呼び出すことはできません。

コンストラクターのパラメーターとして使用されるすべてのインターフェイス型には属性がInheritedExport設定されており、具体的な実装も含まれているため、期待どおりに機能するはずです。

同じではない作業代替

これらのプライベートフィールドで直接インポートを行うことで別のアプローチを試みると、すべてうまくいくようです。

public abstract class LogControllerBase : ControllerBase
{
    [Import]
    private ILogger logger = null;

    protected LogControllerBase() { }
}

public class SomeController : LogControllerBase
{
    [Import]
    private IService service = null;

    public SomeController() { }
}

したがって、これは機能しますが、同じではありません...依存関係の挿入のためにここにコンストラクターを追加できますが、2セットのコンストラクターがあり、ユニットテストを行うときに、依存関係がないためもちろん間違っているパラメーターなしのコンストラクターを使用する可能性があります設定されます。本物でもモックでもない。

質問

依存性注入コンストラクターを として設定することにより、コンストラクターに具体的な実装を注入することにより、MEF がコントローラーを作成するように説得するにはどうすればよいImportingConstructorですか?

4

1 に答える 1

0

MEFコンテナはデフォルトでスレッドセーフとして構築されていないため、これはスレッド化に関連している可能性があります。コンテナーのコンストラクターで、スレッドセーフを有効にしてみてください。

var container = new CompositionContainer(catalog, true);
于 2012-07-13T10:21:52.480 に答える