diff --git a/src/NLog/LayoutRenderers/FuncLayoutRenderer.cs b/src/NLog/LayoutRenderers/FuncLayoutRenderer.cs index 927c62fcdb..bfe45d9f5b 100644 --- a/src/NLog/LayoutRenderers/FuncLayoutRenderer.cs +++ b/src/NLog/LayoutRenderers/FuncLayoutRenderer.cs @@ -43,6 +43,16 @@ namespace NLog.LayoutRenderers /// public class FuncLayoutRenderer : LayoutRenderer, IStringValueRenderer { + private readonly Func _renderMethod; + + /// + /// Initializes a new instance of the class. + /// + /// Name without ${}. + protected FuncLayoutRenderer(string layoutRendererName) : this(layoutRendererName, null) + { + } + /// /// Initializes a new instance of the class. /// @@ -50,7 +60,7 @@ public class FuncLayoutRenderer : LayoutRenderer, IStringValueRenderer /// Method that renders the layout. public FuncLayoutRenderer(string layoutRendererName, Func renderMethod) { - RenderMethod = renderMethod ?? throw new ArgumentNullException(nameof(renderMethod)); + _renderMethod = renderMethod ?? throw new ArgumentNullException(nameof(renderMethod)); LayoutRendererName = layoutRendererName; } @@ -60,9 +70,11 @@ public FuncLayoutRenderer(string layoutRendererName, Func - /// Method that renders the layout. + /// Method that renders the layout. + /// + /// Will be removed in NLog 5! /// - public Func RenderMethod { get; } + public Func RenderMethod => _renderMethod; /// /// Format string for conversion from object to string. @@ -92,9 +104,14 @@ private string GetStringValue(LogEventInfo logEvent) return null; } - private object GetValue(LogEventInfo logEvent) + /// + /// Get the value for the LogEvent + /// + /// + /// + protected virtual object GetValue(LogEventInfo logEvent) { - return RenderMethod.Invoke(logEvent, LoggingConfiguration); + return _renderMethod?.Invoke(logEvent, LoggingConfiguration); } } } \ No newline at end of file diff --git a/src/NLog/LayoutRenderers/LayoutRenderer.cs b/src/NLog/LayoutRenderers/LayoutRenderer.cs index 9c7f0f9df7..83496aec53 100644 --- a/src/NLog/LayoutRenderers/LayoutRenderer.cs +++ b/src/NLog/LayoutRenderers/LayoutRenderer.cs @@ -244,7 +244,7 @@ protected CultureInfo GetCulture(LogEventInfo logEvent, CultureInfo layoutCultur /// Type of the layout renderer. /// Name of the layout renderer - without ${}. public static void Register(string name) - where T: LayoutRenderer + where T : LayoutRenderer { var layoutRendererType = typeof(T); Register(name, layoutRendererType); @@ -280,8 +280,17 @@ public static void Register(string name, Func func) public static void Register(string name, Func func) { var layoutRenderer = new FuncLayoutRenderer(name, func); - - ConfigurationItemFactory.Default.GetLayoutRenderers().RegisterFuncLayout(name, layoutRenderer); + + Register(layoutRenderer); + } + + /// + /// Register a custom layout renderer with a callback function . The callback receives the logEvent and the current configuration. + /// + /// Renderer with callback func + public static void Register(FuncLayoutRenderer layoutRenderer) + { + ConfigurationItemFactory.Default.GetLayoutRenderers().RegisterFuncLayout(layoutRenderer.LayoutRendererName, layoutRenderer); } } } \ No newline at end of file diff --git a/tests/NLog.UnitTests/LayoutRenderers/FuncLayoutRendererTests.cs b/tests/NLog.UnitTests/LayoutRenderers/FuncLayoutRendererTests.cs new file mode 100644 index 0000000000..c2563b2ae1 --- /dev/null +++ b/tests/NLog.UnitTests/LayoutRenderers/FuncLayoutRendererTests.cs @@ -0,0 +1,86 @@ +// +// Copyright (c) 2004-2020 Jaroslaw Kowalski , Kim Christensen, Julian Verdurmen +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of Jaroslaw Kowalski nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +// + +using NLog.LayoutRenderers; +using System; +using NLog.Config; +using Xunit; + +namespace NLog.UnitTests.LayoutRenderers +{ + public class FuncLayoutRendererTests : NLogTestBase + { + [Fact] + public void RegisterCustomFuncLayoutRendererTest() + { + // Arrange + var funcLayoutRenderer = new MyFuncLayoutRenderer("the-answer-new"); + + // Act + LayoutRenderer.Register(funcLayoutRenderer); + + LogManager.Configuration = XmlLoggingConfiguration.CreateFromXmlString(@" + + + + + + "); + + var logger = LogManager.GetCurrentClassLogger(); + logger.Debug("test1"); + + // Assert + AssertDebugLastMessage("debug", "TheAnswer=042"); + } + + + private class MyFuncLayoutRenderer : FuncLayoutRenderer + { + /// + public MyFuncLayoutRenderer(string layoutRendererName) : base(layoutRendererName) + { + } + + #region Overrides of FuncLayoutRenderer + + /// + protected override object GetValue(LogEventInfo logEvent) + { + return 42; + } + + #endregion + } + } +}