log4net integration questions

338 views
Skip to first unread message

Taylan Aydinli

unread,
May 22, 2009, 5:19:50 AM5/22/09
to ninject
Hi,

I'm trying to understand how log4net integration works in Ninject. My
problem is that I don't understand how the Type parameter is injected
into the LoggerBase constructor. I wanted to do a similar log4net
integration without using the integration facilities provided by
Ninject but I can't figure it out.

I have a similar ILogger interface and a Log4NetLogger implementation
with a Type parameter in the constructor, and I want to inject the
type that requests the ILogger, so the type name will show in the
logs, but I don't know too much about Ninject so I'm stumped.

My Log4NetLogger looks like this:

public class Log4netLogger : ILogger
{
private readonly ILog logger;

public Log4netLogger(Type type)
{
this.logger = log4net.LogManager.GetLogger(type);
}
...snip...
Implementations for Log, Warn, Debug methods etc
...snip...
}

I don't want to provide a constructor parameter everytime I ask the
kernel for an ILogger like this:

ILogger logger = kernel.Get<ILogger>(
With.Parameters
.ConstructorArgument(“type”, this.GetType())
);
since doing this everytime i need a Logger felt wrong.

After going into the Ninject source code and trying to figure out how
it works, I've come up with this binding:

Bind<ILogger>()
.To<Log4netLogger>()
.WithConstructorArgument("type", context =>
context.Binding.Provider.Prototype);

This kind of does what I want it to, but it feels contrived, I'm not
convinced that this is the right thing to do. I couldn't find much
documentation about this kind of binding with arguments, so I'd be
grateful if I could get some tips, or some pointers to documentation
about this type of bindings.

Regards

Taylan

Ben Ellis

unread,
May 22, 2009, 9:35:08 AM5/22/09
to nin...@googlegroups.com
Taylan,

You'd probably want to use a Provider.

NInject 1.X:

using log4net;
using Ninject.Core.Activation;
using Ninject.Core.Creation;

public class LogProvider : SimpleProvider<ILog>
{
protected override ILog CreateInstance(IContext context)
{
return LogManager.GetLogger(context.Member.DeclaringType);
}
}

Ninject 2.0:

using log4net;
using Ninject.Activation;

public class LogProvider : Provider<ILog>
{
protected override ILog CreateInstance(IContext context)
{
Return
LogManager.GetLogger(context.Request.Target.Member.DeclaringType);
}
}

Then Bind to a provider instead of a type,

Ninject 1.X:

public class Log4NetModule : StandardModule
{
public override void Load()
{
this.Bind<ILog>().ToProvider<LoggerProvider>();
}
}

static void Main(string[] args)
{
StandardKernel kernel = new StandardKernel(new Log4NetModule());
kernel.Get<MyClass>();
}

public class MyClass
{
private ILog logger;

[Inject]
public MyClass(ILog logger)
{
this.logger = logger;
}

public MyFunction()
{
if (this.logger.IsInfoEnabled)
{
this.logger.Info("Hello World!");
}
}
}

Ninject 2.0:

static void Main(string[] args)
{
StandardKernel kernel = new StandardKernel();
kernel.Bind<ILog>().ToProvider(new LogProvider());
}

public class MyClass
{
private ILog logger;

[Inject]
public MyClass(ILog logger)
{
this.logger = logger;
}

public MyFunction()
{
if (this.logger.IsInfoEnabled)
{
this.logger.Info("Hello World!");
}
}
}

I've been using this without any problems thus far.

Regards,

Ben Ellis

Ian Davis

unread,
May 22, 2009, 2:01:59 PM5/22/09
to nin...@googlegroups.com
I ported the logging system to 2.0 for this purpose.
But I went to put together a sample app for this post, I found can't get it to work with the latest version. Ninject is autoloading all of my extensions and modules and won't listen to the settings I pass in to tell it not to autoload.
   using ( var kernel = new StandardKernel() )
  {
  kernel.Load( new Log4netModule() );
  kernel.Load( new TestModule() );
  var myClass = kernel.Get<MyClass>();
  Assert.NotNull( myClass.Logger );
  }

No matter what I do I always get 
 System.NotSupportedException : Error loading module 'Log4netModule' of type Log4netModule
Another module (of type Log4netModule) with the same name has already been loaded
Suggestions:
  1) Ensure that you have not accidentally loaded the same module twice.
  2) If you are using automatic module loading, ensure you have not manually loaded a module
  that may be found by the module loader.

I will have to try to debug this during the weekend unless someone else has any ideas.
-Ian
--
Ian Davis

Ian Davis

unread,
May 24, 2009, 4:59:10 PM5/24/09
to nin...@googlegroups.com
-Ian

Reply all
Reply to author
Forward
0 new messages