3

ドメイン全体で多くのものをログに記録する必要があるため、ドメインとアプリケーション サービスのほとんどはログの実装に依存しています。この小さなコントラクトを作成したとしましょう:

public interface ILogger {

    void Info(string message);

}

偉大な。ここで、log4net に基づくインフラストラクチャ サービスを実装しました。

public class Log4NetProxy : ILogger {

    private ILog _logger = LogManager.GetLogger();

    public void Info(string message) {
        _logger.Info(message);
    }
}

ただし、私のクラスのほとんどは単なるロガー以外の依存関係を持っているため、constructor-over-injection パターンにどんどん近づいています..

public class MyService : IMyService {

    public MyService(ILogger logger, IRepository repo, IAlsoNeedSettings settings) {

    }

}

設定やロギングなどの基本的なコア要件の注入を回避し、本当に必要な依存関係だけに集中するにはどうすればよいでしょうか? プロパティ注入?サービスファサード? 静的ログ工場?

4

1 に答える 1

1

[必要なものではないため、インターセプターに関する暴言+コードは削除されました:)]

通常はあまり面白くないボイラープレート コードを回避するため、通常はプロパティ インジェクションが適していると思います。

...そして、コンストラクター値からプロパティに多数の ISomething を割り当てます...

Autofac での使用方法はわかりませんが (主に Castle.Windsor を使用しています)、メンテナンスの手間が少なく、コンストラクターの肥大化を回避する良い方法としてお勧めします。

編集: どうやら、Mark Seemann の質問は、これらのケースを処理する有効な方法として傍受について言及しているようです。そのため、元の暴言 + コードを元に戻します。彼が言及しているものと一致するかどうかはわかりませんが、いくつかのアイデアが得られるかもしれません


アスペクト指向プログラミングに少し似ていて、解決されたコンポーネントをインターセプターでラップし、パラメーター、メソッド名などに応じて動作する方法を決定できる、Castle-Windsor インターセプト システムが本当に好きです。

これが私の傍受ロガーの例です:

public class LoggingInterceptor: IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        using (Tracer t = new Tracer(string.Format("{0}.{1}", invocation.TargetType.Name, invocation.Method.Name)))
        {
            StringBuilder sb = new StringBuilder(100);
            sb.AppendFormat("IN (", invocation.TargetType.Name, invocation.Method.Name);
            sb.Append(string.Join(", ", invocation.Arguments.Select(a => a == null ? "null" : DumpObject(a)).ToArray()));
            sb.Append(")");
            t.Verbose(sb.ToString());

            invocation.Proceed();

            sb = new StringBuilder(100);
            sb.AppendFormat("OUT {0}", invocation.ReturnValue != null ? DumpObject(invocation.ReturnValue) : "void");
            t.Verbose(sb.ToString());
        }
    }

    private string DumpObject(object argument)
    {
        // serialize object
    }
}

このロガー インターセプターは、セットアップ中に登録され、WCF サービスの対象クラスに適用されます。

// register interceptors
_container.Register(
    Classes.FromAssemblyInThisApplication()
    .BasedOn<IInterceptor>()
    .WithServiceBase()
    .Configure(c => c.Named(c.Implementation.Name))
);

// apply them
_container.Register
(
    Component.For<IService>()
        .ImplementedBy<ServicesImplementation.Service>()
        .Named("Service")
        .LifestylePerWcfOperation()
        .Interceptors("LoggingInterceptor")
);

ILogger または ILogger プロパティを持つクラスを必要とするメソッドへの呼び出しをインターセプトし、インターセプターから注入することを検討できます。

于 2014-03-13T11:04:03.980 に答える