Is there a way to use DebugFormat () with arguments that are expensive to build?

I am a big fan of log4net and the log4j "format" API for logging messages, which avoids the cost of calling ToString () on arguments if the required log level is not enabled.

But there are times when one or more of the arguments that I used is not a simple object, it needs to be created somehow. For example, for example:

logger.DebugFormat("Item {0} not found in {1}",
        itemID,
        string.Join(",", items.Select(i => <you get the idea>))
       );

Is there a way to encapsulate the second argument (Join expression) so that it doesn't execute if DebugFormat doesn't decide what it should be (as for ToString of the first argument)?

It feels like a lambda or func, or something should help here, but I'm pretty new to C # and I can't rely on it.

+4
source share
1 answer

You can create an extension method or a wrapper class, but it is not easy to get a satisfactory syntax because you need to specify some parameters ( itemIDin your example) and some only if necessary. But you cannot pass an anonymous function like object. Instead, I would use another solution that does not require extension methods or wrappers. Create the class as follows:

public sealed class Delayed {
    private readonly Lazy<object> _lazy;
    public Delayed(Func<object> func) {
        _lazy = new Lazy<object>(func, false);
    }

    public override string ToString() {
        var result = _lazy.Value;
        return result != null ? result.ToString() : "";
    }
}

This takes a function that returns an object in the constructor and will not call this function until a call is called ToString(), which, as you know, is called by log4net only if necessary (if such a debugging level is enabled). Then use like this:

logger.DebugFormat("Item {0} not found in {1}",
    itemID,
    new Delayed(() => string.Join(",", items.Select(i => <you get the idea>)))
   );
+6
source

Source: https://habr.com/ru/post/1689622/


All Articles