试图让Log4Net与依赖注入一起工作

时间:2009-10-10 14:25:36

标签: .net reflection dependency-injection log4net

我有一个简单的winform测试应用程序,我正在尝试使用Log4Net依赖注入的东西。

我在 Services 项目中创建了一个简单的界面: -

public interface ILogging
{
    void Debug(string message);

    // snip the other's.
}

然后我的具体类型将使用Log4Net ......

public class Log4NetLogging : ILogging
{
    private static ILog Log4Net
    {
        get { return LogManager.GetLogger(
                       MethodBase.GetCurrentMethod().DeclaringType); }
    }

    public void Debug(string message)
    {
        if (Log4Net.IsDebugEnabled)
        {
            Log4Net.Debug(message);
        }
    }
}

到目前为止一切顺利。那里没什么难的。

现在,在一个不同的项目(以及因此的名称)中,我尝试使用它......

public partial class Form1 : Form
{  
    public Form1()
    {
        FileInfo fileInfo = new FileInfo("Log4Net.config");
        log4net.Config.XmlConfigurator.Configure(fileInfo);
    }

    private void Foo()
    {
        // This would be handled with DI, but i've not set it up 
        // (on the constructor, in this code example).
        ILogging logging = new Log4NetLogging(); 
        logging.Debug("Test message");
    }
}

好的..也很简单。我已经对ILogging实例进行了硬编码,但这通常是通过构造函数注入的依赖项。无论如何,当我检查这行代码时......

return LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

DeclaringType类型值是 Service 命名空间,而不是实际调用该方法的 Form (即X.Y.Z.Form1)的类型。

如果不将类型INTO方法作为另一个参数传递,是否仍然使用反射来找出调用它的real方法?

2 个答案:

答案 0 :(得分:1)

可能有助于某人的额外答案 根据Steve的建议,我改变了我的日志服务实现,使其具有一个接受一个类型的构造函数,即提供的类型参数 ILogger接口中指定的Log方法

public class MyLogging_Service : IMyLogging_Service
{
    private Type _declaringType;
    private ILog _log;
    private ILog Log { get { return _log; } }

    public MyLogging_Service(Type p_Val)
    {
        _declaringType = p_Val;
        _log = LogManager.GetLogger(p_Val);
    }

    public void LogInfo(string p_Msg)
    {
        Log.Logger.Log(_declaringType, Level.Info, p_Msg, null);
    }

...

}

实际使用

public class Service1 : IService1
{
    // declared as a property
    IMyLogging_Service MyLoggingService { get; set; }

}

之前我使用StructureMap自动填充此属性 二传手注射
link

在我的依赖注入引导程序中,我使用了以下语句

FillAllPropertiesOfType<IMyLogging_Service>().TheDefault.Is
                .ConstructedBy(context => new MyLogging_Service(context.ParentType));

回顾一下
1。创建了一个类,使用构造函数实现日志记录,该构造函数接受一个类型,用于在Log方法实现中指定callerStackBoundaryDeclaringType参数
2。为需要具有日志记录功能的类创建了日志服务属性
3。在依赖注入引导程序中包含代码,使用上下文StructureMap变量

使用父类型填充属性

btw在您的代码中没有必要DI的情况下,您可以编写这样的代码

new MyLogging_Service(this.GetType())

答案 1 :(得分:0)

要获取调用特定方法的MethodInfo对象,需要检查调用堆栈。这可以通过StackTrace类以下列方式完成。

using System.Diagnostics;
using System.Reflection;

public class Log4NetLogging : ILogging
{
    private ILog GetLogForStackFrame(StackFrame frame)
    {
        return LogManager.GetLogger(frame.GetMethod().DeclaringType);
    }

    public void Debug(string message)
    {
        ILog log = GetLogForStackFrame(new StackTrace().GetFrame(0));
        if (log.IsDebugEnabled)
        {
            log.Debug(message);
        }
    }
}

在旁注中,我会考虑修改您的接口以接受将使用抽象日志的对象的Type。我意识到你不想这样做,但是在运行时检索调用堆栈是一项代价高昂的操作,每次调用ILogging.Debug时都需要执行。