简体   繁体   English

如何从 .NET Framework 初始化 .net Core ILogger 或 ILoggerFactory 并注入 Class 内置库中的构造函数.Net Core

[英]How to initialize .net Core ILogger or ILoggerFactory from .NET Framework and inject to a constructor in Class library built in .Net Core

I am consuming a Class Library which is built using .NET Core.我正在使用一个使用 .NET Core 构建的 Class 库。 The Library has only one public class with a constructor accepting ILoggerFactory and another overloaded constructor accepting ILogger.该库只有一个公共 class,其构造函数接受 ILoggerFactory,另一个重载构造函数接受 ILogger。 But I am consuming this library in a console app built using .NET Framework 4.7.但是我在使用 .NET Framework 4.7 构建的控制台应用程序中使用这个库。 My console app uses Log4Net for logging.我的控制台应用程序使用 Log4Net 进行日志记录。 But I need to inject the instance of ILogger or ILoggerFactory so that the class library log's error based on my log.config settings.但我需要注入 ILogger 或 ILoggerFactory 的实例,以便 class 库日志的错误基于我的 log.config 设置。

I tried as below我试过如下

ILogger logger = new LoggerFactory().CreateLogger(); ILogger 记录器 = new LoggerFactory().CreateLogger(); var contentManager = new ContentManager(logger); var contentManager = new ContentManager(记录器);

But I don't know how to pass the Log4Net instance to the LoggerFactory.但我不知道如何将 Log4Net 实例传递给 LoggerFactory。

private static ILog _log = LogManager.GetLogger(typeof(Program));
static void Main(string[] args)
{
   ILogger logger = new LoggerFactory().CreateLogger<ContentManager>();
   var contentManager = new ContentManager(logger);
   contentManager.Run();
}

I don't find anything getting logged and ContentManager doesn't throw any exceptions.我没有发现任何记录,ContentManager 也没有抛出任何异常。 I know that the ILogger instance doesn't know anything about Log4Net from my console app, how I need to pass the Log4Net instance?我知道 ILogger 实例对我的控制台应用程序中的 Log4Net 一无所知,我需要如何传递 Log4Net 实例? Need help on this.在这方面需要帮助。

The answer from Dan S is a great general answer with good example. Dan S的回答是一个很好的一般性回答,有很好的例子。 To implement this specifically for log.net you could use a class like this:要专门为 log.net 实现此功能,您可以像这样使用 class:

public class Log4netAdapter<TCategoryName> : ILogger<TCategoryName>
{
    private readonly ILog _logger = LogManager.GetLogger(typeof(TCategoryName));

    public IDisposable BeginScope<TState>(TState state)
    {
        return null; // log4net does not have scope capability
    }

    public bool IsEnabled(LogLevel logLevel)
    {
        switch (logLevel)
        {
            case LogLevel.Trace:
            case LogLevel.Debug:
                return _logger.IsDebugEnabled;
            case LogLevel.Information:
                return _logger.IsInfoEnabled;
            case LogLevel.Warning:
                return _logger.IsWarnEnabled;
            case LogLevel.Error:
                return _logger.IsErrorEnabled;
            case LogLevel.Critical:
                return _logger.IsFatalEnabled;
            case LogLevel.None:
            default:
                return false;
        }
    }

    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
    {
        if (!IsEnabled(logLevel)) return;
        if (formatter == null) throw new ArgumentNullException(nameof(formatter));

        var message = formatter(state, exception);
        if (!string.IsNullOrEmpty(message) || exception != null)
        {
            switch (logLevel)
            {
                case LogLevel.None:
                    break;
                case LogLevel.Trace:
                case LogLevel.Debug:
                    _logger.Debug(message, exception);
                    break;
                case LogLevel.Information:
                    _logger.Info(message, exception);
                    break;
                case LogLevel.Warning:
                    _logger.Warn(message, exception);
                    break;
                case LogLevel.Error:
                    _logger.Error(message, exception);
                    break;
                case LogLevel.Critical:
                    _logger.Fatal(message, exception);
                    break;
            }
        }
    }
}

Then reference the packages log.net and Microsoft.Extensions.Logging (or Microsoft.Extensions.Logging.Abstractions if you are creating this in a library).然后引用包log.netMicrosoft.Extensions.Logging (或Microsoft.Extensions.Logging.Abstractions ,如果您在库中创建它)。

To use the adapter when instantiating a class using Microsoft.Extensions.Logging (and your project is not using dependency injection):要在使用 Microsoft.Extensions.Logging 实例化 class 时使用适配器(并且您的项目未使用依赖注入):

var logger = new Log4netAdapter<NewClassLibrary>();
var newClassLibrary = new NewClassLibrary(logger);

Try the Adapter Pattern to facilitate delegation to Log4Net. 尝试使用适配器模式以便于委派到Log4Net。 I'm not familiar with Log4Net but I think you'll understand this example: 我不熟悉Log4Net,但我想你会理解这个例子:

class MyLoggerAdapter : Library.ILogger 
{
    private readonly ILog _delegation;

    public MyLoggerAdapter(ILog delegation)
    {
        _delegation = delegation;
    }

    public void ILogger.Debug(string msg, params object[] p)
    {
        _delegation.Debug(msg, p); 
    }
}

Then in your code you can do this: 然后在您的代码中,您可以这样做:

private static ILog _log = LogManager.GetLogger(typeof(Program));
static void Main(string[] args)
{
   MyLoggerAdapter logAdapter = new MyLoggerAdapter(_log);
   var contentManager = new ContentManager(logAdapter);
   contentManager.Run();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM