私はC#.NET 3.5でクラスライブラリアセンブリを書いています。これは、サードパーティの市販品(COTS)ツールを含む他のアプリケーションとの統合に使用されます。したがって、このクラスライブラリは、私が制御するアプリケーション(EXE)によって呼び出されることもあれば、他のDLLまたはnot制御を行うアプリケーションによって呼び出されることもあります。
解決策は次のとおりです。
OR
スタンドアロンクラスライブラリがDLLまたは制御していないアプリケーション(サードパーティのCOTSツールなど)によって呼び出され、log4net構成情報を指定していない場合、私のクラスはライブラリはログの記録を行うことができません。
スタンドアロンクラスライブラリアセンブリのlog4netを構成して有効にして、呼び出し元のアプリケーションがlog4net構成を提供しているかどうかに関係なくログを記録できるようにする方法
最初の制約セットの解決策は、基本的に log4net.LogManager を Jacob 、 Jeroen 、および-のような独自のカスタムLogManagerクラスにラップすることです McWafflestix が提案しています(以下のコードを参照)。
残念ながら、 log4net.LogManager クラスは静的であり、C#は静的継承をサポートしていないため、単純に継承してGetLoggerメソッドをオーバーライドすることはできません。 log4net.LogManager クラスにはあまり多くのメソッドがないため、これは確かに可能性があります。
このソリューションのもう1つの欠点は、既存のコードベース(私はこれを行う)がある場合、log4net.LogManagerへの既存の呼び出しをすべてラッパークラスに置き換える必要があることです。しかし、今日のリファクタリングツールではそれほど重要ではありません。
私のプロジェクトでは、これらの欠点が、呼び出し元のアプリケーションによって提供されるロギング構成を使用する利点を上回っていたため、ソリューション2を採用しました。
まず、LogManagerラッパークラスが必要です。
using System;
using System.IO;
using log4net;
using log4net.Config;
namespace MyApplication.Logging
{
//// TODO: Implement the additional GetLogger method signatures and log4net.LogManager methods that are not seen below.
public static class LogManagerWrapper
{
private static readonly string LOG_CONFIG_FILE= @"path\to\log4net.config";
public static ILog GetLogger(Type type)
{
// If no loggers have been created, load our own.
if(LogManager.GetCurrentLoggers().Length == 0)
{
LoadConfig();
}
return LogManager.GetLogger(type);
}
private void LoadConfig()
{
//// TODO: Do exception handling for File access issues and supply sane defaults if it's unavailable.
XmlConfigurator.ConfigureAndWatch(new FileInfo(LOG_CONFIG_FILE));
}
}
次に、クラスの代わりに:
private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));
使用する:
private static readonly ILog log = LogManagerWrapper.GetLogger(typeof(MyApp));
私の目的のために、2番目の制約のセットを満たすソリューションを選択することにしました。私の解決策については、以下のコードを参照してください。
"アセンブリは、デフォルトのリポジトリではなく、名前付きのログリポジトリを使用することを選択できます。これにより、アセンブリのログがアプリケーションの残りの部分から完全に分離されます。これは、コンポーネント開発者にとって非常に役立ちます。コンポーネントにlog4netを使用したいが、コンポーネントを使用するすべてのアプリケーションがlog4netを認識している必要はありません。これは、デバッグ構成がアプリケーション構成から分離されていることも意味します。リポジトリ。」
クラスライブラリのAssemblyInfo.csファイルに次の行を配置しました。
// Log4Net configuration file location [Assembly: log4net.Config.Repository("CompanyName.IntegrationLibName")] [Assembly: log4net.Config.XmlConfigurator(ConfigFile = "CompanyName.IntegrationLibName.config", Watch = true)]
あなたはおそらく XmlConfigurator クラスの周りに何かをコーディングすることができます:
public static class MyLogManager
{
// for illustration, you should configure this somewhere else...
private static string configFile = @"path\to\log4net.config";
public static ILog GetLogger(Type type)
{
if(log4net.LogManager.GetCurrentLoggers().Length == 0)
{
// load logger config with XmlConfigurator
log4net.Config.XmlConfigurator.Configure(configFile);
}
return LogManager.GetLogger(type);
}
}
次に、クラスの代わりに:
private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));
使用する:
private static readonly ILog log = MyLogManager.GetLogger(typeof(MyApp));
もちろん、このクラスをサービスにして、選択したIoCコンテナーで動的に構成するのが望ましいでしょうが、そのアイデアはわかりますか?
EDIT:修正されたCount()の問題がコメントで指摘されました。
あなたのコードでは、ロガーが存在するかどうかを確認できます
log4net.LogManager.GetCurrentLoggers().Count()
次に、たとえばXmlConfiguratorを使用して、ファイルからデフォルト構成をロードします。
log4net.Config.XmlConfigurator.Configure(configFile)
静的または通常のコンストラクターで初期化を行うことができます。
class Sample
{
private static readonly log4net.ILog LOG;
static Sample()
{
if (log4net.LogManager.GetCurrentLoggers().Count() == 0)
{
loadConfig();
}
LOG = log4net.LogManager.GetLogger(typeof(Sample));
}
private static void loadConfig()
{
/* Load your config file here */
}
public void YourMethod()
{
LOG.Info("Your messages");
}
}
スタンドアロンクラスライブラリに、log4net
を使用してlog4net.Config.XmlConfigurator
構成ファイルをロードするシングルトンがあります。
具体的には、独自のカスタムロギングクラスを使用するようにすべてのコードを定義できます。このクラスは、log4netロギング呼び出しの単純なラッパーであり、1つ追加されています。記録したいログ情報を含む静的メンバーを作成します。そのクラスの静的コンストラクターでXmlConfiguratorを呼び出してそれを初期化します。それだけです。
あなたはここで良い説明を見つけることができます: log4net:クイックスタートガイド
記事で説明しているように、各アセンブリを個別に構成するには、_AssemblyName.dll.log4net
_という名前のアセンブリ用のXMLファイルを作成し、次のXMLコードを配置します。
_<?xml version="1.0" encoding="utf-8"?>
<log4net debug="false">
<appender name="XmlSchemaFileAppender" type="log4net.Appender.FileAppender">
<file value="AppLog.xml" />
<appendToFile value="true" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.XmlLayout" />
</appender>
<root>
<level value="WARN" />
<appender-ref ref="XmlSchemaFileAppender" />
</root>
</log4net>
_
さらに、新しいロガーをインスタンス化するために、クラス全体の変数として次のように宣言することも説明しています。
_public class LogSample
{
private static readonly log4net.ILog Log
= log4net.LogManager.GetLogger(typeof(LogSample));
// Class Methods Go Here...
}
_
次に、クラス内で次のようにプライベート変数Log
を使用できます。
_Log.Info("Sample message");
_
同様に、Log.Error("Error occurred while running myMethod", ex)
を使用して、例外の詳細とともにエラーをログに記録できます。
私が見つけたものは次のとおりです:
設定を有効にするためにlog4net.Config.XmlConfigurator.Configure();
を呼び出すことを忘れないでください
書き込まれたファイルのパスを知る必要がある場合、 ここ Log4Netから取得するためのコード
これがお役に立てば幸いです。