无法记住更好的标题,随时可以将其更改为更好的内容:)
我的应用程序包含许多日志记录语句,如下所示:
var logger = new Logger(/*..get flag from settings if the logger should be active..*/);
// ....
logger.LogActivity(..serialize an object..);
//...
logger.LogActivity(..get another object's expensive overriden ToString method..);
//...
logger.LogActivity(..log something new..);
记录器类:
public class Logger
{
private readonly bool _isActive;
public Logger(bool isActive)
{
_isActive = isActive;
}
public void LogActivity(string activity)
{
if (_isActive)
{
// Save activity to Database.
}
}
}
当我在设置中禁用logger时(因此Logger类中的_isActive字段为false),则不会将任何内容保存到数据库中。但是仍然会评估Logger.LogActivity方法中的所有表达式(例如..serialize object ..在前面的例子中),这会减慢我的应用程序。 我可以使用这样的日志语句:
var logger = new Logger(/*..get flag from settings if the logger should be active..*/);
// ....
if (loggerIsActive) logger.LogActivity(..serialize an object..);
//...
if (loggerIsActive) logger.LogActivity(..get another object's expensive overriden ToString method..);
//...
if (loggerIsActive) logger.LogActivity(..log something new..);
但是仅更改LogActivity方法会好得多......是否有可能以某种方式仅更改LogActivity方法,以便在禁用记录器的情况下,不评估LogActivity调用中的表达式?好吧 - 如果在C#中可行,我会感到惊讶,但有没有其他方法/模式可以做到这一点?
答案 0 :(得分:4)
您可以添加一个带有Func<string>
的重载,该重载将生成要记录的字符串。
public void LogActivity(Func<string> activity)
{
if (_isActive)
{
string log = activity();
// save 'log' to database
}
}
然后像这样使用它:
logger.LogActivity(() => expensiveObject.ToString());
答案 1 :(得分:1)
你无法完全避免参数评估,不,但你可以提供一些额外的记录方法来帮助你。
@Martin和@kenny建议传递lambda表达式。这将推迟对代码的评估,但会导致丑陋的客户端代码。你可能会节省几个周期,但我怀疑它是否值得。
我建议你创建几个LogActivity覆盖:
LogActivity(string message) // logs the message
LogActivity(object obj) // calls obj.ToString() and logs it
如果您认为确实有必要,请保留lambda表达式变体:
LogActivity(Func<String> func) // evaluates the function and logs its response
注意,您将无法避免调用LogActivity的成本。 C#不是C,你没有像C一样工作的宏。这几乎不是问题,如果调用一个非虚方法对你来说很贵,那你经常这样做你不应该这样做无论如何,将日志消息放在那里。