最終的に、これはlog4Netのセットアップと関係がありますが、一般的に問題はロギング固有ではありません。
一般的に私が理解しようとしているのは、Microsoft Unity 2.0で、Castle.Facilities.Logging.LoggingFacilityで得られるものと同等の方法です。つまり、ロガーへの依存関係を宣言し、ロガーを注入先のオブジェクトのタイプで初期化する機能。
テストの精神では千の言葉の価値があります、これが私が必要とするものです:
class Logger_IOC_Tests
{
//[Test]
public void Logger_should_be_initialized_with_the_type_of_the_object_that_is_using_it()
{
var container = new UnityContainer();
/* Configuration Magic probably involiving registering either
* a custom IDependencyResolverPolicy or BuilderStrategy
* goes here...
*/
container.RegisterType<LoggerUser>(new ContainerControlledLifetimeManager());
var user = container.Resolve<LoggerUser>();
Assert.True(user.Logger.GetUserType() == user.GetType());
}
}
interface ILogger
{
Type GetUserType();
}
class Logger : ILogger
{
private readonly Type _type;
public Logger(Type type)
{
_type = type;
}
public Type GetUserType()
{
return _type;
}
}
class LoggerUser
{
public readonly ILogger Logger;
public LoggerUser(ILogger logger)
{
Logger = logger;
}
}
これがあなたが探しているものかどうかはわかりませんが、数ヶ月前に見たのですが、あなたの質問を見たときに思い出しました。私はUnityを使用していないので、あなたが投稿したものとリンクにあるものを実際に比較することはできません。うまくいけば、それはあなたに役立つでしょう:
http://davidkeaveny.blogspot.com/2011/03/unity-and-log4net.html
Unityでコンストラクターインジェクションを使用して、正しく構成されたILog
インスタンスを依存関係に挿入できるという同じ結果を達成しようとしています。
結局、私はこれを正確に行うために独自の「log4net」ユニティ拡張を作成しました(一部は別の回答者であるKenneth Baltrinicが書いたブログ投稿に触発されました)。
これにより、拡張機能をUnityに一度登録できます。
var container = new UnityContainer();
container.AddNewExtension<Log4NetExtension>();
次に、正しいILogロガーインスタンスを渡します。
public class MyClass
{
private readonly ILog logger;
public MyClass(ILog logger)
{
this.logger = logger;
}
}
拡張機能はここにあります:
https://github.com/roblevine/UnityLoggingExtensions
詳細はこちら: http://blog.roblevine.co.uk/net/using-log4net-with-unity/
[〜#〜] edit [〜#〜]これは NuGetパッケージ として利用できるようになりました
Unityのソースコードを何時間も調べた後、次の解決策を思いつきました。ただし、デフォルトのコンストラクターセレクターポリシーをオーバーライドするのではなく、解決されるタイプに基づいて適切な依存関係リゾルバーを設定する方法を見つけたいと思います。 1つは、以前に他の目的でデフォルトのコンストラクターセレクターをオーバーライドしたためです。また、このソリューションは、コンストラクターを介して注入された依存関係のみを処理します。完全に網羅するには、デフォルトのプロパティとメソッドセレクターをオーバーライドする必要があると思います。私自身は、コンストラクターだけが必要です。
class Logger_IOC_Tests
{
[Test]
public void Logger_should_be_initialized_with_the_type_of_the_object_that_is_using_it()
{
var container = new UnityContainer();
container.AddNewExtension<LoggingExtension>();
container.RegisterType<LoggerUser>(new ContainerControlledLifetimeManager());
var user = container.Resolve<LoggerUser>();
Assert.True(user.Logger.GetUserType() == user.GetType());
}
}
class LoggingExtension : UnityContainerExtension
{
protected override void Initialize()
{
Context.Policies.SetDefault(typeof(IConstructorSelectorPolicy), new LoggingConstructorSelectorPolicy());
}
}
public class LoggingConstructorSelectorPolicy : DefaultUnityConstructorSelectorPolicy
{
protected override IDependencyResolverPolicy CreateResolver(ParameterInfo parameter)
{
return parameter.ParameterType == typeof(ILogger)
? new LoggerResolverPolicy(parameter.Member.DeclaringType)
: base.CreateResolver(parameter);
}
}
class LoggerResolverPolicy : IDependencyResolverPolicy
{
private readonly Type _dependantType;
public LoggerResolverPolicy(Type dependantType)
{
_dependantType = dependantType;
}
public object Resolve(IBuilderContext context)
{
return new Logger(_dependantType);
}
}
上記の拡張機能は適切に機能しますが、MVC5ユーザーにはより多くの構成情報が必要です。 Unityを使用する手順は次のとおりです。
次の行を、名前空間の上のstartup.csクラスの先頭に追加します。
[アセンブリ:log4net.Config.XmlConfigurator(ConfigFile = "Web.config"、Watch = true)]
あなたのglobal.asax application_startup
メソッドは次の情報を追加します。
log4net.Config.XmlConfigurator.Configure(new FileInfo(Server.MapPath("~/Web.config")));
ユニティコンテナの残りの構成は次のようになります。
container.AddNewExtension<Log4NetExtension>();
Web.configにappender
が追加されていることを確認してください。これを正しく機能させるには、これで十分です。幸運を
Unity 5以降では、Unity独自のLog4Net拡張機能を https://github.com/unitycontainer/log4net から使用できるようになりました。
Nugetをインストールし、コンテナーに拡張機能を追加するだけです。
container.AddNewExtension<Log4NetExtension>();
また、依存関係としてILog
を使用するすべてのクラスで自動的に機能します。
次のコードを使用して、Log4Netを挿入できます
log4net.Config.BasicConfigurator.Configure();
container.RegisterType<ILog>(new InjectionFactory(x => LogManager.GetLogger(typeof(Program))));
プログラムクラスに登録しているのでtypeof(Program)を使用しています。クラス名またはこのキーワードを使用できます
次に、ILogをクラスに挿入できます
public class MyClass
{
private readonly ILog logger;
public MyClass(ILog logger)
{
this.logger = logger;
}
}