0

いくつかのメソッドの前後に呼び出したいロギング ロジックがあります。各メソッドは、異なる数/タイプのパラメーターを受け入れます。各メソッドを呼び出すときにロギング ロジックを複製する必要がないように設定しようとしています。いくつかのデリゲートを作成することで、重複の量を減らすことができました。使用されるパラメーターの数/タイプごとにデリゲートを作成しました。各デリゲートを受け入れてログを記録するメソッドがあります。ただし、私はまだ約 6 つの異なるデリゲートを持っているので、ロジックはそれらの 6 つに対して複製されます。

これを変更する必要はないと思うので、パラメーターの数に関係なく、ログを記録してメソッドを呼び出すメソッドが 1 つあります。しかし、私はそれを理解することができませんでした。

以下は、重複しないようにしようとしているデリゲートの 1 つとロジックの例です。

    public delegate void LineOfBusinessHandler(DateTime runDate, LineOfBusinessCode lineOfBusinessCode);

    public void Run(DateTime runDate, ProcessCode process, LineOfBusinessCode lineOfBusinessCode, LineOfBusinessHandler del)
    {
        this.ProcessManager.AddToBatchLog(process.ToString(), ProcessStatus.Started.ToString(), null, runDate);


        try
        {
            del(runDate, lineOfBusinessCode);
            this.ProcessManager.AddToBatchLog(process.ToString(), ProcessStatus.Finished.ToString(), null, runDate);
        }
        catch (Exception e)
        {
            int errorId = SystemManager.LogError(e, process.ToString());
            this.ProcessManager.AddToBatchLog(process.ToString(), ProcessStatus.Errored.ToString(), errorId, runDate);
        }
    }
4

4 に答える 4

1

これは、あなたが探している範囲や機能を超えている可能性があることを認識しています。object[]しかし、型安全性を失わずに (つまり、 で引数を渡さないで)、さまざまなメソッド呼び出しで再利用したい一般的なログ ロジックがある場合は、インターセプトを使用します。AOP、依存性注入、または類似のものを提供できるフレームワークが必要です (最初に独自に作成することはお勧めしません!)。それらは通常傍受に対処できます。

たとえば、Ninject で使用するロギング インターセプターがあります。

public void Intercept(IInvocation invocation)
{
    var logger = LoggerFactory.GetLogger(invocation.Request.Method.DeclaringType);
    var debug = !invocation.Request.Method.IsSpecialName && logger.IsDebugEnabled;
    if (debug)
        logger.Debug(invocation.Request.Method.Name);
    try
    {
        invocation.Proceed();
        if (debug)
            logger.Debug(invocation.Request.Method.Name + " FINISH");
    }
    catch (Exception)
    {
        logger.Error(invocation.Request.Method.Name + " ERROR");
        throw;
    }

}

次に、Ninject を使用してオブジェクトを作成し (わからない場合は、いくつかのチュートリアルを参照してください)、傍受を追加します。たとえば、上記の方法Kernel.Bind<MyTypeToLog>().ToSelf().Intercept().With<LoggingInterceptor>();LoggingInterceptor実装する場所...IInterceptor

詳細なヘルプが必要な場合は、言ってください。

EDIT:私の例ではこれが表示されていないことに気付きましたが、呼び出しの引数(オブジェクトコレクションとして)にもアクセスできます!!

于 2012-11-05T15:27:15.137 に答える
0

C#言語には、メタプログラミング用の構文はありません。リフレクションを使用する必要があります。確かに、任意のメソッド/デリゲートを反映してパラメータータイプを決定し、パラメーターをログに記録して元のメソッドを呼び出すメソッドを構築し、この新しいラッパーメソッドをコンパイルして、元のメソッドと同じ呼び出しシグネチャを持つデリゲートを返すことができます。

実行時にこれを行う(デリゲートを返す)か、すべてのラッパー関数を使用して新しいアセンブリを構築し、コードで参照して通常どおりに使用できます。

アスペクト指向プログラミングに使用されるコードウィービングツールを確認する必要があります。それらのいくつかはすでにこれを行っています。

params配列を使用する場合とは異なり、これにより、元のメソッドと同じシグネチャ(またはデリゲート型)のラッパーが提供されるため、型が安全であり、Intellisenseは(他のデリゲートと同様に)機能します。

于 2012-11-05T15:21:34.530 に答える
0

異なるバージョン間で何が共通しているかによって異なりますが、runDate とプロセスが共通であると仮定すると、次のようにすることができます。

public void Run(DateTime runDate, ProcessCode process, LineOfBusinessCode lineOfBusinessCode, LineOfBusinessHandler del)
{
    this.DoRun(runDate, process, (d, p) => del(d, p, lineOfBusinessCode));
}

public void DoRun(DateTime runDate, ProcessCode process, Action<DateTime, ProcessCode> action)
{
    this.ProcessManager.AddToBatchLog(process.ToString(), ProcessStatus.Started.ToString(), null, runDate);


    try
    {
        action(runDate, process);
        this.ProcessManager.AddToBatchLog(process.ToString(), ProcessStatus.Finished.ToString(), null, runDate);
    }
    catch (Exception e)
    {
        int errorId = SystemManager.LogError(e, process.ToString());
        this.ProcessManager.AddToBatchLog(process.ToString(), ProcessStatus.Errored.ToString(), errorId, runDate);
    }
}

次のようにカスタム デリゲートを定義する必要がないように、一般化することもできます。

public void Run<T1>(DateTime runDate, ProcessCode process, T1 param1, Action<DateTime, ProcessCode, T1> del)
{
    this.DoRun(runDate, process, (d, p) => del(d, p, param1));
}

public void Run<T1, T2>(DateTime runDate, ProcessCode process, T1 param1, T2 param2, Action<DateTime, ProcessCode, T1, T2> del)
{
    this.DoRun(runDate, process, (d, p) => del(d, p, param1, param2));
}
于 2012-11-05T15:24:46.397 に答える