0

メソッドの完了時間を記録するために Ninject.Extensions.Interception.DynamixProxy を使用してインターセプターを作成しようとしています。

シングルスレッド環境では、次のように機能します。

public class TimingInterceptor : SimpleInterceptor
{
    readonly Stopwatch _stopwatch = new Stopwatch();
    private bool _isStarted;


    protected override void BeforeInvoke(IInvocation invocation)
    {
        _stopwatch.Restart();
        if (_isStarted) throw new Exception("resetting stopwatch for another invocation => false results");
        _isStarted = true;
        invocation.Proceed();
    }

    protected override void AfterInvoke(IInvocation invocation)
    {
        Debug.WriteLine(_stopwatch.Elapsed);
        _isStarted = false;
    }
}

ただし、マルチスレッドのシナリオでは、StopWatch が呼び出し間で共有されるため、これは機能しません。呼び出し間で共有されないように、StopWatch のインスタンスを BeforeInvoke から AfterInvoke に渡す方法は?

4

1 に答える 1

3

各スレッドは独自のオブジェクト グラフを取得する必要があるため、これはマルチスレッド アプリケーションで問題なく機能するはずです。したがって、タスクの処理を開始するときは、新しいグラフの解決から開始し、グラフをスレッドからスレッドに渡してはなりません。これにより、スレッドセーフ (およびスレッドセーフでないもの) に関する知識を、アプリケーション内のすべてを接続する 1 つの場所 (コンポジション ルート) に集中させることができます。

このように作業する場合、このインターセプターを使用してシングルトンである (およびスレッド間で使用される) クラスを監視する場合、各スレッドは引き続き独自のインターセプターを取得します (一時的なものとして登録されている場合)。新しいインターセプター (同じ「インターセプトされた」インスタンスを再利用したとしても)。

ただし、これは、このインターセプトされたオブジェクトを別のシングルトンにインジェクトすると、再び問題が発生するため、このインターセプトされたコンポーネントをどこにインジェクトするかに非常に注意する必要があることを意味します。この特定の種類の「トラブル」は、ライフスタイルのミスマッチとも呼ばれる拘束依存症と呼ばれます。誤ってコンテナの構成を誤って、これによって問題が発生することは非常に簡単です。残念ながら、Ninject にはこれについて警告する機能がありません。

ただし、デコレーターを使用するとすべてを単一のメソッドに保持できるため、インターセプターの代わりにデコレーターを使用し始めると、問題がなくなることに注意してください。これは、スレッド化の問題を引き起こすことなく、デコレーターでさえシングルトンにできることを意味します。例:

// Timing cross-cutting concern for command handlers
public class TimingCommandHandlerDecorator<TCommand> : ICommandHandler<TCommand>
{
    private readonly ICommandHandler<TCommand> decoratee;

    public TimingCommandHandlerDecorator(ICommandHandler<TCommand> decoratee)
    {
        this.decoratee = decoratee;
    }

    public void Handle(TCommand command)
    {
        var stopwatch = Stopwatch.StartNew();
        this.decoratee.Handle(command);
        Debug.WriteLine(stopwatch.Elapsed);
    }
}

もちろん、多くの場合、デコレータの使用は、SOLID原則を設計に正しく適用した場合にのみ可能です。これは、多くの場合、デコレータをシステム内の広範囲のクラスに適用できるようにするために、いくつかの明確な汎用抽象化が必要になるためです。レガシー コード ベースで効率的にデコレータを使用するのは気が遠くなるかもしれません。

于 2014-10-18T10:20:27.837 に答える