.net 试图让Log4Net与依赖注入一起工作时遇到了麻烦

.net 试图让Log4Net与依赖注入一起工作时遇到了麻烦,.net,reflection,dependency-injection,log4net,.net,Reflection,Dependency Injection,Log4net,我有一个简单的winform测试应用程序,用来尝试一些Log4Net依赖注入的东西 我在我的服务项目中制作了一个简单的界面:- public interface ILogging { void Debug(string message); // snip the other's. } 然后我的具体类型将使用Log4Net public class Log4NetLogging : ILogging { private static ILog Log4Net {

我有一个简单的winform测试应用程序,用来尝试一些Log4Net依赖注入的东西

我在我的服务项目中制作了一个简单的界面:-

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);
        }
    }
}
到目前为止还不错。没有什么太难的

现在,在另一个项目中(因此命名APCE),我尝试使用这个

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");
    }
}
好的。。也很简单。我已经硬编码了iLogg实例,但这通常是通过构造函数注入的依赖项。不管怎样,当我检查这行代码时

return LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
DeclaringType
type值属于服务名称空间,而不是实际调用方法的表单类型(即X.Y.Z.Form1)


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

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

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);
        }
    }
}

在一个旁注下,我会考虑修改您的接口以接受使用抽象日志的对象的<代码>类型<代码>。我知道您不想这样做,但在运行时检索调用堆栈是一项代价高昂的操作,每次调用

iloging.Debug

时都需要执行该操作,这可能会对其他人有所帮助
根据Steve的建议,我更改了日志服务实现,使其具有一个接受类型的构造函数,即在 在ILogger接口中指定的日志方法

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使用 塞特注射

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

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

干杯,我去试试这个。我担心你会说这种反思很昂贵。另一方面,‘GetLogger(string)’到底做了什么。。。它是否查找配置条目值=>。。所以理论上,我可以在这里输入一些手动字符串。。并确保配置文件中存在?关于
GetLogger(string)
的文档不是很有帮助,但它确实建议从配置文件中检索日志配置。如果这是真的,那么您可以按照建议将“get-logger-for-type-T”代码替换为“get-logger by-name”调用,并在配置文件中为类型T配置命名记录器。有关更多信息,请参阅。我花了很长时间才让它工作,但如果你有…,那么你可以做GetLogger(“你好”)。我花了很长时间才让它工作起来,是因为它非常区分大小写。所以我在做GetLogger(“hello”),这是返回默认的/根记录器:(该死的!:X)
new MyLogging_Service(this.GetType())