Using Ninject to fill Log4Net Dependency

后端 未结 7 1207
天命终不由人
天命终不由人 2020-12-23 21:28

I use Ninject as a DI Container in my application. In order to loosely couple to my logging library, I use an interface like this:

public interface ILogger
         


        
相关标签:
7条回答
  • 2020-12-23 22:05
    Bind<ILog>().ToMethod(x => LogManager.GetLogger(GetParentTypeName(x)))
                .InSingletonScope();
    

    You are currently binding in Singleton scope, so only one logger is created which will use the name of the first one created. Instead use InTransientScope()

    0 讨论(0)
  • 2020-12-23 22:09

    The Scope of ILog and ILogger needs to be Transient, otherwise it will just reuse the first logger that it creates. Thanks to @Meryln Morgan-Graham for helping me find that.

    0 讨论(0)
  • 2020-12-23 22:10

    maybe my answer is late but I'm using this format:

    private static void RegisterServices(IKernel kernel)
        {
            kernel.Bind<ILog>()
                .ToMethod(c => LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType))
                .InSingletonScope();
        }
    
    0 讨论(0)
  • 2020-12-23 22:16

    I personally have no interest in abstracting away my logger, so my implementation modules reference log4net.dll directly and my constructors request an ILog as desired.

    To achieve this, a one line registration using Ninject v3 looks like this at the end of my static void RegisterServices( IKernel kernel ):

            kernel.Bind<ILog>().ToMethod( context=> 
                LogManager.GetLogger( context.Request.Target.Member.ReflectedType ) );
            kernel.Get<LogCanary>();
        }
    
        class LogCanary
        {
            public LogCanary(ILog log)
            {
                log.Debug( "Debug Logging Canary message" );
                log.Info( "Logging Canary message" );
            }
        }
    

    For ease of diagnosing logging issues, I stick the following at the start to get a non-DI driven message too:

    public static class NinjectWebCommon
    {
        public static void Start()
        {
            LogManager.GetLogger( typeof( NinjectWebCommon ) ).Info( "Start" );
    

    Which yields the following on starting of the app:

    <datetime> INFO  MeApp.App_Start.NinjectWebCommon           - Start
    <datetime> DEBUG MeApp.App_Start.NinjectWebCommon+LogCanary - Debug Logging Canary message
    <datetime> INFO  MeApp.App_Start.NinjectWebCommon+LogCanary - Logging Canary message
    
    0 讨论(0)
  • 2020-12-23 22:17

    I do like the idea of wrapping the Log4Net in my own interfaces. I don't want to be dependent on Ninjects implementation, because to me that just means I take a dependency on Ninject throughout my application and I thought that was the exact opposite of what dependency injection is for. Decouple from third party services. So I took the original posters code but I changed the following code to make it work.

        private string GetParentTypeName(IContext context)
        {
            var res = context.Request.ParentRequest.ParentRequest.Service.FullName;
            return res.ToString();
        }
    

    I have to call ParentRequest.ParentRequest so that when I print the layout %logger it will print the class that calls the Log4Net log method instead of the Log4Net class of the method that called the Log method.

    0 讨论(0)
  • 2020-12-23 22:23

    For all of you that are still looking for the correct answer, the correct implementation is :

    public class LoggingModule : NinjectModule
    {
        public override void Load()
        {
            Bind<ILog>().ToMethod(x => LogManager.GetLogger(x.Request.Target.Member.DeclaringType));
    
            Bind<ILogger>().To<Log4NetLogger>()
                .InSingletonScope();
        }
    }
    

    Emphasis on:

    x.Request.Target.Member.DeclaringType
    
    0 讨论(0)
提交回复
热议问题