简体   繁体   English

从类库访问日志记录功能

[英]Accessing logging functionality from a class library

I have a solution with two projects, my WPF application project which references the second project, a class library. 我有一个包含两个项目的解决方案,我的WPF应用程序项目引用了第二个项目,一个类库。 The WPF application uses Caliburn.Micro. WPF应用程序使用Caliburn.Micro。 I would like some classes in the library to log messages through Caliburn.Micro's logging facility (which I've set up with log4net, but that should be irrelevant). 我想库中的一些类通过Caliburn.Micro的日志工具(我用log4net设置,但这应该是无关紧要的)记录消息。

To see if this would work, I put the following class into my library to see if anything would show up in my log, and called it from one of my viewmodels: 为了查看这是否有效,我将以下类放入我的库中,以查看是否有任何内容会显示在我的日志中,并从我的一个视图模型中调用它:

public class TempClass {
    private static ILog Log = LogManager.GetLog(typeof(TempClass));

    public static void LogSomething(string something) {
        Log.Info(something);
    }
}

It didn't work. 它没用。

The class library can't reference my WPF application's project because that would cause a circular reference. 类库无法引用我的WPF应用程序的项目,因为这会导致循环引用。

What is a good solution to this problem? 什么是这个问题的好方法?

EDIT 编辑

A bit of additional information that might be useful. 一些可能有用的附加信息。 LogManager is a static class inside Caliburn.Micro.DLL, and has a public static GetLog field: LogManager是Caliburn.Micro.DLL中的静态类,并具有公共静态GetLog字段:

public static Func<Type, ILog> GetLog = type => NullLogInstance;

In my bootstrapper, I'm setting that to 在我的引导程序中,我正在设置它

LogManager.GetLog = type => new Log4netLogger(type);

If I set a breakpoint in the Log4netLogger constructor, it isn't hit when the GetLog() call is made to get my ILog instance in TempClass. 如果我在Log4netLogger构造函数中设置断点,则在调用GetLog()以在TempClass中获取我的ILog实例时不会触发它。

Here is the implementation of Log4netLogger if it helps: 如果有帮助,这是Log4netLogger的实现:

internal class Log4netLogger : ILog {
    private readonly log4net.ILog InnerLogger;

    public Log4netLogger(Type type) {
        InnerLogger = log4net.LogManager.GetLogger(type);
    }

    public void Error(Exception exception) {
        InnerLogger.Error(exception.Message, exception);
    }

    public void Info(string format, params object[] args) {
        InnerLogger.InfoFormat(format, args);
    }

    public void Warn(string format, params object[] args) {
        InnerLogger.WarnFormat(format, args);
    }
}

It turns out the problem was using a field initializer. 事实证明问题是使用字段初始化程序。 I believe this was being called before my bootstrapper had the opportunity to assign another delegate to GetLog. 我相信这是在我的引导程序有机会将另一个委托分配给GetLog之前调用的。 Here is the new TempClass which works: 以下是新的TempClass:

public class TempClass {
    private static ILog Log;

    public static void LogSomething(string something) {
        if (Log == null)
            Log = LogManager.GetLog(typeof(TempClass));

        Log.Info(something);
    }
}

You could use Dependency Injection to solve this problem: http://msdn.microsoft.com/en-us/library/aa973811.aspx 您可以使用依赖注入来解决此问题: http//msdn.microsoft.com/en-us/library/aa973811.aspx

(You could also use ServiceLocator: http://www.martinfowler.com/articles/injection.html although, you will find mixed opinions on it. Some people like it, some say that Service Locator is evil: http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/ (你也可以使用ServiceLocator: http//www.martinfowler.com/articles/injection.html虽然,你会发现它的意见不一。有些人喜欢它,有人说服务定位器是邪恶的: http:// blog .ploeh.dk / 2010/02/03 / ServiceLocatorisanAnti点模式/

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

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