C# 将Func重新设置为特定委托

C# 将Func重新设置为特定委托,c#,nlog,C#,Nlog,我正在利用NLog的能力将代理而不是字符串作为日志调用的一部分。比如说 log.Error(()=>"I am an error which was encountered at " + DateTime.Now) 仅当启用日志记录时,才会计算此委托。理论上,它允许更快的执行,因为委托并不总是被评估。漂亮 当我像一个好的第三方库消费者一样包装NLog记录器时,我的问题就开始了。我有一个像 public interface ILog { ... void Erro

我正在利用NLog的能力将代理而不是字符串作为日志调用的一部分。比如说

log.Error(()=>"I am an error which was encountered at " + DateTime.Now)
仅当启用日志记录时,才会计算此委托。理论上,它允许更快的执行,因为委托并不总是被评估。漂亮

当我像一个好的第三方库消费者一样包装NLog记录器时,我的问题就开始了。我有一个像

public interface ILog
{
 ...        
    void Error(string errorMessage, params string[] args);
    void Error(Func<string> messageGenerator);
    void Error(Exception excepetion, string errorMessage, params string[] args);
    void Error(Exception excepetion, Func<string> messageGenerator);
 ...
}
公共接口ILog
{
...        
无效错误(字符串错误消息,参数字符串[]args);
无效错误(Func messageGenerator);
无效错误(异常例外、字符串错误消息、参数字符串[]参数);
无效错误(异常例外,Func messageGenerator);
...
}
然后是一个实现,比如

...

    public void Error(Func<string> messageGenerator)
    {
        //_log is an NLog logger
        _log.Error((LogMessageGenerator) messageGenerator);
    }
....
。。。
公共无效错误(Func messageGenerator)
{
//_log是一个NLog记录器
_log.Error((LogMessageGenerator)messageGenerator);
}
....
我的问题是,在我的错误日志中,没有对lambda进行评估。我讨论了一下,我认为问题在于,当Func第一次被创建时,它被创建为一个Func,然后当它被传递到NLog时,它被传递为一个Func,而不是LogMessageGenerator。接受对象的NLog重载被调用。所以我猜,在编译lambdas时,C#编译器会尝试基于上下文静态地键入它们的返回

 //log is raw nlog logger
 log.Error(()=> "I am a terrible error"); => LogMessageGenerator
 //log is my wrapper
 log.Error(()=> "I am an even more terrible error"); => Func<string>
//日志是原始nlog记录器
log.Error(()=>“我是一个可怕的错误”);=>日志消息生成器
//日志是我的包装
log.Error(()=>“我是一个更可怕的错误”);=>Func
是否有任何方法可以构建我的ILog实现,这样它仍然可以调用正确的NLog重载,而不必通过将方法签名更改为使用LogMessageGenerator在我的接口中显式依赖NLog?我天真地尝试将Func转换为LogMessageDelegate,但这是不可能的

试试看

public void Error(Func<string> messageGenerator)
{
    //_log is an NLog logger
    _log.Error(new LogMessageGenerator(messageGenerator));
}
public void错误(Func messageGenerator)
{
//_log是一个NLog记录器
_log.Error(新的LogMessageGenerator(messageGenerator));
}

为什么不干脆_log.Error(messageGenerator())@HansPassant,因为如果这样做,则始终会对委托进行求值,即使在禁用日志记录时也是如此。它首先破坏了使用委托的目的。不幸的是,这会产生相同的输出:它只记录委托,而不计算它。我得到了2013-08-14 19:45:50.0826 | ERROR | LoggerName | System.Func`1[System.String]我发现这非常令人惊讶。如果将鼠标悬停在对_log.Error的调用上,会看到什么?这叫什么超负荷?我又试了一次,确实奏效了。(我在另一个没有被调用的方法上尝试了它)。有趣的是,coderush将其标记为冗余委托创建,尽管这肯定不是真的。