1

Simple Injectorを使用して、ロガーが注入されるサービス オブジェクトのコンストラクターにロガー名を設定するという、ロガーに共通のテーマに遭遇しました。サービスがログに書き込むときは、このログ名で簡単に識別できます。

LogNamesはサービスごとに設定されるため、ロガーはオブジェクト グラフ リクエストごとに一意である必要があります。

グラフが作成されているときにこれを自動的に実行したいのですが、いろいろ調べてみましExpressionBuilt()たが、まだ作業したいものを得るのに苦労しています.

私のコンストラクター コードは以下のとおりです (このLogNameプロパティ設定コードは、ほとんどのサービスで共通です)。

ありがとう、

クリス

public interface ILogger
{
    void LogMessage(string message, LogLevel level,
        ILoggableCompany company = null);

    string LogName {get; set; }
}

public BusinessUnitService
{
    private readonly IUnitOfWork unitOfWork;
    private readonly ILogger logger;

    public BusinessUnitService(IUnitOfWork unitOfWork, 
        ILogger logger)
    {
        this.unitOfWork = unitOfWork;
        this.logger = logger;

        // it would be great if we could take away this 
        // line and set it automatically
        this.logger.LogName = this.GetType().ToString();
    }
}
4

1 に答える 1

1

この設計は、ロガーが作成されるクラスLogger<T>である log4netの設計に少し似ています。T私はあなたのデザインを調べることはできませんが、私は疑問に思っています:あなたはログをとりすぎていませんか?

本当にこれを行う必要がある場合は、少なくともインターフェイスLogNameからプロパティを削除してください。ILoggerこれは、このプロパティを設定するコードをコンストラクターから削除する必要があることを意味します。これは、あらゆる場所でコードが重複しているため、まったく問題ありません。

あなたがやろうとしているのはコンテキストベースのインジェクションです。これはすぐにサポートされるものではありませんが、Simple Injector wiki には、このサポートを追加する方法を説明するContext Bases Injection セクションが含まれています。このドキュメンテーションページでは、Logger<T>例としても使用しています:-)

ウィキが参照する拡張メソッドを使用すると、次のことができます。

public interface ILogger
{
    void LogMessage(string message, LogLevel level,
        ILoggableCompany company = null);

    // No LogName property here. Keep it clean.
}

public class LoggerImpl : ILogger
{
    public void LogMessage(string message, 
        LogLevel level, ILoggableCompany company)
    {
       // implementation
    }

    // Property only part of the implementation.
    public string LogName {get; set; }
}

// The parent contains information about the type in 
// which ILogger is injected.
container.RegisterWithContext<ILogger>(parent =>
{
    // Retrieve a new LoggerImpl instance from the container 
    // to allow this type to be auto-wired.
    var logger = container.GetInstance<LoggerImpl>();

    // ImplementationType is null when ILogger is
    // requested directly (using GetInstance<ILogger>())
    // since it will have no parent in that case.
    if (parent.ImplementationType != null)
    {
        // Set the LogName with the name of the class 
        // it is injected into.
        logger.LogName = parent.ImplementationType.Name;
    }

    return logger;
});

// Register the LoggerImpl as transient. This line is
// in fact redundant in Simple Injector, but it is important
// to not accidentally register this type with another
// lifestyle, since the previous registration depends on it
// to be transient.
container.Register<LoggerImpl>();

これは、イベントにフックし、式を再配線することで機能するため、ファクトリ メソッドBuiltExpressionを使用した登録とほぼ同じ速さでインスタンスを解決できます。Func<T>

于 2012-06-22T07:33:22.677 に答える