diff --git a/src/log4net.Tests/Appender/RemotingAppenderTest.cs b/src/log4net.Tests/Appender/RemotingAppenderTest.cs index 51198740..511b2211 100644 --- a/src/log4net.Tests/Appender/RemotingAppenderTest.cs +++ b/src/log4net.Tests/Appender/RemotingAppenderTest.cs @@ -22,6 +22,8 @@ using System; using System.Collections; +using System.Collections.Generic; +using System.Linq; using System.Reflection; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; @@ -47,7 +49,7 @@ namespace log4net.Tests.Appender [TestFixture] public class RemotingAppenderTest { - private IChannel m_remotingChannel = null; + private IChannel? m_remotingChannel; /// /// Test that the Message property is correctly remoted @@ -55,21 +57,20 @@ public class RemotingAppenderTest [Test] public void TestRemotedMessage() { - // Setup the remoting appender + // Set up the remoting appender ConfigureRootAppender(FixFlags.Partial); RemoteLoggingSinkImpl.Instance.Reset(); - Logger root; - root = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; + Logger root = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; - string testMessage = string.Format("test message [ {0} ]", (new Random()).Next()); + string testMessage = $"test message [ {(new Random()).Next()} ]"; // Log a message that will be remoted root.Log(Level.Debug, testMessage, null); // Wait for the remoted object to be delivered - Thread.Sleep(2000); + WaitFor("Remote instance should have received all remoting events", () => RemoteLoggingSinkImpl.Instance.Events.Length > 0); LoggingEvent[] events = RemoteLoggingSinkImpl.Instance.Events; Assert.AreEqual(1, events.Length, "Expect to receive 1 remoted event"); @@ -83,19 +84,18 @@ public void TestRemotedMessage() [Test] public void TestPartialFix() { - // Setup the remoting appender + // Set up the remoting appender ConfigureRootAppender(FixFlags.Partial); RemoteLoggingSinkImpl.Instance.Reset(); - Logger root; - root = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; + Logger root = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; // Log a message that will be remoted root.Log(Level.Debug, "test message", null); // Wait for the remoted object to be delivered - Thread.Sleep(2000); + WaitFor("Remote instance should have received all remoting events", () => RemoteLoggingSinkImpl.Instance.Events.Length > 0); LoggingEvent[] events = RemoteLoggingSinkImpl.Instance.Events; Assert.AreEqual(1, events.Length, "Expect to receive 1 remoted event"); @@ -109,20 +109,17 @@ public void TestPartialFix() [Test] public void TestFullFix() { - // Setup the remoting appender + // Set up the remoting appender ConfigureRootAppender(FixFlags.All); RemoteLoggingSinkImpl.Instance.Reset(); - Logger root; - root = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; + Logger root = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; // Log a message that will be remoted root.Log(Level.Debug, "test message", null); // Wait for the remoted object to be delivered - Thread.Sleep(5000); - WaitFor("Remote instance should have received a remoting event", () => RemoteLoggingSinkImpl.Instance.Events.Length > 0); LoggingEvent[] events = RemoteLoggingSinkImpl.Instance.Events; Assert.AreEqual(1, events.Length, "Expect to receive 1 remoted event"); @@ -130,7 +127,7 @@ public void TestFullFix() Assert.IsNotNull(events[0].LocationInfo, "Expect LocationInfo to not be null because doing a full fix"); } - private void WaitFor( + private static void WaitFor( string failMessage, Func condition, int maxWaitMilliseconds = 5000) @@ -139,7 +136,9 @@ private void WaitFor( do { if (condition()) + { return; + } Thread.Sleep(100); } while ((DateTime.Now - start).TotalMilliseconds < maxWaitMilliseconds); throw new TimeoutException($"Condition not achieved within {maxWaitMilliseconds}ms: {failMessage}"); @@ -151,15 +150,14 @@ private void WaitFor( [Test] public void TestRemotedMessageNdcPushPop() { - // Setup the remoting appender + // Set up the remoting appender ConfigureRootAppender(FixFlags.Partial); RemoteLoggingSinkImpl.Instance.Reset(); - Logger root; - root = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; + Logger root = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; - string testMessage = string.Format("test message [ {0} ]", (new Random()).Next()); + string testMessage = $"test message [ {(new Random()).Next()} ]"; using (NDC.Push("value")) { @@ -169,7 +167,7 @@ public void TestRemotedMessageNdcPushPop() root.Log(Level.Debug, testMessage, null); // Wait for the remoted object to be delivered - Thread.Sleep(2000); + WaitFor("Remote instance should have received all remoting events", () => RemoteLoggingSinkImpl.Instance.Events.Length > 0); LoggingEvent[] events = RemoteLoggingSinkImpl.Instance.Events; Assert.AreEqual(1, events.Length, "Expect to receive 1 remoted event"); @@ -180,47 +178,43 @@ public void TestRemotedMessageNdcPushPop() [Test] public void TestNestedNdc() { - // This test can suffer from timing and ordering issues as the RemotingAppender does dispatch events asynchronously - - // Setup the remoting appender + // Set up the remoting appender ConfigureRootAppender(FixFlags.Partial); RemoteLoggingSinkImpl.Instance.Reset(); - TestService t; - t = new TestService(); + var t = new TestService(); t.Test(); - // Wait for the remoted objects to be delivered - Thread.Sleep(3000); + WaitFor("Remote instance should have received all remoting events", () => RemoteLoggingSinkImpl.Instance.Events.Length == 5); LoggingEvent[] events = RemoteLoggingSinkImpl.Instance.Events; - Assert.AreEqual(5, events.Length, "Expect to receive 5 remoted event"); - - Assert.AreEqual("begin test", events[0].RenderedMessage, "Verify event 1 RenderedMessage"); - Assert.AreEqual("feature", events[1].RenderedMessage, "Verify event 2 RenderedMessage"); - Assert.AreEqual("return", events[2].RenderedMessage, "Verify event 3 RenderedMessage"); - Assert.AreEqual("return", events[3].RenderedMessage, "Verify event 4 RenderedMessage"); - Assert.AreEqual("end test", events[4].RenderedMessage, "Verify event 5 RenderedMessage"); - - Assert.IsNull(events[0].Properties["NDC"], "Verify event 1 Properties"); - Assert.AreEqual("test1", events[1].Properties["NDC"], "Verify event 2 Properties"); - Assert.AreEqual("test1 test2", events[2].Properties["NDC"], "Verify event 3 Properties"); - Assert.AreEqual("test1", events[3].Properties["NDC"], "Verify event 4 Properties"); - Assert.IsNull(events[4].Properties["NDC"], "Verify event 5 Properties"); - } + // RemotingAppender dispatches events asynchronously, messages could be in any order. + LoggingEvent beingTest = events.First(e => e.RenderedMessage == "begin test"); + Assert.IsNull(beingTest.Properties["NDC"], "Verify 'being test' event Properties"); + + LoggingEvent feature = events.First(e => e.RenderedMessage == "feature"); + Assert.AreEqual("test1", feature.Properties["NDC"], "Verify 'feature' event Properties"); + + LoggingEvent return1 = events.First(e => e.RenderedMessage == "return" && Equals(e.Properties["NDC"], "test1 test2")); + + LoggingEvent return2 = events.First(e => e.RenderedMessage == "return" && Equals(e.Properties["NDC"], "test1")); + + LoggingEvent endTest = events.First(e => e.RenderedMessage == "end test"); + Assert.IsNull(endTest.Properties["NDC"], "Verify 'end test' event Properties"); + } private void RegisterRemotingServerChannel() { - if (m_remotingChannel == null) + if (m_remotingChannel is null) { BinaryClientFormatterSinkProvider clientSinkProvider = new BinaryClientFormatterSinkProvider(); BinaryServerFormatterSinkProvider serverSinkProvider = new BinaryServerFormatterSinkProvider(); serverSinkProvider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full; - Hashtable channelProperties = new Hashtable(); + var channelProperties = new Hashtable(); channelProperties["port"] = 8085; m_remotingChannel = new TcpChannel(channelProperties, clientSinkProvider, serverSinkProvider); @@ -277,7 +271,7 @@ public void TearDown() [OneTimeTearDown] public void UnregisterRemotingServerChannel() { - if (m_remotingChannel != null) + if (m_remotingChannel is not null) { ((TcpChannel)m_remotingChannel).StopListening(null); try @@ -296,20 +290,21 @@ public void UnregisterRemotingServerChannel() /// private static void ConfigureRootAppender(FixFlags fixFlags) { - Logger root; - root = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; + Logger root = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; root.Level = Level.Debug; root.AddAppender(CreateAppender(fixFlags)); - root.Repository.Configured = true; + root.Repository!.Configured = true; } private static RemotingAppender CreateAppender(FixFlags fixFlags) { - RemotingAppender appender = new RemotingAppender(); - appender.Sink = "tcp://localhost:8085/LoggingSink"; - appender.Lossy = false; - appender.BufferSize = 1; - appender.Fix = fixFlags; + var appender = new RemotingAppender + { + Sink = "tcp://localhost:8085/LoggingSink", + Lossy = false, + BufferSize = 1, + Fix = fixFlags + }; appender.ActivateOptions(); @@ -318,33 +313,25 @@ private static RemotingAppender CreateAppender(FixFlags fixFlags) public class RemoteLoggingSinkImpl : MarshalByRefObject, RemotingAppender.IRemoteLoggingSink { - public static readonly RemoteLoggingSinkImpl Instance = new RemoteLoggingSinkImpl(); + public static readonly RemoteLoggingSinkImpl Instance = new(); - private ArrayList m_events = new ArrayList(); + private readonly List m_events = new(); - #region Public Instance Constructors private RemoteLoggingSinkImpl() { } - #endregion Public Instance Constructors - #region Implementation of IRemoteLoggingSink /// - /// Logs the events to to an internal buffer + /// Logs the events to an internal buffer. /// /// The events to log. /// - /// Logs the events to to an internal buffer. The logged events can + /// The logged events can /// be retrieved via the property. To clear /// the buffer call the method. /// - public void LogEvents(LoggingEvent[] events) - { - m_events.AddRange(events); - } - #endregion Implementation of IRemoteLoggingSink + public void LogEvents(LoggingEvent[] events) => m_events.AddRange(events); - #region Override implementation of MarshalByRefObject /// /// Obtains a lifetime service object to control the lifetime /// policy for this instance. @@ -353,21 +340,14 @@ public void LogEvents(LoggingEvent[] events) /// null to indicate that this instance should live /// forever. /// - public override object InitializeLifetimeService() + public override object? InitializeLifetimeService() { return null; } - #endregion Override implementation of MarshalByRefObject - public void Reset() - { - m_events.Clear(); - } + public void Reset() => m_events.Clear(); - public LoggingEvent[] Events - { - get { return (LoggingEvent[])m_events.ToArray(typeof(LoggingEvent)); } - } + public LoggingEvent[] Events => m_events.ToArray(); } } } @@ -378,14 +358,14 @@ namespace log4net.Tests.Appender.Remoting.UserInterfaces { public class TestService { - private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod()!.DeclaringType!); public void Test() { log.Info("begin test"); Thread.Sleep(100); - Feature f = new Feature(); + var f = new Feature(); f.Test(); log.Info("end test"); Thread.Sleep(100); @@ -399,7 +379,7 @@ namespace log4net.Tests.Appender.Remoting { public class Feature { - private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod()!.DeclaringType!); public void Test() { @@ -408,7 +388,7 @@ public void Test() log.Info("feature"); Thread.Sleep(100); - Dal d = new Dal(); + var d = new Dal(); d.Test(); log.Info("return"); Thread.Sleep(100); @@ -423,7 +403,7 @@ namespace log4net.Tests.Appender.Remoting.Data { public class Dal { - private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod()!.DeclaringType!); public void Test() { diff --git a/src/log4net.Tests/Appender/StringAppender.cs b/src/log4net.Tests/Appender/StringAppender.cs index 83602f88..90e0c6ef 100644 --- a/src/log4net.Tests/Appender/StringAppender.cs +++ b/src/log4net.Tests/Appender/StringAppender.cs @@ -30,7 +30,7 @@ namespace log4net.Tests.Appender /// Nicko Cadell public class StringAppender : AppenderSkeleton { - private StringBuilder m_buf = new StringBuilder(); + private StringBuilder m_buf = new(); /// /// Initializes a new instance of the class. @@ -68,9 +68,6 @@ protected override void Append(LoggingEvent loggingEvent) /// This appender requires a to be set. /// /// true - protected override bool RequiresLayout - { - get { return true; } - } + protected override bool RequiresLayout => true; } } \ No newline at end of file diff --git a/src/log4net.Tests/Context/LogicalThreadContextTest.cs b/src/log4net.Tests/Context/LogicalThreadContextTest.cs index 8d61a39a..b4861e0f 100644 --- a/src/log4net.Tests/Context/LogicalThreadContextTest.cs +++ b/src/log4net.Tests/Context/LogicalThreadContextTest.cs @@ -29,6 +29,8 @@ using NUnit.Framework; +#nullable enable + namespace log4net.Tests.Context { /// @@ -253,7 +255,7 @@ public async Task TestLogicalThreadStackPatternAsyncAwait() stringAppender.Reset(); string testValueForCurrentContext = "Outer"; - string[] strings = null; + string[]? strings; using (LogicalThreadContext.Stacks[Utils.PROPERTY_KEY].Push(testValueForCurrentContext)) { log1.Info("TestMessage"); @@ -304,10 +306,12 @@ static async Task MoreWorkProperties(ILog log, string propertyName) log.Info("TestMessage"); } - static async Task SomeWorkStack(string stackName) + private static async Task SomeWorkStack(string stackName) { - StringAppender stringAppender = new StringAppender(); - stringAppender.Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}"); + var stringAppender = new StringAppender + { + Layout = new PatternLayout("%property{" + Utils.PROPERTY_KEY + "}") + }; ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString()); BasicConfigurator.Configure(rep, stringAppender); diff --git a/src/log4net.Tests/Context/ThreadContextTest.cs b/src/log4net.Tests/Context/ThreadContextTest.cs index f08a63cb..a01ca037 100644 --- a/src/log4net.Tests/Context/ThreadContextTest.cs +++ b/src/log4net.Tests/Context/ThreadContextTest.cs @@ -21,6 +21,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Threading; using log4net.Config; @@ -35,9 +36,6 @@ namespace log4net.Tests.Context /// /// Used for internal unit testing the class. /// - /// - /// Used for internal unit testing the class. - /// [TestFixture] public class ThreadContextTest { @@ -197,36 +195,36 @@ public void TestThreadStackPatternNullVal2() stringAppender.Reset(); } - private static string TestBackgroundThreadContextPropertyRepository; - [Test] public void TestBackgroundThreadContextProperty() { StringAppender stringAppender = new StringAppender(); stringAppender.Layout = new PatternLayout("%property{DateTimeTodayToString}"); - ILoggerRepository rep = LogManager.CreateRepository(TestBackgroundThreadContextPropertyRepository = - "TestBackgroundThreadContextPropertyRepository" + Guid.NewGuid().ToString()); + string testBackgroundThreadContextPropertyRepository = + "TestBackgroundThreadContextPropertyRepository" + Guid.NewGuid(); + ILoggerRepository rep = LogManager.CreateRepository(testBackgroundThreadContextPropertyRepository); BasicConfigurator.Configure(rep, stringAppender); - Thread thread = new Thread(new ThreadStart(ExecuteBackgroundThread)); - thread.Start(); + Thread thread = new Thread(ExecuteBackgroundThread); + thread.Start(testBackgroundThreadContextPropertyRepository); Thread.CurrentThread.Join(2000); } - private static void ExecuteBackgroundThread() + private static void ExecuteBackgroundThread(object context) { - ILog log = LogManager.GetLogger(TestBackgroundThreadContextPropertyRepository, "ExecuteBackGroundThread"); - ThreadContext.Properties["DateTimeTodayToString"] = DateTime.Today.ToString(); + string testBackgroundThreadContextPropertyRepository = (string)context; + ILog log = LogManager.GetLogger(testBackgroundThreadContextPropertyRepository, "ExecuteBackGroundThread"); + ThreadContext.Properties["DateTimeTodayToString"] = DateTime.Today.ToString(CultureInfo.InvariantCulture); log.Info("TestMessage"); Repository.Hierarchy.Hierarchy hierarchyLoggingRepository = (Repository.Hierarchy.Hierarchy)log.Logger.Repository; - StringAppender stringAppender = (StringAppender)hierarchyLoggingRepository.Root.Appenders[0]; + StringAppender stringAppender = (StringAppender)hierarchyLoggingRepository!.Root.Appenders[0]; - Assert.AreEqual(DateTime.Today.ToString(), stringAppender.GetString()); + Assert.AreEqual(DateTime.Today.ToString(CultureInfo.InvariantCulture), stringAppender.GetString()); } [Test] @@ -237,7 +235,7 @@ public void PropertiesShouldBeThreadSafe() var flags = new List(); // Act - for (var i = 0; i < 256; i++) + for (var i = 0; i < Math.Max(64, 4 * Environment.ProcessorCount); i++) { var t = new Thread(SpinAndCheck); var flag = new FlagContainer(); @@ -261,7 +259,7 @@ public class FlagContainer private void SpinAndCheck(object obj) { - var container = obj as FlagContainer; + var container = (FlagContainer)obj; var threadid = Thread.CurrentThread.ManagedThreadId; for (var i = 0; i < 100000; i++) { diff --git a/src/log4net.Tests/Core/DefaultRepositorySelectorTest.cs b/src/log4net.Tests/Core/DefaultRepositorySelectorTest.cs index 024e03d9..a0525927 100644 --- a/src/log4net.Tests/Core/DefaultRepositorySelectorTest.cs +++ b/src/log4net.Tests/Core/DefaultRepositorySelectorTest.cs @@ -21,7 +21,6 @@ using System.Collections; using System.Collections.Generic; using log4net.Appender; -using log4net.Config; using log4net.Core; using log4net.ObjectRenderer; using log4net.Plugin; @@ -183,7 +182,5 @@ public IAppender[] GetAppenders() } } - internal class MockLoggerRepository2 : MockLoggerRepository - { - } + internal class MockLoggerRepository2 : MockLoggerRepository; } diff --git a/src/log4net.Tests/Hierarchy/LoggerTest.cs b/src/log4net.Tests/Hierarchy/LoggerTest.cs index b03357b7..6dbd2331 100644 --- a/src/log4net.Tests/Hierarchy/LoggerTest.cs +++ b/src/log4net.Tests/Hierarchy/LoggerTest.cs @@ -71,6 +71,7 @@ public void TestAppender1() { Assert.IsTrue(enumAppenders.MoveNext()); var aHat = (CountingAppender?)enumAppenders.Current; + Assert.IsNotNull(aHat); Assert.AreEqual(a1, aHat); } finally @@ -101,6 +102,7 @@ public void TestAppender2() Assert.AreEqual(a1, aHat); aHat = (CountingAppender?)log.GetAppender(a2.Name); + Assert.IsNotNull(aHat); Assert.AreEqual(a2, aHat); // By name. @@ -113,6 +115,7 @@ public void TestAppender2() { Assert.IsTrue(enumAppenders.MoveNext()); aHat = (CountingAppender?)enumAppenders.Current; + Assert.IsNotNull(aHat); Assert.AreSame(a2, aHat); Assert.IsFalse(enumAppenders.MoveNext()); } @@ -125,6 +128,7 @@ public void TestAppender2() } aHat = (CountingAppender?)log.GetAppender(a2.Name); + Assert.IsNotNull(aHat); Assert.AreSame(a2, aHat); // By appender. @@ -154,7 +158,7 @@ public void TestAdditivity1() { Logger a = (Logger)LogManager.GetLogger("a").Logger; Logger ab = (Logger)LogManager.GetLogger("a.b").Logger; - CountingAppender ca = new CountingAppender(); + var ca = new CountingAppender(); a.AddAppender(ca); Assert.IsNotNull(a.Repository); @@ -182,8 +186,8 @@ public void TestAdditivity2() Logger abc = (Logger)LogManager.GetLogger("a.b.c").Logger; Logger x = (Logger)LogManager.GetLogger("x").Logger; - CountingAppender ca1 = new CountingAppender(); - CountingAppender ca2 = new CountingAppender(); + var ca1 = new CountingAppender(); + var ca2 = new CountingAppender(); a.AddAppender(ca1); abc.AddAppender(ca2); @@ -217,9 +221,9 @@ public void TestAdditivity3() Logger ab = (Logger)LogManager.GetLogger("a.b").Logger; Logger abc = (Logger)LogManager.GetLogger("a.b.c").Logger; - CountingAppender caRoot = new CountingAppender(); - CountingAppender caA = new CountingAppender(); - CountingAppender caABC = new CountingAppender(); + var caRoot = new CountingAppender(); + var caA = new CountingAppender(); + var caABC = new CountingAppender(); root.AddAppender(caRoot); a.AddAppender(caA); @@ -255,7 +259,7 @@ public void TestAdditivity3() [Test] public void TestDisable1() { - CountingAppender caRoot = new CountingAppender(); + var caRoot = new CountingAppender(); Logger root = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; root.AddAppender(caRoot); @@ -308,8 +312,11 @@ public void TestDisable1() public void TestExists() { ILog a = LogManager.GetLogger("a"); + Assert.IsNotNull(a); ILog a_b = LogManager.GetLogger("a.b"); + Assert.IsNotNull(a_b); ILog a_b_c = LogManager.GetLogger("a.b.c"); + Assert.IsNotNull(a_b_c); ILog? t = LogManager.Exists("xx"); Assert.IsNull(t); @@ -327,7 +334,7 @@ public void TestExists() [Test] public void TestHierarchy1() { - Repository.Hierarchy.Hierarchy h = new Repository.Hierarchy.Hierarchy(); + var h = new Repository.Hierarchy.Hierarchy(); h.Root.Level = Level.Error; Logger a0 = (Logger)h.GetLogger("a"); @@ -339,4 +346,4 @@ public void TestHierarchy1() Assert.AreSame(a0, a1); } } -} \ No newline at end of file +} diff --git a/src/log4net.Tests/Util/LogLogTest.cs b/src/log4net.Tests/Util/LogLogTest.cs index d9fcf4fe..4aed3a2f 100644 --- a/src/log4net.Tests/Util/LogLogTest.cs +++ b/src/log4net.Tests/Util/LogLogTest.cs @@ -19,7 +19,7 @@ * */ -using System.Collections; +using System.Collections.Generic; using System.Diagnostics; using log4net.Util; using NUnit.Framework; @@ -71,7 +71,7 @@ public void EmitInternalMessages() [Test] public void LogReceivedAdapter() { - ArrayList messages = new ArrayList(); + var messages = new List(); using (new LogLog.LogReceivedAdapter(messages)) { @@ -86,26 +86,21 @@ public void LogReceivedAdapter() public class TraceListenerCounter : TraceListener { - private int count = 0; - - public override void Write(string message) + public override void Write(string? message) { - count++; + Count++; } - public override void WriteLine(string message) + public override void WriteLine(string? message) { Write(message); } public void Reset() { - count = 0; + Count = 0; } - public int Count - { - get { return count; } - } + public int Count { get; private set; } } } diff --git a/src/log4net.Tests/Util/PropertiesDictionaryTest.cs b/src/log4net.Tests/Util/PropertiesDictionaryTest.cs index 51cf6bf8..861b7acd 100644 --- a/src/log4net.Tests/Util/PropertiesDictionaryTest.cs +++ b/src/log4net.Tests/Util/PropertiesDictionaryTest.cs @@ -19,6 +19,7 @@ #if NET462_OR_GREATER +using System.Collections.Generic; using System.IO; using System.Runtime.Serialization.Formatters.Binary; @@ -49,6 +50,8 @@ public void TestSerialization() Assert.AreEqual(10, pd.Count, "Dictionary should have 10 items"); + Assert.IsNull(pd["notThere"], "Getter should act as IDictionary not IDictionary"); + // Serialize the properties into a memory stream BinaryFormatter formatter = new BinaryFormatter(); MemoryStream memory = new MemoryStream(); diff --git a/src/log4net/Config/BasicConfigurator.cs b/src/log4net/Config/BasicConfigurator.cs index be31939a..7af9f901 100644 --- a/src/log4net/Config/BasicConfigurator.cs +++ b/src/log4net/Config/BasicConfigurator.cs @@ -19,6 +19,7 @@ using System; using System.Collections; +using System.Collections.Generic; using System.Reflection; using log4net.Appender; @@ -49,10 +50,8 @@ namespace log4net.Config /// /// Nicko Cadell /// Gert Driesen - public sealed class BasicConfigurator + public static class BasicConfigurator { - #region Private Static Fields - /// /// The fully qualified type of the BasicConfigurator class. /// @@ -62,26 +61,6 @@ public sealed class BasicConfigurator /// private static readonly Type declaringType = typeof(BasicConfigurator); - #endregion Private Static Fields - - #region Private Instance Constructors - - /// - /// Initializes a new instance of the class. - /// - /// - /// - /// Uses a private access modifier to prevent instantiation of this class. - /// - /// - private BasicConfigurator() - { - } - - #endregion Private Instance Constructors - - #region Public Static Methods - /// /// Initializes the log4net system with a default configuration. /// @@ -96,7 +75,7 @@ private BasicConfigurator() /// public static ICollection Configure() { - return BasicConfigurator.Configure(LogManager.GetRepository(Assembly.GetCallingAssembly())); + return Configure(LogManager.GetRepository(Assembly.GetCallingAssembly())); } /// @@ -110,7 +89,7 @@ public static ICollection Configure() /// public static ICollection Configure(params IAppender[] appenders) { - ArrayList configurationMessages = new ArrayList(); + var configurationMessages = new List(); ILoggerRepository repository = LogManager.GetRepository(Assembly.GetCallingAssembly()); @@ -124,20 +103,6 @@ public static ICollection Configure(params IAppender[] appenders) return configurationMessages; } - /// - /// Initializes the log4net system using the specified appender. - /// - /// The appender to use to log all logging events. - /// - /// - /// Initializes the log4net system using the specified appender. - /// - /// - public static ICollection Configure(IAppender appender) - { - return Configure(new IAppender[] { appender }); - } - /// /// Initializes the with a default configuration. /// @@ -153,18 +118,16 @@ public static ICollection Configure(IAppender appender) /// public static ICollection Configure(ILoggerRepository repository) { - ArrayList configurationMessages = new ArrayList(); + var configurationMessages = new List(); using (new LogLog.LogReceivedAdapter(configurationMessages)) { // Create the layout - PatternLayout layout = new PatternLayout(); - layout.ConversionPattern = PatternLayout.DetailConversionPattern; + var layout = new PatternLayout { ConversionPattern = PatternLayout.DetailConversionPattern }; layout.ActivateOptions(); // Create the appender - ConsoleAppender appender = new ConsoleAppender(); - appender.Layout = layout; + var appender = new ConsoleAppender { Layout = layout }; appender.ActivateOptions(); InternalConfigure(repository, appender); @@ -175,21 +138,6 @@ public static ICollection Configure(ILoggerRepository repository) return configurationMessages; } - /// - /// Initializes the using the specified appender. - /// - /// The repository to configure. - /// The appender to use to log all logging events. - /// - /// - /// Initializes the using the specified appender. - /// - /// - public static ICollection Configure(ILoggerRepository repository, IAppender appender) - { - return Configure(repository, new IAppender[] { appender }); - } - /// /// Initializes the using the specified appenders. /// @@ -202,7 +150,7 @@ public static ICollection Configure(ILoggerRepository repository, IAppender appe /// public static ICollection Configure(ILoggerRepository repository, params IAppender[] appenders) { - ArrayList configurationMessages = new ArrayList(); + var configurationMessages = new List(); using (new LogLog.LogReceivedAdapter(configurationMessages)) { @@ -216,17 +164,14 @@ public static ICollection Configure(ILoggerRepository repository, params IAppend private static void InternalConfigure(ILoggerRepository repository, params IAppender[] appenders) { - IBasicRepositoryConfigurator configurableRepository = repository as IBasicRepositoryConfigurator; - if (configurableRepository != null) + if (repository is IBasicRepositoryConfigurator configurableRepository) { configurableRepository.Configure(appenders); } else { - LogLog.Warn(declaringType, "BasicConfigurator: Repository [" + repository + "] does not support the BasicConfigurator"); + LogLog.Warn(declaringType, $"BasicConfigurator: Repository [{repository}] does not support the BasicConfigurator"); } } - - #endregion Public Static Methods } -} \ No newline at end of file +} diff --git a/src/log4net/Config/XmlConfigurator.cs b/src/log4net/Config/XmlConfigurator.cs index 48f22c3a..29ecbabd 100644 --- a/src/log4net/Config/XmlConfigurator.cs +++ b/src/log4net/Config/XmlConfigurator.cs @@ -20,6 +20,7 @@ using System; using System.Xml; using System.Collections; +using System.Collections.Concurrent; using System.IO; using System.Reflection; using System.Threading; @@ -27,34 +28,17 @@ using log4net.Util; using log4net.Repository; +using System.Collections.Generic; namespace log4net.Config { /// - /// Use this class to initialize the log4net environment using an Xml tree. + /// Configures a using an XML tree. /// - /// - /// - /// Configures a using an Xml tree. - /// - /// /// Nicko Cadell /// Gert Driesen - public sealed class XmlConfigurator + public static class XmlConfigurator { - #region Private Instance Constructors - - /// - /// Private constructor - /// - private XmlConfigurator() - { - } - - #endregion Protected Instance Constructors - - #region Configure static methods - /// /// Automatically configures the using settings /// stored in the application's configuration file. @@ -77,7 +61,7 @@ private XmlConfigurator() /// The repository to configure. public static ICollection Configure(ILoggerRepository repository) { - ArrayList configurationMessages = new ArrayList(); + var configurationMessages = new List(); using (new LogLog.LogReceivedAdapter(configurationMessages)) { @@ -91,11 +75,11 @@ public static ICollection Configure(ILoggerRepository repository) private static void InternalConfigure(ILoggerRepository repository) { - LogLog.Debug(declaringType, "configuring repository [" + repository.Name + "] using .config file section"); + LogLog.Debug(declaringType, $"configuring repository [{repository.Name}] using .config file section"); try { - LogLog.Debug(declaringType, "Application config file is [" + SystemInfo.ConfigurationFileLocation + "]"); + LogLog.Debug(declaringType, $"Application config file is [{SystemInfo.ConfigurationFileLocation}]"); } catch { @@ -105,8 +89,7 @@ private static void InternalConfigure(ILoggerRepository repository) try { - XmlElement configElement = System.Configuration.ConfigurationManager.GetSection("log4net") as XmlElement; - if (configElement == null) + if (System.Configuration.ConfigurationManager.GetSection("log4net") is not XmlElement configElement) { // Failed to load the xml config using configuration settings handler LogLog.Error(declaringType, "Failed to find configuration section 'log4net' in the application's .config file. Check your .config file for the and elements. The configuration section should look like:
"); @@ -119,7 +102,7 @@ private static void InternalConfigure(ILoggerRepository repository) } catch (System.Configuration.ConfigurationException confEx) { - if (confEx.BareMessage.IndexOf("Unrecognized element") >= 0) + if (confEx.BareMessage.IndexOf("Unrecognized element", StringComparison.Ordinal) >= 0) { // Looks like the XML file is not valid LogLog.Error(declaringType, "Failed to parse config file. Check your .config file is well formed XML.", confEx); @@ -170,7 +153,7 @@ public static ICollection Configure() /// The element to parse. public static ICollection Configure(XmlElement element) { - ArrayList configurationMessages = new ArrayList(); + var configurationMessages = new List(); ILoggerRepository repository = LogManager.GetRepository(Assembly.GetCallingAssembly()); @@ -195,7 +178,7 @@ public static ICollection Configure(XmlElement element) /// the log4net configuration data. /// /// - /// The log4net configuration file can possible be specified in the application's + /// The log4net configuration file can possibly be specified in the application's /// configuration file (either MyAppName.exe.config for a /// normal application on Web.config for an ASP.NET application). /// @@ -236,7 +219,7 @@ public static ICollection Configure(XmlElement element) /// public static ICollection Configure(FileInfo configFile) { - ArrayList configurationMessages = new ArrayList(); + var configurationMessages = new List(); using (new LogLog.LogReceivedAdapter(configurationMessages)) { @@ -262,7 +245,7 @@ public static ICollection Configure(FileInfo configFile) /// public static ICollection Configure(Uri configUri) { - ArrayList configurationMessages = new ArrayList(); + var configurationMessages = new List(); ILoggerRepository repository = LogManager.GetRepository(Assembly.GetCallingAssembly()); using (new LogLog.LogReceivedAdapter(configurationMessages)) @@ -291,7 +274,7 @@ public static ICollection Configure(Uri configUri) /// public static ICollection Configure(Stream configStream) { - ArrayList configurationMessages = new ArrayList(); + var configurationMessages = new List(); ILoggerRepository repository = LogManager.GetRepository(Assembly.GetCallingAssembly()); using (new LogLog.LogReceivedAdapter(configurationMessages)) @@ -316,7 +299,7 @@ public static ICollection Configure(Stream configStream) /// The element to parse. public static ICollection Configure(ILoggerRepository repository, XmlElement element) { - ArrayList configurationMessages = new ArrayList(); + var configurationMessages = new List(); using (new LogLog.LogReceivedAdapter(configurationMessages)) { @@ -343,7 +326,7 @@ public static ICollection Configure(ILoggerRepository repository, XmlElement ele /// the configuration data. /// /// - /// The log4net configuration file can possible be specified in the application's + /// The log4net configuration file can possibly be specified in the application's /// configuration file (either MyAppName.exe.config for a /// normal application on Web.config for an ASP.NET application). /// @@ -384,7 +367,7 @@ public static ICollection Configure(ILoggerRepository repository, XmlElement ele /// public static ICollection Configure(ILoggerRepository repository, FileInfo configFile) { - ArrayList configurationMessages = new ArrayList(); + var configurationMessages = new List(); using (new LogLog.LogReceivedAdapter(configurationMessages)) { @@ -396,11 +379,11 @@ public static ICollection Configure(ILoggerRepository repository, FileInfo confi return configurationMessages; } - private static void InternalConfigure(ILoggerRepository repository, FileInfo configFile) + private static void InternalConfigure(ILoggerRepository repository, FileInfo? configFile) { - LogLog.Debug(declaringType, "configuring repository [" + repository.Name + "] using file [" + configFile + "]"); + LogLog.Debug(declaringType, $"configuring repository [{repository.Name}] using file [{configFile}]"); - if (configFile == null) + if (configFile is null) { LogLog.Error(declaringType, "Configure called with null 'configFile' parameter"); } @@ -411,7 +394,7 @@ private static void InternalConfigure(ILoggerRepository repository, FileInfo con if (File.Exists(configFile.FullName)) { // Open the file for reading - FileStream fs = null; + FileStream? fs = null; // Try hard to open the file for (int retry = 5; --retry >= 0;) @@ -425,16 +408,16 @@ private static void InternalConfigure(ILoggerRepository repository, FileInfo con { if (retry == 0) { - LogLog.Error(declaringType, "Failed to open XML config file [" + configFile.Name + "]", ex); + LogLog.Error(declaringType, $"Failed to open XML config file [{configFile.Name}]", ex); // The stream cannot be valid fs = null; } - System.Threading.Thread.Sleep(250); + Thread.Sleep(250); } } - if (fs != null) + if (fs is not null) { try { @@ -473,7 +456,7 @@ private static void InternalConfigure(ILoggerRepository repository, FileInfo con /// public static ICollection Configure(ILoggerRepository repository, Uri configUri) { - ArrayList configurationMessages = new ArrayList(); + var configurationMessages = new List(); using (new LogLog.LogReceivedAdapter(configurationMessages)) { @@ -485,11 +468,11 @@ public static ICollection Configure(ILoggerRepository repository, Uri configUri) return configurationMessages; } - private static void InternalConfigure(ILoggerRepository repository, Uri configUri) + private static void InternalConfigure(ILoggerRepository repository, Uri? configUri) { - LogLog.Debug(declaringType, "configuring repository [" + repository.Name + "] using URI [" + configUri + "]"); + LogLog.Debug(declaringType, $"configuring repository [{repository.Name}] using URI [{configUri}]"); - if (configUri == null) + if (configUri is null) { LogLog.Error(declaringType, "Configure called with null 'configUri' parameter"); } @@ -503,7 +486,7 @@ private static void InternalConfigure(ILoggerRepository repository, Uri configUr else { // NETCF dose not support WebClient - WebRequest configRequest = null; + WebRequest? configRequest = null; try { @@ -511,10 +494,10 @@ private static void InternalConfigure(ILoggerRepository repository, Uri configUr } catch (Exception ex) { - LogLog.Error(declaringType, "Failed to create WebRequest for URI [" + configUri + "]", ex); + LogLog.Error(declaringType, $"Failed to create WebRequest for URI [{configUri}]", ex); } - if (configRequest != null) + if (configRequest is not null) { // authentication may be required, set client to use default credentials try @@ -527,8 +510,8 @@ private static void InternalConfigure(ILoggerRepository repository, Uri configUr } try { - using WebResponse response = configRequest.GetResponse(); - if (response != null) + using WebResponse? response = configRequest.GetResponse(); + if (response is not null) { using var configStream = response.GetResponseStream(); InternalConfigure(repository, configStream); @@ -536,7 +519,7 @@ private static void InternalConfigure(ILoggerRepository repository, Uri configUr } catch (Exception ex) { - LogLog.Error(declaringType, "Failed to request config from URI [" + configUri + "]", ex); + LogLog.Error(declaringType, $"Failed to request config from URI [{configUri}]", ex); } } } @@ -561,7 +544,7 @@ private static void InternalConfigure(ILoggerRepository repository, Uri configUr /// public static ICollection Configure(ILoggerRepository repository, Stream configStream) { - ArrayList configurationMessages = new ArrayList(); + var configurationMessages = new List(); using (new LogLog.LogReceivedAdapter(configurationMessages)) { @@ -573,22 +556,22 @@ public static ICollection Configure(ILoggerRepository repository, Stream configS return configurationMessages; } - private static void InternalConfigure(ILoggerRepository repository, Stream configStream) + private static void InternalConfigure(ILoggerRepository repository, Stream? configStream) { - LogLog.Debug(declaringType, "configuring repository [" + repository.Name + "] using stream"); + LogLog.Debug(declaringType, $"configuring repository [{repository.Name}] using stream"); - if (configStream == null) + if (configStream is null) { LogLog.Error(declaringType, "Configure called with null 'configStream' parameter"); } else { // Load the config file into a document - XmlDocument doc = new XmlDocument { XmlResolver = null }; + XmlDocument? doc = new XmlDocument { XmlResolver = null }; try { // Allow the DTD to specify entity includes - XmlReaderSettings settings = new XmlReaderSettings(); + var settings = new XmlReaderSettings(); // .NET 4.0 warning CS0618: 'System.Xml.XmlReaderSettings.ProhibitDtd' // is obsolete: 'Use XmlReaderSettings.DtdProcessing property instead.' settings.DtdProcessing = DtdProcessing.Ignore; @@ -607,7 +590,7 @@ private static void InternalConfigure(ILoggerRepository repository, Stream confi doc = null; } - if (doc != null) + if (doc is not null) { LogLog.Debug(declaringType, "loading XML configuration"); @@ -619,7 +602,7 @@ private static void InternalConfigure(ILoggerRepository repository, Stream confi } else if (configNodeList.Count > 1) { - LogLog.Error(declaringType, "XML configuration contains [" + configNodeList.Count + "] elements. Only one is allowed. Configuration Aborted."); + LogLog.Error(declaringType, $"XML configuration contains [{configNodeList.Count}] elements. Only one is allowed. Configuration Aborted."); } else { @@ -629,10 +612,6 @@ private static void InternalConfigure(ILoggerRepository repository, Stream confi } } - #endregion Configure static methods - - #region ConfigureAndWatch static methods - /// /// Configures log4net using the file specified, monitors the file for changes /// and reloads the configuration if a change is detected. @@ -656,7 +635,7 @@ private static void InternalConfigure(ILoggerRepository repository, Stream confi /// public static ICollection ConfigureAndWatch(FileInfo configFile) { - ArrayList configurationMessages = new ArrayList(); + var configurationMessages = new List(); ILoggerRepository repository = LogManager.GetRepository(Assembly.GetCallingAssembly()); @@ -695,7 +674,7 @@ public static ICollection ConfigureAndWatch(FileInfo configFile) /// public static ICollection ConfigureAndWatch(ILoggerRepository repository, FileInfo configFile) { - ArrayList configurationMessages = new ArrayList(); + var configurationMessages = new List(); using (new LogLog.LogReceivedAdapter(configurationMessages)) { @@ -707,9 +686,9 @@ public static ICollection ConfigureAndWatch(ILoggerRepository repository, FileIn return configurationMessages; } - private static void InternalConfigureAndWatch(ILoggerRepository repository, FileInfo configFile) + private static void InternalConfigureAndWatch(ILoggerRepository repository, FileInfo? configFile) { - LogLog.Debug(declaringType, "configuring repository [" + repository.Name + "] using file [" + configFile + "] watching for file updates"); + LogLog.Debug(declaringType, $"configuring repository [{repository.Name}] using file [{configFile}] watching for file updates"); if (configFile == null) { @@ -722,35 +701,26 @@ private static void InternalConfigureAndWatch(ILoggerRepository repository, File try { - lock (m_repositoryName2ConfigAndWatchHandler) - { - // support multiple repositories each having their own watcher - ConfigureAndWatchHandler handler = - (ConfigureAndWatchHandler)m_repositoryName2ConfigAndWatchHandler[configFile.FullName]; - - if (handler != null) + // Support multiple repositories each having their own watcher. + // Create and start a watch handler that will reload the + // configuration whenever the config file is modified. + m_repositoryName2ConfigAndWatchHandler.AddOrUpdate( + configFile.FullName, + _ => new ConfigureAndWatchHandler(repository, configFile), + (_, handler) => { - m_repositoryName2ConfigAndWatchHandler.Remove(configFile.FullName); + // Replace the old handler. handler.Dispose(); - } - - // Create and start a watch handler that will reload the - // configuration whenever the config file is modified. - handler = new ConfigureAndWatchHandler(repository, configFile); - m_repositoryName2ConfigAndWatchHandler[configFile.FullName] = handler; - } + return new ConfigureAndWatchHandler(repository, configFile); + }); } catch (Exception ex) { - LogLog.Error(declaringType, "Failed to initialize configuration file watcher for file [" + configFile.FullName + "]", ex); + LogLog.Error(declaringType, $"Failed to initialize configuration file watcher for file [{configFile.FullName}]", ex); } } } - #endregion ConfigureAndWatch static methods - - #region ConfigureAndWatchHandler - /// /// Class used to watch config files. /// @@ -772,17 +742,17 @@ private sealed class ConfigureAndWatchHandler : IDisposable /// /// Holds the FileInfo used to configure the XmlConfigurator /// - private FileInfo m_configFile; + private readonly FileInfo m_configFile; /// /// Holds the repository being configured. /// - private ILoggerRepository m_repository; + private readonly ILoggerRepository m_repository; /// /// The timer used to compress the notification events. /// - private Timer m_timer; + private readonly Timer m_timer; /// /// The default amount of time to wait after receiving notification @@ -794,7 +764,7 @@ private sealed class ConfigureAndWatchHandler : IDisposable /// Watches file for changes. This object should be disposed when no longer /// needed to free system handles on the watched resources. /// - private FileSystemWatcher m_watcher; + private readonly FileSystemWatcher m_watcher; /// /// Initializes a new instance of the class to @@ -814,25 +784,24 @@ public ConfigureAndWatchHandler(ILoggerRepository repository, FileInfo configFil m_configFile = configFile; // Create a new FileSystemWatcher and set its properties. - m_watcher = new FileSystemWatcher(); - - m_watcher.Path = m_configFile.DirectoryName; - m_watcher.Filter = m_configFile.Name; - - // Set the notification filters - m_watcher.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.LastWrite | NotifyFilters.FileName; + m_watcher = new FileSystemWatcher() + { + Path = m_configFile.DirectoryName, + Filter = m_configFile.Name, + NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.LastWrite | NotifyFilters.FileName, + }; // Add event handlers. OnChanged will do for all event handlers that fire a FileSystemEventArgs - m_watcher.Changed += new FileSystemEventHandler(ConfigureAndWatchHandler_OnChanged); - m_watcher.Created += new FileSystemEventHandler(ConfigureAndWatchHandler_OnChanged); - m_watcher.Deleted += new FileSystemEventHandler(ConfigureAndWatchHandler_OnChanged); - m_watcher.Renamed += new RenamedEventHandler(ConfigureAndWatchHandler_OnRenamed); + m_watcher.Changed += ConfigureAndWatchHandler_OnChanged; + m_watcher.Created += ConfigureAndWatchHandler_OnChanged; + m_watcher.Deleted += ConfigureAndWatchHandler_OnChanged; + m_watcher.Renamed += ConfigureAndWatchHandler_OnRenamed; // Begin watching. m_watcher.EnableRaisingEvents = true; // Create the timer that will be used to deliver events. Set as disabled - m_timer = new Timer(new TimerCallback(OnWatchedFileChange), null, Timeout.Infinite, Timeout.Infinite); + m_timer = new Timer(OnWatchedFileChange, state: null, Timeout.Infinite, Timeout.Infinite); } /// @@ -847,7 +816,7 @@ public ConfigureAndWatchHandler(ILoggerRepository repository, FileInfo configFil /// private void ConfigureAndWatchHandler_OnChanged(object source, FileSystemEventArgs e) { - LogLog.Debug(declaringType, "ConfigureAndWatchHandler: " + e.ChangeType + " [" + m_configFile.FullName + "]"); + LogLog.Debug(declaringType, $"ConfigureAndWatchHandler: {e.ChangeType} [{m_configFile.FullName}]"); // Deliver the event in TimeoutMillis time // timer will fire only once @@ -866,7 +835,7 @@ private void ConfigureAndWatchHandler_OnChanged(object source, FileSystemEventAr /// private void ConfigureAndWatchHandler_OnRenamed(object source, RenamedEventArgs e) { - LogLog.Debug(declaringType, "ConfigureAndWatchHandler: " + e.ChangeType + " [" + m_configFile.FullName + "]"); + LogLog.Debug(declaringType, $"ConfigureAndWatchHandler: {e.ChangeType} [{m_configFile.FullName}]"); // Deliver the event in TimeoutMillis time // timer will fire only once @@ -894,10 +863,6 @@ public void Dispose() } } - #endregion ConfigureAndWatchHandler - - #region Private Static Methods - /// /// Configures the specified repository using a log4net element. /// @@ -913,13 +878,13 @@ public void Dispose() /// to load the configuration from an . /// /// - private static void InternalConfigureFromXml(ILoggerRepository repository, XmlElement element) + private static void InternalConfigureFromXml(ILoggerRepository? repository, XmlElement? element) { - if (element == null) + if (element is null) { LogLog.Error(declaringType, "ConfigureFromXml called with null 'element' parameter"); } - else if (repository == null) + else if (repository is null) { LogLog.Error(declaringType, "ConfigureFromXml called with null 'repository' parameter"); } @@ -927,8 +892,7 @@ private static void InternalConfigureFromXml(ILoggerRepository repository, XmlEl { LogLog.Debug(declaringType, "Configuring Repository [" + repository.Name + "]"); - IXmlRepositoryConfigurator configurableRepository = repository as IXmlRepositoryConfigurator; - if (configurableRepository == null) + if (repository is not IXmlRepositoryConfigurator configurableRepository) { LogLog.Warn(declaringType, "Repository [" + repository + "] does not support the XmlConfigurator"); } @@ -946,16 +910,12 @@ private static void InternalConfigureFromXml(ILoggerRepository repository, XmlEl } } - #endregion Private Static Methods - - #region Private Static Fields - /// /// Maps repository names to ConfigAndWatchHandler instances to allow a particular /// ConfigAndWatchHandler to dispose of its FileSystemWatcher when a repository is /// reconfigured. /// - private static readonly Hashtable m_repositoryName2ConfigAndWatchHandler = new Hashtable(); + private static readonly ConcurrentDictionary m_repositoryName2ConfigAndWatchHandler = new(StringComparer.Ordinal); /// /// The fully qualified type of the XmlConfigurator class. @@ -965,7 +925,5 @@ private static void InternalConfigureFromXml(ILoggerRepository repository, XmlEl /// log message. /// private static readonly Type declaringType = typeof(XmlConfigurator); - - #endregion Private Static Fields } -} \ No newline at end of file +} diff --git a/src/log4net/Config/XmlConfiguratorAttribute.cs b/src/log4net/Config/XmlConfiguratorAttribute.cs index b6d6c249..3579cdae 100644 --- a/src/log4net/Config/XmlConfiguratorAttribute.cs +++ b/src/log4net/Config/XmlConfiguratorAttribute.cs @@ -18,7 +18,7 @@ #endregion using System; -using System.Collections; +using System.Collections.Generic; using System.Reflection; using System.IO; @@ -26,6 +26,8 @@ using log4net.Repository; using log4net.Repository.Hierarchy; +#nullable enable + namespace log4net.Config { /// @@ -95,8 +97,6 @@ public XmlConfiguratorAttribute() : base(0) /* configurator priority 0 */ { } - #region Public Instance Properties - /// /// Gets or sets the filename of the configuration file. /// @@ -113,18 +113,11 @@ public XmlConfiguratorAttribute() : base(0) /* configurator priority 0 */ /// The takes priority over the . /// /// - public string ConfigFile - { - get { return m_configFile; } - set { m_configFile = value; } - } + public string? ConfigFile { get; set; } /// /// Gets or sets the extension of the configuration file. /// - /// - /// The extension of the configuration file. - /// /// /// /// If specified this is the extension for the configuration file. @@ -141,11 +134,7 @@ public string ConfigFile /// The takes priority over the . /// /// - public string ConfigFileExtension - { - get { return m_configFileExtension; } - set { m_configFileExtension = value; } - } + public string? ConfigFileExtension { get; set; } /// /// Gets or sets a value indicating whether to watch the configuration file. @@ -169,15 +158,7 @@ public string ConfigFileExtension /// Watching configuration is not supported on the SSCLI. /// /// - public bool Watch - { - get { return m_configureAndWatch; } - set { m_configureAndWatch = value; } - } - - #endregion Public Instance Properties - - #region Override ConfiguratorAttribute + public bool Watch { get; set; } /// /// Configures the for the specified assembly. @@ -195,11 +176,11 @@ public bool Watch /// The does not extend . public override void Configure(Assembly sourceAssembly, ILoggerRepository targetRepository) { - IList configurationMessages = new ArrayList(); + var configurationMessages = new List(); using (new LogLog.LogReceivedAdapter(configurationMessages)) { - string applicationBaseDirectory = null; + string? applicationBaseDirectory = null; try { applicationBaseDirectory = SystemInfo.ApplicationBaseDirectory; @@ -210,21 +191,19 @@ public override void Configure(Assembly sourceAssembly, ILoggerRepository target // and the application does not have PathDiscovery permission } - if (applicationBaseDirectory == null || (new Uri(applicationBaseDirectory)).IsFile) + if (applicationBaseDirectory is null || (new Uri(applicationBaseDirectory)).IsFile) { ConfigureFromFile(sourceAssembly, targetRepository); } else { - ConfigureFromUri(sourceAssembly, targetRepository); + ConfigureFromUri(targetRepository); } } targetRepository.ConfigurationMessages = configurationMessages; } - #endregion - /// /// Attempt to load configuration from the local file system /// @@ -233,12 +212,12 @@ public override void Configure(Assembly sourceAssembly, ILoggerRepository target private void ConfigureFromFile(Assembly sourceAssembly, ILoggerRepository targetRepository) { // Work out the full path to the config file - string fullPath2ConfigFile = null; + string? fullPath2ConfigFile = null; // Select the config file - if (m_configFile == null || m_configFile.Length == 0) + if (string.IsNullOrEmpty(ConfigFile)) { - if (m_configFileExtension == null || m_configFileExtension.Length == 0) + if (string.IsNullOrEmpty(ConfigFileExtension)) { // Use the default .config file for the AppDomain try @@ -253,12 +232,12 @@ private void ConfigureFromFile(Assembly sourceAssembly, ILoggerRepository target else { // Force the extension to start with a '.' - if (m_configFileExtension[0] != '.') + if (ConfigFileExtension![0] != '.') { - m_configFileExtension = "." + m_configFileExtension; + ConfigFileExtension = '.' + ConfigFileExtension; } - string applicationBaseDirectory = null; + string? applicationBaseDirectory = null; try { applicationBaseDirectory = SystemInfo.ApplicationBaseDirectory; @@ -268,36 +247,36 @@ private void ConfigureFromFile(Assembly sourceAssembly, ILoggerRepository target LogLog.Error(declaringType, "Exception getting ApplicationBaseDirectory. Must be able to resolve ApplicationBaseDirectory and AssemblyFileName when ConfigFileExtension property is set.", ex); } - if (applicationBaseDirectory != null) + if (applicationBaseDirectory is not null) { - fullPath2ConfigFile = Path.Combine(applicationBaseDirectory, SystemInfo.AssemblyFileName(sourceAssembly) + m_configFileExtension); + fullPath2ConfigFile = Path.Combine(applicationBaseDirectory, SystemInfo.AssemblyFileName(sourceAssembly) + ConfigFileExtension); } } } else { - string applicationBaseDirectory = null; + string? applicationBaseDirectory = null; try { applicationBaseDirectory = SystemInfo.ApplicationBaseDirectory; } catch (Exception ex) { - LogLog.Warn(declaringType, "Exception getting ApplicationBaseDirectory. ConfigFile property path [" + m_configFile + "] will be treated as an absolute path.", ex); + LogLog.Warn(declaringType, $"Exception getting ApplicationBaseDirectory. ConfigFile property path [{ConfigFile}] will be treated as an absolute path.", ex); } - if (applicationBaseDirectory != null) + if (applicationBaseDirectory is not null) { // Just the base dir + the config file - fullPath2ConfigFile = Path.Combine(applicationBaseDirectory, m_configFile); + fullPath2ConfigFile = Path.Combine(applicationBaseDirectory, ConfigFile!); } else { - fullPath2ConfigFile = m_configFile; + fullPath2ConfigFile = ConfigFile; } } - if (fullPath2ConfigFile != null) + if (fullPath2ConfigFile is not null) { ConfigureFromFile(targetRepository, new FileInfo(fullPath2ConfigFile)); } @@ -311,7 +290,7 @@ private void ConfigureFromFile(Assembly sourceAssembly, ILoggerRepository target private void ConfigureFromFile(ILoggerRepository targetRepository, FileInfo configFile) { // Do we configure just once or do we configure and then watch? - if (m_configureAndWatch) + if (Watch) { XmlConfigurator.ConfigureAndWatch(targetRepository, configFile); } @@ -324,19 +303,18 @@ private void ConfigureFromFile(ILoggerRepository targetRepository, FileInfo conf /// /// Attempt to load configuration from a URI /// - /// The assembly that this attribute was defined on. /// The repository to configure. - private void ConfigureFromUri(Assembly sourceAssembly, ILoggerRepository targetRepository) + private void ConfigureFromUri(ILoggerRepository targetRepository) { // Work out the full path to the config file - Uri fullPath2ConfigFile = null; + Uri? fullPath2ConfigFile = null; // Select the config file - if (m_configFile == null || m_configFile.Length == 0) + if (string.IsNullOrEmpty(ConfigFile)) { - if (m_configFileExtension == null || m_configFileExtension.Length == 0) + if (string.IsNullOrEmpty(ConfigFileExtension)) { - string systemConfigFilePath = null; + string? systemConfigFilePath = null; try { systemConfigFilePath = SystemInfo.ConfigurationFileLocation; @@ -346,23 +324,21 @@ private void ConfigureFromUri(Assembly sourceAssembly, ILoggerRepository targetR LogLog.Error(declaringType, "XmlConfiguratorAttribute: Exception getting ConfigurationFileLocation. Must be able to resolve ConfigurationFileLocation when ConfigFile and ConfigFileExtension properties are not set.", ex); } - if (systemConfigFilePath != null) + if (systemConfigFilePath is not null) { - Uri systemConfigFileUri = new Uri(systemConfigFilePath); - // Use the default .config file for the AppDomain - fullPath2ConfigFile = systemConfigFileUri; + fullPath2ConfigFile = new Uri(systemConfigFilePath); } } else { // Force the extension to start with a '.' - if (m_configFileExtension[0] != '.') + if (ConfigFileExtension![0] != '.') { - m_configFileExtension = "." + m_configFileExtension; + ConfigFileExtension = '.' + ConfigFileExtension; } - string systemConfigFilePath = null; + string? systemConfigFilePath = null; try { systemConfigFilePath = SystemInfo.ConfigurationFileLocation; @@ -372,18 +348,18 @@ private void ConfigureFromUri(Assembly sourceAssembly, ILoggerRepository targetR LogLog.Error(declaringType, "XmlConfiguratorAttribute: Exception getting ConfigurationFileLocation. Must be able to resolve ConfigurationFileLocation when the ConfigFile property are not set.", ex); } - if (systemConfigFilePath != null) + if (systemConfigFilePath is not null) { - UriBuilder builder = new UriBuilder(new Uri(systemConfigFilePath)); + var builder = new UriBuilder(new Uri(systemConfigFilePath)); // Remove the current extension from the systemConfigFileUri path string path = builder.Path; - int startOfExtension = path.LastIndexOf("."); + int startOfExtension = path.LastIndexOf('.'); if (startOfExtension >= 0) { path = path.Substring(0, startOfExtension); } - path += m_configFileExtension; + path += ConfigFileExtension; builder.Path = path; fullPath2ConfigFile = builder.Uri; @@ -392,38 +368,38 @@ private void ConfigureFromUri(Assembly sourceAssembly, ILoggerRepository targetR } else { - string applicationBaseDirectory = null; + string? applicationBaseDirectory = null; try { applicationBaseDirectory = SystemInfo.ApplicationBaseDirectory; } catch (Exception ex) { - LogLog.Warn(declaringType, "Exception getting ApplicationBaseDirectory. ConfigFile property path [" + m_configFile + "] will be treated as an absolute URI.", ex); + LogLog.Warn(declaringType, $"Exception getting ApplicationBaseDirectory. ConfigFile property path [{ConfigFile}] will be treated as an absolute URI.", ex); } - if (applicationBaseDirectory != null) + if (applicationBaseDirectory is not null) { // Just the base dir + the config file - fullPath2ConfigFile = new Uri(new Uri(applicationBaseDirectory), m_configFile); + fullPath2ConfigFile = new Uri(new Uri(applicationBaseDirectory), ConfigFile!); } else { - fullPath2ConfigFile = new Uri(m_configFile); + fullPath2ConfigFile = new Uri(ConfigFile!); } } - if (fullPath2ConfigFile != null) + if (fullPath2ConfigFile is not null) { if (fullPath2ConfigFile.IsFile) { - // The m_configFile could be an absolute local path, therefore we have to be + // The ConfigFile could be an absolute local path, therefore we have to be // prepared to switch back to using FileInfos here ConfigureFromFile(targetRepository, new FileInfo(fullPath2ConfigFile.LocalPath)); } else { - if (m_configureAndWatch) + if (Watch) { LogLog.Warn(declaringType, "XmlConfiguratorAttribute: Unable to watch config file loaded from a URI"); } @@ -432,16 +408,6 @@ private void ConfigureFromUri(Assembly sourceAssembly, ILoggerRepository targetR } } - #region Private Instance Fields - - private string m_configFile = null; - private string m_configFileExtension = null; - private bool m_configureAndWatch = false; - - #endregion Private Instance Fields - - #region Private Static Fields - /// /// The fully qualified type of the XmlConfiguratorAttribute class. /// @@ -450,7 +416,5 @@ private void ConfigureFromUri(Assembly sourceAssembly, ILoggerRepository targetR /// log message. /// private static readonly Type declaringType = typeof(XmlConfiguratorAttribute); - - #endregion Private Static Fields } -} \ No newline at end of file +} diff --git a/src/log4net/Core/IFixingRequired.cs b/src/log4net/Core/IFixingRequired.cs index 58e84cf3..2251135d 100644 --- a/src/log4net/Core/IFixingRequired.cs +++ b/src/log4net/Core/IFixingRequired.cs @@ -17,8 +17,6 @@ // #endregion -using System; - namespace log4net.Core { /// @@ -53,6 +51,6 @@ public interface IFixingRequired /// and logged from any thread with identical results. /// /// - object GetFixedObject(); + object? GetFixedObject(); } } diff --git a/src/log4net/Core/ILoggerWrapper.cs b/src/log4net/Core/ILoggerWrapper.cs index fefbd205..3edde25c 100644 --- a/src/log4net/Core/ILoggerWrapper.cs +++ b/src/log4net/Core/ILoggerWrapper.cs @@ -17,12 +17,6 @@ // #endregion -using System; - -using log4net; -using log4net.Core; -using log4net.Repository; - namespace log4net.Core { /// @@ -40,18 +34,14 @@ namespace log4net.Core public interface ILoggerWrapper { /// - /// Get the implementation behind this wrapper object. + /// Gets the object that implements this object. /// /// - /// The object that in implementing this object. /// /// /// - /// The object that in implementing this - /// object. The Logger object may not - /// be the same object as this object because of logger decorators. - /// This gets the actual underlying objects that is used to process - /// the log events. + /// The Logger object may not be the same object as this object because of logger decorators. + /// This gets the actual underlying objects that is used to process the log events. /// /// ILogger Logger { get; } diff --git a/src/log4net/Core/IOptionHandler.cs b/src/log4net/Core/IOptionHandler.cs index 6d73ee18..aadf71cd 100644 --- a/src/log4net/Core/IOptionHandler.cs +++ b/src/log4net/Core/IOptionHandler.cs @@ -17,8 +17,6 @@ // #endregion -using System; - namespace log4net.Core { /// diff --git a/src/log4net/Core/LocationInfo.cs b/src/log4net/Core/LocationInfo.cs index 5e8295e7..a05adca1 100644 --- a/src/log4net/Core/LocationInfo.cs +++ b/src/log4net/Core/LocationInfo.cs @@ -59,8 +59,6 @@ namespace log4net.Core [Serializable] public class LocationInfo { - #region Public Instance Constructors - /// /// Constructor /// @@ -72,16 +70,16 @@ public class LocationInfo /// class based on the current thread. /// /// - public LocationInfo(Type callerStackBoundaryDeclaringType) + public LocationInfo(Type? callerStackBoundaryDeclaringType) { // Initialize all fields - m_className = NA; - m_fileName = NA; - m_lineNumber = NA; - m_methodName = NA; - m_fullInfo = NA; + ClassName = NA; + FileName = NA; + LineNumber = NA; + MethodName = NA; + FullInfo = NA; - if (callerStackBoundaryDeclaringType != null) + if (callerStackBoundaryDeclaringType is not null) { try { @@ -114,35 +112,35 @@ public LocationInfo(Type callerStackBoundaryDeclaringType) { // take into account the frames we skip above int adjustedFrameCount = st.FrameCount - frameIndex; - ArrayList stackFramesList = new ArrayList(adjustedFrameCount); - m_stackFrames = new StackFrameItem[adjustedFrameCount]; + ArrayList stackFramesList = new ArrayList(adjustedFrameCount); + StackFrames = new StackFrameItem[adjustedFrameCount]; for (int i=frameIndex; i < st.FrameCount; i++) { stackFramesList.Add(new StackFrameItem(st.GetFrame(i))); } - stackFramesList.CopyTo(m_stackFrames, 0); + stackFramesList.CopyTo(StackFrames, 0); // now frameIndex is the first 'user' caller frame StackFrame locationFrame = st.GetFrame(frameIndex); - if (locationFrame != null) + if (locationFrame is not null) { System.Reflection.MethodBase method = locationFrame.GetMethod(); - if (method != null) + if (method is not null) { - m_methodName = method.Name; - if (method.DeclaringType != null) + MethodName = method.Name; + if (method.DeclaringType is not null) { - m_className = method.DeclaringType.FullName; + ClassName = method.DeclaringType.FullName; } } - m_fileName = locationFrame.GetFileName(); - m_lineNumber = locationFrame.GetFileLineNumber().ToString(System.Globalization.NumberFormatInfo.InvariantInfo); + FileName = locationFrame.GetFileName(); + LineNumber = locationFrame.GetFileLineNumber().ToString(System.Globalization.NumberFormatInfo.InvariantInfo); // Combine all location info - m_fullInfo = m_className + '.' + m_methodName + '(' + m_fileName + ':' + m_lineNumber + ')'; + FullInfo = ClassName + '.' + MethodName + '(' + FileName + ':' + LineNumber + ')'; } } } @@ -170,84 +168,33 @@ public LocationInfo(Type callerStackBoundaryDeclaringType) /// public LocationInfo(string className, string methodName, string fileName, string lineNumber) { - m_className = className; - m_fileName = fileName; - m_lineNumber = lineNumber; - m_methodName = methodName; - m_fullInfo = m_className + '.' + m_methodName + '(' + m_fileName + - ':' + m_lineNumber + ')'; + ClassName = className; + FileName = fileName; + LineNumber = lineNumber; + MethodName = methodName; + FullInfo = $"{ClassName}.{MethodName}({FileName}:{LineNumber})"; } - #endregion Public Instance Constructors - - #region Public Instance Properties - /// /// Gets the fully qualified class name of the caller making the logging /// request. /// - /// - /// The fully qualified class name of the caller making the logging - /// request. - /// - /// - /// - /// Gets the fully qualified class name of the caller making the logging - /// request. - /// - /// - public string ClassName - { - get { return m_className; } - } + public string? ClassName { get; } /// /// Gets the file name of the caller. /// - /// - /// The file name of the caller. - /// - /// - /// - /// Gets the file name of the caller. - /// - /// - public string FileName - { - get { return m_fileName; } - } + public string? FileName { get; } /// /// Gets the line number of the caller. /// - /// - /// The line number of the caller. - /// - /// - /// - /// Gets the line number of the caller. - /// - /// - public string LineNumber - { - get { return m_lineNumber; } - } + public string LineNumber { get; } /// /// Gets the method name of the caller. /// - /// - /// The method name of the caller. - /// - /// - /// - /// Gets the method name of the caller. - /// - /// - public string MethodName - { - get { return m_methodName; } - } + public string MethodName { get; } /// /// Gets all available caller information @@ -262,42 +209,21 @@ public string MethodName /// fully.qualified.classname.of.caller.methodName(Filename:line) /// /// - public string FullInfo - { - get { return m_fullInfo; } - } - + public string FullInfo { get; } + /// /// Gets the stack frames from the stack trace of the caller making the log request /// - public StackFrameItem[] StackFrames - { - get { return m_stackFrames; } - } - - #endregion Public Instance Properties - - #region Private Instance Fields - - private readonly string m_className; - private readonly string m_fileName; - private readonly string m_lineNumber; - private readonly string m_methodName; - private readonly string m_fullInfo; - private readonly StackFrameItem[] m_stackFrames; + public StackFrameItem[]? StackFrames { get; } - #endregion Private Instance Fields - - #region Private Static Fields - - /// - /// The fully qualified type of the LocationInfo class. - /// - /// - /// Used by the internal logger to record the Type of the - /// log message. - /// - private static readonly Type declaringType = typeof(LocationInfo); + /// + /// The fully qualified type of the LocationInfo class. + /// + /// + /// Used by the internal logger to record the Type of the + /// log message. + /// + private static readonly Type declaringType = typeof(LocationInfo); /// /// When location information is not available the constant @@ -305,7 +231,5 @@ public StackFrameItem[] StackFrames /// constant is ?. /// private const string NA = "?"; - - #endregion Private Static Fields } } diff --git a/src/log4net/Core/LoggerManager.cs b/src/log4net/Core/LoggerManager.cs index e09b4228..0a9a6915 100644 --- a/src/log4net/Core/LoggerManager.cs +++ b/src/log4net/Core/LoggerManager.cs @@ -18,12 +18,13 @@ #endregion using System; -using System.Runtime.InteropServices; using System.Reflection; - +using System.Text; using log4net.Util; using log4net.Repository; +#nullable enable + namespace log4net.Core { /// @@ -34,7 +35,7 @@ namespace log4net.Core /// Static manager that controls the creation of repositories /// /// - /// This class is used by the wrapper managers (e.g. ) + /// This class is used by the wrapper managers (e.g. ) /// to provide access to the objects. /// /// @@ -47,26 +48,8 @@ namespace log4net.Core /// /// Nicko Cadell /// Gert Driesen - public sealed class LoggerManager + public static class LoggerManager { - #region Private Instance Constructors - - /// - /// Private constructor to prevent instances. Only static methods should be used. - /// - /// - /// - /// Private constructor to prevent instances. Only static methods should be used. - /// - /// - private LoggerManager() - { - } - - #endregion Private Instance Constructors - - #region Static Constructor - /// /// Hook the shutdown event /// @@ -74,7 +57,7 @@ private LoggerManager() /// /// On the full .NET runtime, the static constructor hooks up the /// AppDomain.ProcessExit and AppDomain.DomainUnload> events. - /// These are used to shutdown the log4net system as the application exits. + /// These are used to shut down the log4net system as the application exits. /// /// static LoggerManager() @@ -99,48 +82,45 @@ static LoggerManager() // Set the default repository selector // Look for the RepositorySelector type specified in the AppSettings 'log4net.RepositorySelector' - string appRepositorySelectorTypeName = SystemInfo.GetAppSetting("log4net.RepositorySelector"); - if (appRepositorySelectorTypeName != null && appRepositorySelectorTypeName.Length > 0) + string? appRepositorySelectorTypeName = SystemInfo.GetAppSetting("log4net.RepositorySelector"); + if (!string.IsNullOrEmpty(appRepositorySelectorTypeName)) { // Resolve the config string into a Type - Type appRepositorySelectorType = null; + Type? appRepositorySelectorType = null; try { - appRepositorySelectorType = SystemInfo.GetTypeFromString(appRepositorySelectorTypeName, false, true); + appRepositorySelectorType = SystemInfo.GetTypeFromString(appRepositorySelectorTypeName!, false, true); } catch (Exception ex) { - LogLog.Error(declaringType, "Exception while resolving RepositorySelector Type [" + appRepositorySelectorTypeName + "]", ex); + LogLog.Error(declaringType, $"Exception while resolving RepositorySelector Type [{appRepositorySelectorTypeName}]", ex); } - if (appRepositorySelectorType != null) + if (appRepositorySelectorType is not null) { // Create an instance of the RepositorySelectorType - object appRepositorySelectorObj = null; + object? appRepositorySelectorObj = null; try { appRepositorySelectorObj = Activator.CreateInstance(appRepositorySelectorType); } catch (Exception ex) { - LogLog.Error(declaringType, "Exception while creating RepositorySelector [" + appRepositorySelectorType.FullName + "]", ex); + LogLog.Error(declaringType, $"Exception while creating RepositorySelector [{appRepositorySelectorType.FullName}]", ex); } - if (appRepositorySelectorObj != null && appRepositorySelectorObj is IRepositorySelector) + if (appRepositorySelectorObj is IRepositorySelector sel) { - RepositorySelector = (IRepositorySelector)appRepositorySelectorObj; + RepositorySelector = sel; } else { - LogLog.Error(declaringType, "RepositorySelector Type [" + appRepositorySelectorType.FullName + "] is not an IRepositorySelector"); + LogLog.Error(declaringType, $"RepositorySelector Type [{appRepositorySelectorType.FullName}] is not an IRepositorySelector"); } } } // Create the DefaultRepositorySelector if not configured above - if (RepositorySelector == null) - { - RepositorySelector = new DefaultRepositorySelector(typeof(log4net.Repository.Hierarchy.Hierarchy)); - } + RepositorySelector ??= new DefaultRepositorySelector(typeof(Repository.Hierarchy.Hierarchy)); } /// @@ -158,16 +138,12 @@ static LoggerManager() private static void RegisterAppDomainEvents() { // ProcessExit seems to be fired if we are part of the default domain - AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnProcessExit); + AppDomain.CurrentDomain.ProcessExit += OnProcessExit; // Otherwise DomainUnload is fired - AppDomain.CurrentDomain.DomainUnload += new EventHandler(OnDomainUnload); + AppDomain.CurrentDomain.DomainUnload += OnDomainUnload; } - #endregion Static Constructor - - #region Public Static Methods - /// /// Return the default instance. /// @@ -188,7 +164,7 @@ public static ILoggerRepository GetLoggerRepository(string repository) /// /// Returns the default instance. /// - /// The assembly to use to lookup the repository. + /// The assembly to use to look up the repository. /// The default instance. [Obsolete("Use GetRepository instead of GetLoggerRepository")] public static ILoggerRepository GetLoggerRepository(Assembly repositoryAssembly) @@ -209,9 +185,9 @@ public static ILoggerRepository GetLoggerRepository(Assembly repositoryAssembly) /// public static ILoggerRepository GetRepository(string repository) { - if (repository == null) + if (repository is null) { - throw new ArgumentNullException("repository"); + throw new ArgumentNullException(nameof(repository)); } return RepositorySelector.GetRepository(repository); } @@ -219,7 +195,7 @@ public static ILoggerRepository GetRepository(string repository) /// /// Returns the default instance. /// - /// The assembly to use to lookup the repository. + /// The assembly to use to look up the repository. /// The default instance. /// /// @@ -228,9 +204,9 @@ public static ILoggerRepository GetRepository(string repository) /// public static ILoggerRepository GetRepository(Assembly repositoryAssembly) { - if (repositoryAssembly == null) + if (repositoryAssembly is null) { - throw new ArgumentNullException("repositoryAssembly"); + throw new ArgumentNullException(nameof(repositoryAssembly)); } return RepositorySelector.GetRepository(repositoryAssembly); } @@ -251,15 +227,15 @@ public static ILoggerRepository GetRepository(Assembly repositoryAssembly) /// null. /// /// - public static ILogger Exists(string repository, string name) + public static ILogger? Exists(string repository, string name) { - if (repository == null) + if (repository is null) { - throw new ArgumentNullException("repository"); + throw new ArgumentNullException(nameof(repository)); } - if (name == null) + if (name is null) { - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); } return RepositorySelector.GetRepository(repository).Exists(name); } @@ -267,7 +243,7 @@ public static ILogger Exists(string repository, string name) /// /// Returns the named logger if it exists. /// - /// The assembly to use to lookup the repository. + /// The assembly to use to look up the repository. /// The fully qualified logger name to look for. /// /// The logger found, or null if the named logger does not exist in the @@ -280,15 +256,15 @@ public static ILogger Exists(string repository, string name) /// null. /// /// - public static ILogger Exists(Assembly repositoryAssembly, string name) + public static ILogger? Exists(Assembly repositoryAssembly, string name) { - if (repositoryAssembly == null) + if (repositoryAssembly is null) { - throw new ArgumentNullException("repositoryAssembly"); + throw new ArgumentNullException(nameof(repositoryAssembly)); } - if (name == null) + if (name is null) { - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); } return RepositorySelector.GetRepository(repositoryAssembly).Exists(name); } @@ -305,9 +281,9 @@ public static ILogger Exists(Assembly repositoryAssembly, string name) /// public static ILogger[] GetCurrentLoggers(string repository) { - if (repository == null) + if (repository is null) { - throw new ArgumentNullException("repository"); + throw new ArgumentNullException(nameof(repository)); } return RepositorySelector.GetRepository(repository).GetCurrentLoggers(); } @@ -315,7 +291,7 @@ public static ILogger[] GetCurrentLoggers(string repository) /// /// Returns all the currently defined loggers in the specified assembly's repository. /// - /// The assembly to use to lookup the repository. + /// The assembly to use to look up the repository. /// All the defined loggers. /// /// @@ -324,9 +300,9 @@ public static ILogger[] GetCurrentLoggers(string repository) /// public static ILogger[] GetCurrentLoggers(Assembly repositoryAssembly) { - if (repositoryAssembly == null) + if (repositoryAssembly is null) { - throw new ArgumentNullException("repositoryAssembly"); + throw new ArgumentNullException(nameof(repositoryAssembly)); } return RepositorySelector.GetRepository(repositoryAssembly).GetCurrentLoggers(); } @@ -352,13 +328,13 @@ public static ILogger[] GetCurrentLoggers(Assembly repositoryAssembly) /// public static ILogger GetLogger(string repository, string name) { - if (repository == null) + if (repository is null) { - throw new ArgumentNullException("repository"); + throw new ArgumentNullException(nameof(repository)); } - if (name == null) + if (name is null) { - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); } return RepositorySelector.GetRepository(repository).GetLogger(name); } @@ -366,7 +342,7 @@ public static ILogger GetLogger(string repository, string name) /// /// Retrieves or creates a named logger. /// - /// The assembly to use to lookup the repository. + /// The assembly to use to look up the repository. /// The name of the logger to retrieve. /// The logger with the name specified. /// @@ -384,13 +360,13 @@ public static ILogger GetLogger(string repository, string name) /// public static ILogger GetLogger(Assembly repositoryAssembly, string name) { - if (repositoryAssembly == null) + if (repositoryAssembly is null) { - throw new ArgumentNullException("repositoryAssembly"); + throw new ArgumentNullException(nameof(repositoryAssembly)); } - if (name == null) + if (name is null) { - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); } return RepositorySelector.GetRepository(repositoryAssembly).GetLogger(name); } @@ -408,13 +384,17 @@ public static ILogger GetLogger(Assembly repositoryAssembly, string name) /// public static ILogger GetLogger(string repository, Type type) { - if (repository == null) + if (repository is null) { - throw new ArgumentNullException("repository"); + throw new ArgumentNullException(nameof(repository)); } - if (type == null) + if (type is null) { - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); + } + if (type.FullName is null) + { + throw new ArgumentException($"Type {type} does not have a full name", nameof(type)); } return RepositorySelector.GetRepository(repository).GetLogger(type.FullName); } @@ -422,7 +402,7 @@ public static ILogger GetLogger(string repository, Type type) /// /// Shorthand for . /// - /// the assembly to use to lookup the repository + /// the assembly to use to look up the repository /// The of which the fullname will be used as the name of the logger to retrieve. /// The logger with the name specified. /// @@ -432,13 +412,17 @@ public static ILogger GetLogger(string repository, Type type) /// public static ILogger GetLogger(Assembly repositoryAssembly, Type type) { - if (repositoryAssembly == null) + if (repositoryAssembly is null) { - throw new ArgumentNullException("repositoryAssembly"); + throw new ArgumentNullException(nameof(repositoryAssembly)); } - if (type == null) + if (type is null) { - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); + } + if (type.FullName is null) + { + throw new ArgumentException($"Type {type} does not have a full name", nameof(type)); } return RepositorySelector.GetRepository(repositoryAssembly).GetLogger(type.FullName); } @@ -458,7 +442,7 @@ public static ILogger GetLogger(Assembly repositoryAssembly, Type type) /// /// /// The shutdown method is careful to close nested - /// appenders before closing regular appenders. This is allows + /// appenders before closing regular appenders. This allows /// configurations where a regular appender is attached to a logger /// and again to a nested appender. /// @@ -474,7 +458,7 @@ public static void Shutdown() /// /// Shuts down the repository for the repository specified. /// - /// The repository to shutdown. + /// The repository to shut down. /// /// /// Calling this method will safely close and remove all @@ -487,16 +471,16 @@ public static void Shutdown() /// /// /// The shutdown method is careful to close nested - /// appenders before closing regular appenders. This is allows + /// appenders before closing regular appenders. This allows /// configurations where a regular appender is attached to a logger /// and again to a nested appender. /// /// public static void ShutdownRepository(string repository) { - if (repository == null) + if (repository is null) { - throw new ArgumentNullException("repository"); + throw new ArgumentNullException(nameof(repository)); } RepositorySelector.GetRepository(repository).Shutdown(); } @@ -504,7 +488,7 @@ public static void ShutdownRepository(string repository) /// /// Shuts down the repository for the repository specified. /// - /// The assembly to use to lookup the repository. + /// The assembly to use to look up the repository. /// /// /// Calling this method will safely close and remove all @@ -518,16 +502,16 @@ public static void ShutdownRepository(string repository) /// /// /// The shutdown method is careful to close nested - /// appenders before closing regular appenders. This is allows + /// appenders before closing regular appenders. This allows /// configurations where a regular appender is attached to a logger /// and again to a nested appender. /// /// public static void ShutdownRepository(Assembly repositoryAssembly) { - if (repositoryAssembly == null) + if (repositoryAssembly is null) { - throw new ArgumentNullException("repositoryAssembly"); + throw new ArgumentNullException(nameof(repositoryAssembly)); } RepositorySelector.GetRepository(repositoryAssembly).Shutdown(); } @@ -548,9 +532,9 @@ public static void ShutdownRepository(Assembly repositoryAssembly) /// public static void ResetConfiguration(string repository) { - if (repository == null) + if (repository is null) { - throw new ArgumentNullException("repository"); + throw new ArgumentNullException(nameof(repository)); } RepositorySelector.GetRepository(repository).ResetConfiguration(); } @@ -558,7 +542,7 @@ public static void ResetConfiguration(string repository) /// /// Resets all values contained in this repository instance to their defaults. /// - /// The assembly to use to lookup the repository to reset. + /// The assembly to use to look up the repository to reset. /// /// /// Resets all values contained in the repository instance to their @@ -571,9 +555,9 @@ public static void ResetConfiguration(string repository) /// public static void ResetConfiguration(Assembly repositoryAssembly) { - if (repositoryAssembly == null) + if (repositoryAssembly is null) { - throw new ArgumentNullException("repositoryAssembly"); + throw new ArgumentNullException(nameof(repositoryAssembly)); } RepositorySelector.GetRepository(repositoryAssembly).ResetConfiguration(); } @@ -621,9 +605,9 @@ public static ILoggerRepository CreateDomain(string repository) /// The specified repository already exists. public static ILoggerRepository CreateRepository(string repository) { - if (repository == null) + if (repository is null) { - throw new ArgumentNullException("repository"); + throw new ArgumentNullException(nameof(repository)); } return RepositorySelector.CreateRepository(repository, null); } @@ -669,13 +653,13 @@ public static ILoggerRepository CreateDomain(string repository, Type repositoryT /// The specified repository already exists. public static ILoggerRepository CreateRepository(string repository, Type repositoryType) { - if (repository == null) + if (repository is null) { - throw new ArgumentNullException("repository"); + throw new ArgumentNullException(nameof(repository)); } - if (repositoryType == null) + if (repositoryType is null) { - throw new ArgumentNullException("repositoryType"); + throw new ArgumentNullException(nameof(repositoryType)); } return RepositorySelector.CreateRepository(repository, repositoryType); } @@ -721,13 +705,13 @@ public static ILoggerRepository CreateDomain(Assembly repositoryAssembly, Type r /// public static ILoggerRepository CreateRepository(Assembly repositoryAssembly, Type repositoryType) { - if (repositoryAssembly == null) + if (repositoryAssembly is null) { - throw new ArgumentNullException("repositoryAssembly"); + throw new ArgumentNullException(nameof(repositoryAssembly)); } - if (repositoryType == null) + if (repositoryType is null) { - throw new ArgumentNullException("repositoryType"); + throw new ArgumentNullException(nameof(repositoryType)); } return RepositorySelector.CreateRepository(repositoryAssembly, repositoryType); } @@ -769,23 +753,19 @@ public static ILoggerRepository[] GetAllRepositories() /// public static IRepositorySelector RepositorySelector { get; set; } - #endregion Public Static Methods - - #region Private Static Methods - /// /// Internal method to get pertinent version info. /// /// A string of version info. private static string GetVersionInfo() { - System.Text.StringBuilder sb = new System.Text.StringBuilder(); + var sb = new StringBuilder(); Assembly myAssembly = Assembly.GetExecutingAssembly(); sb.Append("log4net assembly [").Append(myAssembly.FullName).Append("]. "); sb.Append("Loaded from [").Append(SystemInfo.AssemblyLocationInfo(myAssembly)).Append("]. "); - sb.Append("(.NET Runtime [").Append(Environment.Version.ToString()).Append("]"); - sb.Append(" on ").Append(Environment.OSVersion.ToString()); + sb.Append("(.NET Runtime [").Append(Environment.Version).Append("]"); + sb.Append(" on ").Append(Environment.OSVersion); sb.Append(")"); return sb.ToString(); } @@ -826,10 +806,6 @@ private static void OnProcessExit(object sender, EventArgs e) Shutdown(); } - #endregion Private Static Methods - - #region Private Static Fields - /// /// The fully qualified type of the LoggerManager class. /// @@ -838,7 +814,5 @@ private static void OnProcessExit(object sender, EventArgs e) /// log message. /// private static readonly Type declaringType = typeof(LoggerManager); - - #endregion Private Static Fields } } \ No newline at end of file diff --git a/src/log4net/Core/LoggingEvent.cs b/src/log4net/Core/LoggingEvent.cs index 44987046..908d617d 100644 --- a/src/log4net/Core/LoggingEvent.cs +++ b/src/log4net/Core/LoggingEvent.cs @@ -1,5 +1,4 @@ #region Apache License - // // Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with @@ -16,34 +15,27 @@ // See the License for the specific language governing permissions and // limitations under the License. // - #endregion using System; -using System.Collections; +using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Runtime.Serialization; using System.Security; using System.Security.Principal; +using System.Threading; using log4net.Util; using log4net.Repository; -using System.ComponentModel; namespace log4net.Core { /// /// Portable data structure used by /// - /// - /// - /// Portable data structure used by - /// - /// /// Nicko Cadell public struct LoggingEventData { - #region Public Instance Fields - /// /// The logger name. /// @@ -52,7 +44,7 @@ public struct LoggingEventData /// The logger name. /// /// - public string LoggerName; + public string? LoggerName; /// /// Level of logging event. @@ -64,7 +56,7 @@ public struct LoggingEventData /// cannot be declared final either. /// /// - public Level Level; + public Level? Level; /// /// The application supplied message. @@ -74,7 +66,7 @@ public struct LoggingEventData /// The application supplied message of logging event. /// /// - public string Message; + public string? Message; /// /// The name of thread @@ -84,7 +76,7 @@ public struct LoggingEventData /// The name of thread in which this logging event was generated /// /// - public string ThreadName; + public string? ThreadName; /// /// Gets or sets the local time the event was logged @@ -112,9 +104,11 @@ public DateTime TimeStampUtc get { if (TimeStamp != default && _timeStampUtc == default) + { // TimeStamp field has been set explicitly but TimeStampUtc hasn't // => use TimeStamp return TimeStamp.ToUniversalTime(); + } return _timeStampUtc; } @@ -137,7 +131,7 @@ public DateTime TimeStampUtc /// Location information for the caller. /// /// - public LocationInfo LocationInfo; + public LocationInfo? LocationInfo; /// /// String representation of the user @@ -148,7 +142,7 @@ public DateTime TimeStampUtc /// like DOMAIN\username /// /// - public string UserName; + public string? UserName; /// /// String representation of the identity. @@ -158,7 +152,7 @@ public DateTime TimeStampUtc /// String representation of the current thread's principal identity. /// /// - public string Identity; + public string? Identity; /// /// The string representation of the exception @@ -168,7 +162,7 @@ public DateTime TimeStampUtc /// The string representation of the exception /// /// - public string ExceptionString; + public string? ExceptionString; /// /// String representation of the AppDomain. @@ -178,7 +172,7 @@ public DateTime TimeStampUtc /// String representation of the AppDomain. /// /// - public string Domain; + public string? Domain; /// /// Additional event specific properties @@ -190,9 +184,7 @@ public DateTime TimeStampUtc /// have a string key and an object value. /// /// - public PropertiesDictionary Properties; - - #endregion Public Instance Fields + public PropertiesDictionary? Properties; } /// @@ -211,11 +203,11 @@ public DateTime TimeStampUtc /// Some of the values in instances of /// are considered volatile, that is the values are correct at the /// time the event is delivered to appenders, but will not be consistent - /// at any time afterwards. If an event is to be stored and then processed + /// at any time afterward. If an event is to be stored and then processed /// at a later time these volatile values must be fixed by calling /// . There is a performance penalty /// for incurred by calling but it - /// is essential to maintaining data consistency. + /// is essential to maintain data consistency. /// /// /// Nicko Cadell @@ -227,8 +219,6 @@ public class LoggingEvent : ISerializable { private static readonly Type declaringType = typeof(LoggingEvent); - #region Public Instance Constructors - /// /// Initializes a new instance of the class /// from the supplied parameters. @@ -251,17 +241,18 @@ public class LoggingEvent : ISerializable /// to create a logging event. /// /// - public LoggingEvent(Type callerStackBoundaryDeclaringType, - log4net.Repository.ILoggerRepository repository, + public LoggingEvent( + Type callerStackBoundaryDeclaringType, + ILoggerRepository? repository, string loggerName, - Level level, + Level? level, object message, - Exception exception) + Exception? exception) { m_callerStackBoundaryDeclaringType = callerStackBoundaryDeclaringType; m_message = message; - m_repository = repository; - m_thrownException = exception; + Repository = repository; + ExceptionObject = exception; m_data.LoggerName = loggerName; m_data.Level = level; @@ -295,13 +286,14 @@ public LoggingEvent(Type callerStackBoundaryDeclaringType, /// will be captured from the environment if requested or fixed. /// /// - public LoggingEvent(Type callerStackBoundaryDeclaringType, - log4net.Repository.ILoggerRepository repository, + public LoggingEvent( + Type? callerStackBoundaryDeclaringType, + ILoggerRepository? repository, LoggingEventData data, FixFlags fixedData) { m_callerStackBoundaryDeclaringType = callerStackBoundaryDeclaringType; - m_repository = repository; + Repository = repository; m_data = data; m_fixFlags = fixedData; @@ -331,9 +323,11 @@ public LoggingEvent(Type callerStackBoundaryDeclaringType, /// parameter and no other data should be captured from the environment. /// /// - public LoggingEvent(Type callerStackBoundaryDeclaringType, - log4net.Repository.ILoggerRepository repository, - LoggingEventData data) : this(callerStackBoundaryDeclaringType, repository, data, FixFlags.All) + public LoggingEvent( + Type? callerStackBoundaryDeclaringType, + ILoggerRepository? repository, + LoggingEventData data) + : this(callerStackBoundaryDeclaringType, repository, data, FixFlags.All) { } @@ -362,10 +356,6 @@ public LoggingEvent(LoggingEventData data) : this(null, null, data) { } - #endregion Public Instance Constructors - - #region Protected Instance Constructors - /// /// Serialization constructor /// @@ -403,10 +393,6 @@ protected LoggingEvent(SerializationInfo info, StreamingContext context) m_fixFlags = FixFlags.All; } - #endregion Protected Instance Constructors - - #region Public Instance Properties - /// /// Gets the time when the current process started. /// @@ -428,10 +414,7 @@ protected LoggingEvent(SerializationInfo info, StreamingContext context) /// without the process start time being reset. /// /// - public static DateTime StartTime - { - get { return SystemInfo.ProcessStartTimeUtc.ToLocalTime(); } - } + public static DateTime StartTime => SystemInfo.ProcessStartTimeUtc.ToLocalTime(); /// /// Gets the UTC time when the current process started. @@ -451,10 +434,7 @@ public static DateTime StartTime /// without the process start time being reset. /// /// - public static DateTime StartTimeUtc - { - get { return SystemInfo.ProcessStartTimeUtc; } - } + public static DateTime StartTimeUtc => SystemInfo.ProcessStartTimeUtc; /// /// Gets the of the logging event. @@ -467,10 +447,7 @@ public static DateTime StartTimeUtc /// Gets the of the logging event. /// /// - public Level Level - { - get { return m_data.Level; } - } + public Level? Level => m_data.Level; /// /// Gets the time of the logging event. @@ -483,10 +460,7 @@ public Level Level /// The TimeStamp is stored in UTC and converted to the local time zone for this computer. /// /// - public DateTime TimeStamp - { - get { return m_data.TimeStampUtc.ToLocalTime(); } - } + public DateTime TimeStamp => m_data.TimeStampUtc.ToLocalTime(); /// /// Gets UTC the time of the logging event. @@ -494,10 +468,7 @@ public DateTime TimeStamp /// /// The UTC time of the logging event. /// - public DateTime TimeStampUtc - { - get { return m_data.TimeStampUtc; } - } + public DateTime TimeStampUtc => m_data.TimeStampUtc; /// /// Gets the name of the logger that logged the event. @@ -510,10 +481,7 @@ public DateTime TimeStampUtc /// Gets the name of the logger that logged the event. /// /// - public string LoggerName - { - get { return m_data.LoggerName; } - } + public string? LoggerName => m_data.LoggerName; /// /// Gets the location information for this logging event. @@ -531,11 +499,11 @@ public string LoggerName /// Release builds. /// /// - public LocationInfo LocationInformation + public LocationInfo? LocationInformation { get { - if (m_data.LocationInfo == null && this.m_cacheUpdatable) + if (m_data.LocationInfo is null && m_cacheUpdatable) { m_data.LocationInfo = new LocationInfo(m_callerStackBoundaryDeclaringType); } @@ -564,7 +532,7 @@ public LocationInfo LocationInformation /// null will be returned. /// /// - public object MessageObject + public object? MessageObject { get { return m_message; } protected set { m_message = value; } @@ -590,10 +558,7 @@ public object MessageObject /// null will be returned. /// /// - public Exception ExceptionObject - { - get { return m_thrownException; } - } + public Exception? ExceptionObject { get; } /// /// The that this event was created in. @@ -603,20 +568,17 @@ public Exception ExceptionObject /// The that this event was created in. /// /// - public ILoggerRepository Repository - { - get { return m_repository; } - } + public ILoggerRepository? Repository { get; private set; } /// /// Ensure that the repository is set. /// /// the value for the repository - internal void EnsureRepository(ILoggerRepository repository) + internal void EnsureRepository(ILoggerRepository? repository) { - if (repository != null) + if (repository is not null) { - m_repository = repository; + Repository = repository; } } @@ -631,23 +593,23 @@ internal void EnsureRepository(ILoggerRepository repository) /// The collected information is cached for future use. /// /// - public virtual string RenderedMessage + public virtual string? RenderedMessage { get { - if (m_data.Message == null && this.m_cacheUpdatable) + if (m_data.Message is null && m_cacheUpdatable) { if (m_message == null) { - m_data.Message = ""; + m_data.Message = string.Empty; } - else if (m_message is string) + else if (m_message is string s) { - m_data.Message = (m_message as string); + m_data.Message = s; } - else if (m_repository != null) + else if (Repository is not null) { - m_data.Message = m_repository.RendererMap.FindAndRender(m_message); + m_data.Message = Repository.RendererMap.FindAndRender(m_message); } else { @@ -675,21 +637,21 @@ public virtual string RenderedMessage /// public virtual void WriteRenderedMessage(TextWriter writer) { - if (m_data.Message != null) + if (m_data.Message is not null) { writer.Write(m_data.Message); } else { - if (m_message != null) + if (m_message is not null) { - if (m_message is string) + if (m_message is string s) { - writer.Write(m_message as string); + writer.Write(s); } - else if (m_repository != null) + else if (Repository is not null) { - m_repository.RendererMap.FindAndRender(m_message, writer); + Repository.RendererMap.FindAndRender(m_message, writer); } else { @@ -712,16 +674,16 @@ public virtual void WriteRenderedMessage(TextWriter writer) /// The collected information is cached for future use. /// /// - public string ThreadName + public string? ThreadName { get { - if (m_data.ThreadName == null && this.m_cacheUpdatable) + if (m_data.ThreadName == null && m_cacheUpdatable) { // '.NET ThreadPool Worker' appears as a default thread name in the .NET 6-7 thread pool. // '.NET TP Worker' is the default thread name in the .NET 8+ thread pool. // Prefer the numeric thread ID instead. - string threadName = System.Threading.Thread.CurrentThread.Name; + string threadName = Thread.CurrentThread.Name; if (!string.IsNullOrEmpty(threadName) && threadName != ".NET TP Worker" && threadName != ".NET ThreadPool Worker") { m_data.ThreadName = threadName; @@ -733,9 +695,7 @@ public string ThreadName // current thread. (Why don't Threads know their own ID?) try { - m_data.ThreadName = - SystemInfo.CurrentThreadId.ToString(System.Globalization.NumberFormatInfo - .InvariantInfo); + m_data.ThreadName = SystemInfo.CurrentThreadId.ToString(NumberFormatInfo.InvariantInfo); } catch (SecurityException) { @@ -745,8 +705,7 @@ public string ThreadName "Security exception while trying to get current thread ID. Error Ignored. Empty thread name."); // As a last resort use the hash code of the Thread object - m_data.ThreadName = System.Threading.Thread.CurrentThread.GetHashCode() - .ToString(System.Globalization.CultureInfo.InvariantCulture); + m_data.ThreadName = Thread.CurrentThread.GetHashCode().ToString(CultureInfo.InvariantCulture); } } } @@ -805,7 +764,7 @@ public string ThreadName public string UserName => m_data.UserName ??= TryGetCurrentUserName() ?? SystemInfo.NotAvailableText; - private string TryGetCurrentUserName() + private string? TryGetCurrentUserName() { if (_platformDoesNotSupportWindowsIdentity) { @@ -840,11 +799,11 @@ private string TryGetCurrentUserName() } } - private string _cachedWindowsIdentityUserName; + private string? _cachedWindowsIdentityUserName; private static string TryReadWindowsIdentityUserName() { using var identity = WindowsIdentity.GetCurrent(); - return identity?.Name ?? ""; + return identity?.Name ?? string.Empty; } private static bool _platformDoesNotSupportWindowsIdentity; @@ -852,52 +811,47 @@ private static string TryReadWindowsIdentityUserName() /// /// Gets the identity of the current thread principal. /// - /// - /// The string name of the identity of the current thread principal. - /// /// /// /// Calls System.Threading.Thread.CurrentPrincipal.Identity.Name to get /// the name of the current thread principal. /// /// - public string Identity + public string? Identity { get { - if (m_data.Identity == null && this.m_cacheUpdatable) + if (m_data.Identity is null && m_cacheUpdatable) { try { - if (System.Threading.Thread.CurrentPrincipal != null && - System.Threading.Thread.CurrentPrincipal.Identity != null && - System.Threading.Thread.CurrentPrincipal.Identity.Name != null) + if (Thread.CurrentPrincipal?.Identity?.Name is string name) { - m_data.Identity = System.Threading.Thread.CurrentPrincipal.Identity.Name; + m_data.Identity = name; } else { - m_data.Identity = ""; + m_data.Identity = string.Empty; } } catch (ObjectDisposedException) { - // This exception will occur if System.Threading.Thread.CurrentPrincipal.Identity is not null but + // This exception will occur if Thread.CurrentPrincipal.Identity is not null but // the getter of the property Name tries to access disposed objects. // Seen to happen on IIS 7 or greater with windows authentication. LogLog.Debug(declaringType, "Object disposed exception while trying to get current thread principal. Error Ignored. Empty identity name."); - m_data.Identity = ""; + m_data.Identity = string.Empty; } - catch (System.Security.SecurityException) + catch (SecurityException) { // This security exception will occur if the caller does not have // some undefined set of SecurityPermission flags. LogLog.Debug(declaringType, "Security exception while trying to get current thread principal. Error Ignored. Empty identity name."); - m_data.Identity = ""; + m_data.Identity = string.Empty; } } @@ -908,19 +862,11 @@ public string Identity /// /// Gets the AppDomain friendly name. /// - /// - /// The AppDomain friendly name. - /// - /// - /// - /// Gets the AppDomain friendly name. - /// - /// - public string Domain + public string? Domain { get { - if (m_data.Domain == null && this.m_cacheUpdatable) + if (m_data.Domain is null && m_cacheUpdatable) { m_data.Domain = SystemInfo.ApplicationFriendlyName; } @@ -960,16 +906,12 @@ public PropertiesDictionary Properties get { // If we have cached properties then return that otherwise changes will be lost - if (m_data.Properties != null) + if (m_data.Properties is not null) { return m_data.Properties; } - if (m_eventProperties == null) - { - m_eventProperties = new PropertiesDictionary(); - } - + m_eventProperties ??= new PropertiesDictionary(); return m_eventProperties; } } @@ -977,9 +919,6 @@ public PropertiesDictionary Properties /// /// The fixed fields in this event /// - /// - /// The set of fields that are fixed in this event - /// /// /// /// Fields will not be fixed if they have previously been fixed. @@ -988,14 +927,10 @@ public PropertiesDictionary Properties /// public FixFlags Fix { - get { return m_fixFlags; } - set { this.FixVolatileData(value); } + get => m_fixFlags; + set => FixVolatileData(value); } - #endregion Public Instance Properties - - #region Implementation of ISerializable - /// /// Serializes this object into the provided. /// @@ -1011,7 +946,7 @@ public FixFlags Fix /// is to be used outside that method. /// /// - [System.Security.SecurityCritical] + [SecurityCritical] [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, SerializationFormatter = true)] public virtual void GetObjectData(SerializationInfo info, StreamingContext context) @@ -1037,10 +972,6 @@ public virtual void GetObjectData(SerializationInfo info, StreamingContext conte info.AddValue("Identity", m_data.Identity); } - #endregion Implementation of ISerializable - - #region Public Instance Methods - /// /// Gets the portable data for this . /// @@ -1090,7 +1021,7 @@ public LoggingEventData GetLoggingEventData(FixFlags fixFlags) /// /// [Obsolete("Use GetExceptionString instead")] - public string GetExceptionStrRep() + public string? GetExceptionStrRep() { return GetExceptionString(); } @@ -1108,26 +1039,26 @@ public string GetExceptionStrRep() /// . /// /// - public string GetExceptionString() + public string? GetExceptionString() { - if (m_data.ExceptionString == null && this.m_cacheUpdatable) + if (m_data.ExceptionString is null && m_cacheUpdatable) { - if (m_thrownException != null) + if (ExceptionObject is not null) { - if (m_repository != null) + if (Repository is not null) { // Render exception using the repositories renderer map - m_data.ExceptionString = m_repository.RendererMap.FindAndRender(m_thrownException); + m_data.ExceptionString = Repository.RendererMap.FindAndRender(ExceptionObject); } else { // Very last resort - m_data.ExceptionString = m_thrownException.ToString(); + m_data.ExceptionString = ExceptionObject.ToString(); } } else { - m_data.ExceptionString = ""; + m_data.ExceptionString = string.Empty; } } @@ -1142,11 +1073,11 @@ public string GetExceptionString() /// Some of the values in instances of /// are considered volatile, that is the values are correct at the /// time the event is delivered to appenders, but will not be consistent - /// at any time afterwards. If an event is to be stored and then processed + /// at any time afterward. If an event is to be stored and then processed /// at a later time these volatile values must be fixed by calling /// . There is a performance penalty /// incurred by calling but it - /// is essential to maintaining data consistency. + /// is essential to maintain data consistency. /// /// /// Calling is equivalent to @@ -1173,11 +1104,11 @@ public void FixVolatileData() /// Some of the values in instances of /// are considered volatile, that is the values are correct at the /// time the event is delivered to appenders, but will not be consistent - /// at any time afterwards. If an event is to be stored and then processed + /// at any time afterward. If an event is to be stored and then processed /// at a later time these volatile values must be fixed by calling /// . There is a performance penalty /// for incurred by calling but it - /// is essential to maintaining data consistency. + /// is essential to maintain data consistency. /// /// /// The param controls the data that @@ -1218,22 +1149,20 @@ public void FixVolatileData(bool fastButLoose) /// protected virtual void FixVolatileData(FixFlags flags) { - object forceCreation = null; - - //Unlock the cache so that new values can be stored - //This may not be ideal if we are no longer in the correct context - //and someone calls fix. + // Unlock the cache so that new values can be stored + // This may not be ideal if we are no longer in the correct context + // and someone calls fix. m_cacheUpdatable = true; // determine the flags that we are actually fixing - var updateFlags = (FixFlags)((flags ^ m_fixFlags) & flags); + FixFlags updateFlags = (flags ^ m_fixFlags) & flags; if (updateFlags > 0) { if ((updateFlags & FixFlags.Message) != 0) { // Force the message to be rendered - forceCreation = this.RenderedMessage; + _ = RenderedMessage; m_fixFlags |= FixFlags.Message; } @@ -1241,7 +1170,7 @@ protected virtual void FixVolatileData(FixFlags flags) if ((updateFlags & FixFlags.ThreadName) != 0) { // Grab the thread name - forceCreation = this.ThreadName; + _ = ThreadName; m_fixFlags |= FixFlags.ThreadName; } @@ -1249,7 +1178,7 @@ protected virtual void FixVolatileData(FixFlags flags) if ((updateFlags & FixFlags.LocationInfo) != 0) { // Force the location information to be loaded - forceCreation = this.LocationInformation; + _ = LocationInformation; m_fixFlags |= FixFlags.LocationInfo; } @@ -1257,7 +1186,7 @@ protected virtual void FixVolatileData(FixFlags flags) if ((updateFlags & FixFlags.UserName) != 0) { // Grab the user name - forceCreation = this.UserName; + _ = UserName; m_fixFlags |= FixFlags.UserName; } @@ -1265,7 +1194,7 @@ protected virtual void FixVolatileData(FixFlags flags) if ((updateFlags & FixFlags.Domain) != 0) { // Grab the domain name - forceCreation = this.Domain; + _ = Domain; m_fixFlags |= FixFlags.Domain; } @@ -1273,7 +1202,7 @@ protected virtual void FixVolatileData(FixFlags flags) if ((updateFlags & FixFlags.Identity) != 0) { // Grab the identity - forceCreation = this.Identity; + _ = Identity; m_fixFlags |= FixFlags.Identity; } @@ -1281,7 +1210,7 @@ protected virtual void FixVolatileData(FixFlags flags) if ((updateFlags & FixFlags.Exception) != 0) { // Force the exception text to be loaded - forceCreation = GetExceptionString(); + _ = GetExceptionString(); m_fixFlags |= FixFlags.Exception; } @@ -1294,34 +1223,24 @@ protected virtual void FixVolatileData(FixFlags flags) } } - // avoid warning CS0219 - if (forceCreation != null) - { - } - - //Finaly lock everything we've cached. + // Finally lock everything we've cached. m_cacheUpdatable = false; } - #endregion Public Instance Methods - - #region Protected Instance Methods - private void CreateCompositeProperties() { var compositeProperties = new CompositeProperties(); - if (m_eventProperties != null) + if (m_eventProperties is not null) { compositeProperties.Add(m_eventProperties); } var logicalThreadProperties = LogicalThreadContext.Properties.GetProperties(false); - if (logicalThreadProperties != null) + if (logicalThreadProperties is not null) { compositeProperties.Add(logicalThreadProperties); } - var threadProperties = ThreadContext.Properties.GetProperties(false); - if (threadProperties != null) + if (ThreadContext.Properties.GetProperties(false) is PropertiesDictionary threadProperties) { compositeProperties.Add(threadProperties); } @@ -1353,38 +1272,32 @@ private void CreateCompositeProperties() private void CacheProperties() { - if (m_data.Properties == null && this.m_cacheUpdatable) + if (m_data.Properties is null && m_cacheUpdatable) { - if (m_compositeProperties == null) + if (m_compositeProperties is null) { CreateCompositeProperties(); } - var flattenedProperties = m_compositeProperties.Flatten(); + var flattenedProperties = m_compositeProperties!.Flatten(); var fixedProperties = new PropertiesDictionary(); // Validate properties - foreach (DictionaryEntry entry in flattenedProperties) + foreach (KeyValuePair entry in flattenedProperties) { - var key = entry.Key as string; + object? val = entry.Value; - if (key != null) + // Fix any IFixingRequired objects + if (entry.Value is IFixingRequired fixingRequired) { - var val = entry.Value; - - // Fix any IFixingRequired objects - var fixingRequired = val as IFixingRequired; - if (fixingRequired != null) - { - val = fixingRequired.GetFixedObject(); - } + val = fixingRequired.GetFixedObject(); + } - // Strip keys with null values - if (val != null) - { - fixedProperties[key] = val; - } + // Strip keys with null values + if (val is not null) + { + fixedProperties[entry.Key] = val; } } @@ -1393,17 +1306,17 @@ private void CacheProperties() } /// - /// Lookup a composite property in this event + /// Looks up a composite property in this event /// /// the key for the property to lookup /// the value for the property /// /// - /// This event has composite properties that combine together properties from + /// This event has composite properties that combine properties from /// several different contexts in the following order: /// /// - /// this events properties + /// this event's properties /// /// This event has that can be set. These /// properties are specific to this event only. @@ -1426,19 +1339,19 @@ private void CacheProperties() /// /// /// - public object LookupProperty(string key) + public object? LookupProperty(string key) { - if (m_data.Properties != null) + if (m_data.Properties is not null) { return m_data.Properties[key]; } - if (m_compositeProperties == null) + if (m_compositeProperties is null) { CreateCompositeProperties(); } - return m_compositeProperties[key]; + return m_compositeProperties![key]; } /// @@ -1467,13 +1380,9 @@ public PropertiesDictionary GetProperties() CreateCompositeProperties(); } - return m_compositeProperties.Flatten(); + return m_compositeProperties!.Flatten(); } - #endregion Public Instance Methods - - #region Private Instance Fields - /// /// The internal logging event data. /// @@ -1482,45 +1391,28 @@ public PropertiesDictionary GetProperties() /// /// Location information for the caller. /// - public LocationInfo LocationInfo => m_data.LocationInfo; + public LocationInfo? LocationInfo => m_data.LocationInfo; /// /// The internal logging event data. /// - private CompositeProperties m_compositeProperties; + private CompositeProperties? m_compositeProperties; /// /// The internal logging event data. /// - private PropertiesDictionary m_eventProperties; + private PropertiesDictionary? m_eventProperties; /// /// The fully qualified Type of the calling /// logger class in the stack frame (i.e. the declaring type of the method). /// - private readonly Type m_callerStackBoundaryDeclaringType; + private readonly Type? m_callerStackBoundaryDeclaringType; /// /// The application supplied message of logging event. /// - private object m_message; - - /// - /// The exception that was thrown. - /// - /// - /// This is not serialized. The string representation - /// is serialized instead. - /// - private readonly Exception m_thrownException; - - /// - /// The repository that generated the logging event - /// - /// - /// This is not serialized. - /// - private ILoggerRepository m_repository = null; + private object? m_message; /// /// The fix state for this event @@ -1535,15 +1427,11 @@ public PropertiesDictionary GetProperties() /// Indicated that the internal cache is updateable (ie not fixed) /// /// - /// This is a seperate flag to m_fixFlags as it allows incrementel fixing and simpler + /// This is a separate flag to m_fixFlags as it allows incremental fixing and simpler /// changes in the caching strategy. /// private bool m_cacheUpdatable = true; - #endregion Private Instance Fields - - #region Constants - /// /// The key into the Properties map for the host name value. /// @@ -1558,7 +1446,5 @@ public PropertiesDictionary GetProperties() /// The key into the Properties map for the user name value. /// public const string UserNameProperty = "log4net:UserName"; - - #endregion } } \ No newline at end of file diff --git a/src/log4net/Core/WrapperMap.cs b/src/log4net/Core/WrapperMap.cs index b2b30e5d..16613ac8 100644 --- a/src/log4net/Core/WrapperMap.cs +++ b/src/log4net/Core/WrapperMap.cs @@ -24,8 +24,6 @@ namespace log4net.Core { - #region WrapperCreationHandler - /// /// Delegate used to handle creation of new wrappers. /// @@ -43,8 +41,6 @@ namespace log4net.Core /// public delegate ILoggerWrapper WrapperCreationHandler(ILogger logger); - #endregion WrapperCreationHandler - /// /// Maps between logger objects and wrapper objects. /// @@ -52,7 +48,7 @@ namespace log4net.Core /// /// This class maintains a mapping between objects and /// objects. Use the method to - /// lookup the for the specified . + /// look up the for the specified . /// /// /// New wrapper instances are created by the @@ -66,8 +62,6 @@ namespace log4net.Core /// Gert Driesen public class WrapperMap { - #region Public Instance Constructors - /// /// Initializes a new instance of the /// @@ -83,13 +77,9 @@ public WrapperMap(WrapperCreationHandler createWrapperHandler) m_createWrapperHandler = createWrapperHandler; // Create the delegates for the event callbacks - m_shutdownHandler = new LoggerRepositoryShutdownEventHandler(ILoggerRepository_Shutdown); + m_shutdownHandler = ILoggerRepository_Shutdown; } - #endregion Public Instance Constructors - - #region Public Instance Properties - /// /// Gets the wrapper object for the specified logger. /// @@ -99,41 +89,37 @@ public WrapperMap(WrapperCreationHandler createWrapperHandler) /// If the logger is null then the corresponding wrapper is null. /// /// - /// Looks up the wrapper it it has previously been requested and + /// Looks up the wrapper it has previously been requested and /// returns it. If the wrapper has never been requested before then /// the virtual method is /// called. /// /// - public virtual ILoggerWrapper GetWrapper(ILogger logger) + public virtual ILoggerWrapper? GetWrapper(ILogger? logger) { // If the logger is null then the corresponding wrapper is null - if (logger == null) + if (logger is null) { return null; } lock (this) { - // Lookup hierarchy in map. - Hashtable wrappersMap = (Hashtable)m_repositories[logger.Repository]; - - if (wrappersMap == null) + // Look up hierarchy in map. + Hashtable? wrappersMap = (Hashtable?)Repositories[logger.Repository]; + if (wrappersMap is null) { // Hierarchy does not exist in map. // Must register with hierarchy - wrappersMap = new Hashtable(); - m_repositories[logger.Repository] = wrappersMap; + Repositories[logger.Repository] = wrappersMap; // Register for config reset & shutdown on repository logger.Repository.ShutdownEvent += m_shutdownHandler; } // Look for the wrapper object in the map - ILoggerWrapper wrapperObject = wrappersMap[logger] as ILoggerWrapper; - - if (wrapperObject == null) + if (wrappersMap[logger] is not ILoggerWrapper wrapperObject) { // No wrapper object exists for the specified logger @@ -148,10 +134,6 @@ public virtual ILoggerWrapper GetWrapper(ILogger logger) } } - #endregion Public Instance Properties - - #region Protected Instance Properties - /// /// Gets the map of logger repositories. /// @@ -165,14 +147,7 @@ public virtual ILoggerWrapper GetWrapper(ILogger logger) /// value being the corresponding . /// /// - protected Hashtable Repositories - { - get { return this.m_repositories; } - } - - #endregion Protected Instance Properties - - #region Protected Instance Methods + protected Hashtable Repositories { get; } = new(); /// /// Creates the wrapper object for the specified logger. @@ -186,13 +161,9 @@ protected Hashtable Repositories /// can be overridden in a subclass. /// /// - protected virtual ILoggerWrapper CreateNewWrapperObject(ILogger logger) + protected virtual ILoggerWrapper? CreateNewWrapperObject(ILogger logger) { - if (m_createWrapperHandler != null) - { - return m_createWrapperHandler(logger); - } - return null; + return m_createWrapperHandler?.Invoke(logger); } /// @@ -213,7 +184,7 @@ protected virtual void RepositoryShutdown(ILoggerRepository repository) lock (this) { // Remove the repository from map - m_repositories.Remove(repository); + Repositories.Remove(repository); // Unhook events from the repository repository.ShutdownEvent -= m_shutdownHandler; @@ -227,33 +198,21 @@ protected virtual void RepositoryShutdown(ILoggerRepository repository) /// The event args. private void ILoggerRepository_Shutdown(object sender, EventArgs e) { - ILoggerRepository repository = sender as ILoggerRepository; - if (repository != null) + if (sender is ILoggerRepository repository) { // Remove all repository from map RepositoryShutdown(repository); } } - #endregion Protected Instance Methods - - #region Private Instance Variables - - /// - /// Map of logger repositories to hashtables of ILogger to ILoggerWrapper mappings - /// - private readonly Hashtable m_repositories = new Hashtable(); - /// /// The handler to use to create the extension wrapper objects. /// - private readonly WrapperCreationHandler m_createWrapperHandler; + private readonly WrapperCreationHandler? m_createWrapperHandler; /// /// Internal reference to the delegate used to register for repository shutdown events. /// private readonly LoggerRepositoryShutdownEventHandler m_shutdownHandler; - - #endregion Private Instance Variables } } diff --git a/src/log4net/Filter/NdcFilter.cs b/src/log4net/Filter/NdcFilter.cs index 4b0a3e0d..b7b1c874 100644 --- a/src/log4net/Filter/NdcFilter.cs +++ b/src/log4net/Filter/NdcFilter.cs @@ -17,13 +17,6 @@ // #endregion -using System; -using System.Text.RegularExpressions; - -using log4net; -using log4net.Core; -using log4net.Util; - namespace log4net.Filter { /// @@ -34,7 +27,7 @@ namespace log4net.Filter /// Simple filter to match a string in the /// /// - /// As the MDC has been replaced with named stacks stored in the + /// As the NDC has been replaced with named stacks stored in the /// properties collections the should /// be used instead. /// @@ -54,7 +47,7 @@ public class NdcFilter : PropertyFilter /// public NdcFilter() { - base.Key = "NDC"; + Key = "NDC"; } } } diff --git a/src/log4net/Layout/LayoutSkeleton.cs b/src/log4net/Layout/LayoutSkeleton.cs index 348eb075..06b959f3 100644 --- a/src/log4net/Layout/LayoutSkeleton.cs +++ b/src/log4net/Layout/LayoutSkeleton.cs @@ -17,10 +17,8 @@ // #endregion -using System; using System.IO; -using log4net; using log4net.Core; namespace log4net.Layout @@ -50,42 +48,6 @@ namespace log4net.Layout /// Gert Driesen public abstract class LayoutSkeleton : ILayout, IOptionHandler { - #region Member Variables - - /// - /// The header text - /// - /// - /// - /// See for more information. - /// - /// - private string m_header = null; - - /// - /// The footer text - /// - /// - /// - /// See for more information. - /// - /// - private string m_footer = null; - - /// - /// Flag indicating if this layout handles exceptions - /// - /// - /// - /// false if this layout handles exceptions - /// - /// - private bool m_ignoresException = true; - - #endregion - - #region Constructors - /// /// Empty default constructor /// @@ -98,10 +60,6 @@ protected LayoutSkeleton() { } - #endregion - - #region Implementation of IOptionHandler - /// /// Activate component options /// @@ -123,10 +81,6 @@ protected LayoutSkeleton() /// public abstract void ActivateOptions(); - #endregion - - #region Implementation of ILayout - /// /// Implement this method to create your own layout format. /// @@ -149,7 +103,7 @@ protected LayoutSkeleton() /// public string Format(LoggingEvent loggingEvent) { - using StringWriter writer = new StringWriter(System.Globalization.CultureInfo.InvariantCulture); + using var writer = new StringWriter(System.Globalization.CultureInfo.InvariantCulture); Format(writer, loggingEvent); return writer.ToString(); } @@ -168,10 +122,7 @@ public string Format(LoggingEvent loggingEvent) /// property. /// /// - public virtual string ContentType - { - get { return "text/plain"; } - } + public virtual string ContentType => "text/plain"; /// /// The header for the layout format. @@ -183,11 +134,7 @@ public virtual string ContentType /// are formatted and appended. /// /// - public virtual string Header - { - get { return m_header; } - set { m_header = value; } - } + public virtual string? Header { get; set; } /// /// The footer for the layout format. @@ -199,11 +146,7 @@ public virtual string Header /// have been formatted and appended. /// /// - public virtual string Footer - { - get { return m_footer; } - set { m_footer = value; } - } + public virtual string? Footer { get; set; } /// /// Flag indicating if this layout handles exceptions @@ -217,16 +160,10 @@ public virtual string Footer /// object, then the layout should return true. /// /// - /// Set this value to override a this default setting. The default + /// Set this value to override the default setting. The default /// value is true, this layout does not handle the exception. /// /// - public virtual bool IgnoresException - { - get { return m_ignoresException; } - set { m_ignoresException = value; } - } - - #endregion + public virtual bool IgnoresException { get; set; } = true; } } diff --git a/src/log4net/Layout/Pattern/NdcPatternConverter.cs b/src/log4net/Layout/Pattern/NdcPatternConverter.cs index a64dbb98..cc2293b2 100644 --- a/src/log4net/Layout/Pattern/NdcPatternConverter.cs +++ b/src/log4net/Layout/Pattern/NdcPatternConverter.cs @@ -17,8 +17,6 @@ // #endregion -using System; -using System.Text; using System.IO; using log4net.Core; diff --git a/src/log4net/Layout/XmlLayout.cs b/src/log4net/Layout/XmlLayout.cs index c23ecf9a..c1650740 100644 --- a/src/log4net/Layout/XmlLayout.cs +++ b/src/log4net/Layout/XmlLayout.cs @@ -18,6 +18,7 @@ #endregion using System; +using System.Collections.Generic; using System.Text; using System.Xml; @@ -72,12 +73,10 @@ namespace log4net.Layout /// Gert Driesen public class XmlLayout : XmlLayoutBase { - #region Public Instance Constructors - /// /// Constructs an XmlLayout /// - public XmlLayout() : base() + public XmlLayout() { } @@ -88,7 +87,7 @@ public XmlLayout() : base() /// /// The LocationInfo option takes a boolean value. By /// default, it is set to false which means there will be no location - /// information output by this layout. If the the option is set to + /// information output by this layout. If the option is set to /// true, then the file name and line number of the statement /// at the origin of the log statement will be output. /// @@ -102,10 +101,6 @@ public XmlLayout(bool locationInfo) : base(locationInfo) { } - #endregion Public Instance Constructors - - #region Public Instance Properties - /// /// The prefix to use for all element names /// @@ -116,15 +111,10 @@ public XmlLayout(bool locationInfo) : base(locationInfo) /// then no prefix will be written. /// /// - public string Prefix - { - get { return m_prefix; } - set { m_prefix = value; } - } - - + public string Prefix { get; set; } = PREFIX; + /// - /// Set whether or not to base64 encode the message. + /// Set whether to base64 encode the message. /// /// /// @@ -136,14 +126,10 @@ public string Prefix /// on the log message. /// /// - public bool Base64EncodeMessage - { - get { return m_base64Message; } - set { m_base64Message = value; } - } + public bool Base64EncodeMessage { get; set; } /// - /// Set whether or not to base64 encode the property values. + /// Set whether to base64 encode the property values. /// /// /// @@ -155,15 +141,7 @@ public bool Base64EncodeMessage /// on the property values. /// /// - public bool Base64EncodeProperties - { - get { return m_base64Properties; } - set { m_base64Properties = value; } - } - - #endregion Public Instance Properties - - #region Implementation of IOptionHandler + public bool Base64EncodeProperties { get; set; } /// /// Initialize layout options @@ -189,21 +167,17 @@ public override void ActivateOptions() base.ActivateOptions(); // Cache the full element names including the prefix - if (m_prefix != null && m_prefix.Length > 0) + if (Prefix.Length > 0) { - m_elmEvent = m_prefix + ":" + ELM_EVENT; - m_elmMessage = m_prefix + ":" + ELM_MESSAGE; - m_elmProperties = m_prefix + ":" + ELM_PROPERTIES; - m_elmData = m_prefix + ":" + ELM_DATA; - m_elmException = m_prefix + ":" + ELM_EXCEPTION; - m_elmLocation = m_prefix + ":" + ELM_LOCATION; + m_elmEvent = Prefix + ":" + ELM_EVENT; + m_elmMessage = Prefix + ":" + ELM_MESSAGE; + m_elmProperties = Prefix + ":" + ELM_PROPERTIES; + m_elmData = Prefix + ":" + ELM_DATA; + m_elmException = Prefix + ":" + ELM_EXCEPTION; + m_elmLocation = Prefix + ":" + ELM_LOCATION; } } - #endregion Implementation of IOptionHandler - - #region Override implementation of XMLLayoutBase - /// /// Does the actual writing of the XML. /// @@ -217,13 +191,13 @@ public override void ActivateOptions() /// protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) { - writer.WriteStartElement(m_elmEvent, m_prefix, ELM_EVENT, m_prefix); - writer.WriteAttributeString(ATTR_LOGGER, loggingEvent.LoggerName); + writer.WriteStartElement(m_elmEvent, Prefix, ELM_EVENT, Prefix); + writer.WriteAttributeString(ATTR_LOGGER, loggingEvent.LoggerName!); writer.WriteAttributeString(ATTR_TIMESTAMP, XmlConvert.ToString(loggingEvent.TimeStamp, XmlDateTimeSerializationMode.Local)); writer.WriteAttributeString(ATTR_LEVEL, loggingEvent.Level.DisplayName); - writer.WriteAttributeString(ATTR_THREAD, loggingEvent.ThreadName); + writer.WriteAttributeString(ATTR_THREAD, loggingEvent.ThreadName!); if (loggingEvent.Domain != null && loggingEvent.Domain.Length > 0) { @@ -233,14 +207,14 @@ protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) { writer.WriteAttributeString(ATTR_IDENTITY, loggingEvent.Identity); } - if (loggingEvent.UserName != null && loggingEvent.UserName.Length > 0) + if (loggingEvent.UserName.Length > 0) { writer.WriteAttributeString(ATTR_USERNAME, loggingEvent.UserName); } // Append the message text - writer.WriteStartElement(m_elmMessage, m_prefix, ELM_MESSAGE, m_prefix); - if (!this.Base64EncodeMessage) + writer.WriteStartElement(m_elmMessage, Prefix, ELM_MESSAGE, Prefix); + if (!Base64EncodeMessage) { Transform.WriteEscapedXmlString(writer, loggingEvent.RenderedMessage, this.InvalidCharReplacement); } @@ -257,17 +231,17 @@ protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) // Append the properties text if (properties.Count > 0) { - writer.WriteStartElement(m_elmProperties, m_prefix, ELM_PROPERTIES, m_prefix); - foreach (System.Collections.DictionaryEntry entry in properties) + writer.WriteStartElement(m_elmProperties, Prefix, ELM_PROPERTIES, Prefix); + foreach (KeyValuePair entry in properties) { - writer.WriteStartElement(m_elmData, m_prefix, ELM_DATA, m_prefix); - writer.WriteAttributeString(ATTR_NAME, Transform.MaskXmlInvalidCharacters((string)entry.Key, this.InvalidCharReplacement)); + writer.WriteStartElement(m_elmData, Prefix, ELM_DATA, Prefix); + writer.WriteAttributeString(ATTR_NAME, Transform.MaskXmlInvalidCharacters(entry.Key, InvalidCharReplacement)); // Use an ObjectRenderer to convert the object to a string - string valueStr = null; - if (!this.Base64EncodeProperties) + string valueStr; + if (!Base64EncodeProperties) { - valueStr = Transform.MaskXmlInvalidCharacters(loggingEvent.Repository.RendererMap.FindAndRender(entry.Value), this.InvalidCharReplacement); + valueStr = Transform.MaskXmlInvalidCharacters(loggingEvent.Repository.RendererMap.FindAndRender(entry.Value), InvalidCharReplacement); } else { @@ -285,8 +259,8 @@ protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) if (exceptionStr != null && exceptionStr.Length > 0) { // Append the stack trace line - writer.WriteStartElement(m_elmException, m_prefix, ELM_EXCEPTION, m_prefix); - Transform.WriteEscapedXmlString(writer, exceptionStr, this.InvalidCharReplacement); + writer.WriteStartElement(m_elmException, Prefix, ELM_EXCEPTION, Prefix); + Transform.WriteEscapedXmlString(writer, exceptionStr, InvalidCharReplacement); writer.WriteEndElement(); } @@ -294,7 +268,7 @@ protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) { LocationInfo locationInfo = loggingEvent.LocationInformation; - writer.WriteStartElement(m_elmLocation, m_prefix, ELM_LOCATION, m_prefix); + writer.WriteStartElement(m_elmLocation, Prefix, ELM_LOCATION, Prefix); writer.WriteAttributeString(ATTR_CLASS, locationInfo.ClassName); writer.WriteAttributeString(ATTR_METHOD, locationInfo.MethodName); writer.WriteAttributeString(ATTR_FILE, locationInfo.FileName); @@ -305,15 +279,6 @@ protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) writer.WriteEndElement(); } - #endregion Override implementation of XMLLayoutBase - - #region Private Instance Fields - - /// - /// The prefix to use for all generated element names - /// - private string m_prefix = PREFIX; - private string m_elmEvent = ELM_EVENT; private string m_elmMessage = ELM_MESSAGE; private string m_elmData = ELM_DATA; @@ -321,19 +286,11 @@ protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) private string m_elmException = ELM_EXCEPTION; private string m_elmLocation = ELM_LOCATION; - private bool m_base64Message = false; - private bool m_base64Properties = false; - - #endregion Private Instance Fields - - #region Private Static Fields - private const string PREFIX = "log4net"; private const string ELM_EVENT = "event"; private const string ELM_MESSAGE = "message"; private const string ELM_PROPERTIES = "properties"; - private const string ELM_GLOBAL_PROPERTIES = "global-properties"; private const string ELM_DATA = "data"; private const string ELM_EXCEPTION = "exception"; private const string ELM_LOCATION = "locationInfo"; @@ -351,9 +308,6 @@ protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) private const string ATTR_LINE = "line"; private const string ATTR_NAME = "name"; private const string ATTR_VALUE = "value"; - - - #endregion Private Static Fields } } diff --git a/src/log4net/Layout/XmlLayoutBase.cs b/src/log4net/Layout/XmlLayoutBase.cs index 798fcc6b..0002c467 100644 --- a/src/log4net/Layout/XmlLayoutBase.cs +++ b/src/log4net/Layout/XmlLayoutBase.cs @@ -19,7 +19,6 @@ using System; using System.IO; -using System.Text; using System.Xml; using log4net.Util; @@ -44,8 +43,6 @@ namespace log4net.Layout /// Gert Driesen public abstract class XmlLayoutBase : LayoutSkeleton { - #region Protected Instance Constructors - /// /// Protected constructor to support subclasses /// @@ -80,13 +77,9 @@ protected XmlLayoutBase() : this(false) protected XmlLayoutBase(bool locationInfo) { IgnoresException = false; - m_locationInfo = locationInfo; + LocationInfo = locationInfo; } - #endregion Protected Instance Constructors - - #region Public Instance Properties - /// /// Gets a value indicating whether to include location information in /// the XML events. @@ -107,11 +100,8 @@ protected XmlLayoutBase(bool locationInfo) /// appender as well. /// /// - public bool LocationInfo - { - get { return m_locationInfo; } - set { m_locationInfo = value; } - } + public bool LocationInfo { get; set; } + /// /// The string to replace characters that can not be expressed in XML with. /// @@ -125,14 +115,7 @@ public bool LocationInfo /// /// /// - public string InvalidCharReplacement - { - get { return m_invalidCharReplacement; } - set { m_invalidCharReplacement = value; } - } - #endregion - - #region Implementation of IOptionHandler + public string InvalidCharReplacement { get; set; } = "?"; /// /// Initialize layout options @@ -155,10 +138,6 @@ public override void ActivateOptions() // nothing to do } - #endregion Implementation of IOptionHandler - - #region Override implementation of LayoutSkeleton - /// /// Gets the content type output by this layout. /// @@ -193,9 +172,9 @@ public override string ContentType /// public override void Format(TextWriter writer, LoggingEvent loggingEvent) { - if (loggingEvent == null) + if (loggingEvent is null) { - throw new ArgumentNullException("loggingEvent"); + throw new ArgumentNullException(nameof(loggingEvent)); } using XmlWriter xmlWriter = XmlWriterExtensions.CreateXmlWriter(writer); // Write the event to the writer @@ -208,10 +187,6 @@ public override void Format(TextWriter writer, LoggingEvent loggingEvent) // -> Dispose from using var will close & flush } - #endregion Override implementation of LayoutSkeleton - - #region Protected Instance Methods - /// /// Does the actual writing of the XML. /// @@ -224,22 +199,5 @@ public override void Format(TextWriter writer, LoggingEvent loggingEvent) /// /// protected abstract void FormatXml(XmlWriter writer, LoggingEvent loggingEvent); - - #endregion Protected Instance Methods - - #region Private Instance Fields - - /// - /// Flag to indicate if location information should be included in - /// the XML events. - /// - private bool m_locationInfo = false; - - /// - /// The string to replace invalid chars with - /// - private string m_invalidCharReplacement = "?"; - - #endregion Private Instance Fields } } \ No newline at end of file diff --git a/src/log4net/Layout/XmlLayoutSchemaLog4j.cs b/src/log4net/Layout/XmlLayoutSchemaLog4j.cs index ef69e23f..734a1648 100644 --- a/src/log4net/Layout/XmlLayoutSchemaLog4j.cs +++ b/src/log4net/Layout/XmlLayoutSchemaLog4j.cs @@ -18,9 +18,8 @@ #endregion using System; -using System.Text; +using System.Collections.Generic; using System.Xml; -using System.IO; using log4net.Core; using log4net.Util; @@ -39,21 +38,15 @@ namespace log4net.Layout /// Nicko Cadell public class XmlLayoutSchemaLog4j : XmlLayoutBase { - #region Static Members - /// /// The 1st of January 1970 in UTC /// - private static readonly DateTime s_date1970 = new DateTime(1970, 1, 1); - - #endregion - - #region Constructors + private static readonly DateTime s_date1970 = new(1970, 1, 1); /// /// Constructs an XMLLayoutSchemaLog4j /// - public XmlLayoutSchemaLog4j() : base() + public XmlLayoutSchemaLog4j() { } @@ -64,7 +57,7 @@ public XmlLayoutSchemaLog4j() : base() /// /// The LocationInfo option takes a boolean value. By /// default, it is set to false which means there will be no location - /// information output by this layout. If the the option is set to + /// information output by this layout. If the option is set to /// true, then the file name and line number of the statement /// at the origin of the log statement will be output. /// @@ -78,10 +71,6 @@ public XmlLayoutSchemaLog4j(bool locationInfo) : base(locationInfo) { } - #endregion - - #region Public Properties - /// /// The version of the log4j schema to use. /// @@ -102,8 +91,6 @@ public string Version } } - #endregion - /* Example log4j schema event @@ -142,32 +129,31 @@ protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) // Translate logging events for log4j // Translate hostname property - if (loggingEvent.LookupProperty(LoggingEvent.HostNameProperty) != null && - loggingEvent.LookupProperty("log4jmachinename") == null) + if (loggingEvent.LookupProperty(LoggingEvent.HostNameProperty) is not null && + loggingEvent.LookupProperty("log4jmachinename") is null) { loggingEvent.GetProperties()["log4jmachinename"] = loggingEvent.LookupProperty(LoggingEvent.HostNameProperty); } // translate appdomain name - if (loggingEvent.LookupProperty("log4japp") == null && - loggingEvent.Domain != null && + if (loggingEvent.LookupProperty("log4japp") is null && + loggingEvent.Domain is not null && loggingEvent.Domain.Length > 0) { loggingEvent.GetProperties()["log4japp"] = loggingEvent.Domain; } // translate identity name - if (loggingEvent.Identity != null && + if (loggingEvent.Identity is not null && loggingEvent.Identity.Length > 0 && - loggingEvent.LookupProperty(LoggingEvent.IdentityProperty) == null) + loggingEvent.LookupProperty(LoggingEvent.IdentityProperty) is null) { loggingEvent.GetProperties()[LoggingEvent.IdentityProperty] = loggingEvent.Identity; } // translate user name - if (loggingEvent.UserName != null && - loggingEvent.UserName.Length > 0 && - loggingEvent.LookupProperty(LoggingEvent.UserNameProperty) == null) + if (loggingEvent.UserName.Length > 0 && + loggingEvent.LookupProperty(LoggingEvent.UserNameProperty) is null) { loggingEvent.GetProperties()[LoggingEvent.UserNameProperty] = loggingEvent.UserName; } @@ -189,19 +175,19 @@ protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) // Append the message text writer.WriteStartElement("log4j:message", "log4j", "message", "log4net"); - Transform.WriteEscapedXmlString(writer, loggingEvent.RenderedMessage, this.InvalidCharReplacement); + Transform.WriteEscapedXmlString(writer, loggingEvent.RenderedMessage, InvalidCharReplacement); writer.WriteEndElement(); object ndcObj = loggingEvent.LookupProperty("NDC"); - if (ndcObj != null) + if (ndcObj is not null) { - string valueStr = loggingEvent.Repository.RendererMap.FindAndRender(ndcObj); + string? valueStr = loggingEvent.Repository.RendererMap.FindAndRender(ndcObj); - if (valueStr != null && valueStr.Length > 0) + if (valueStr is not null && valueStr.Length > 0) { // Append the NDC text writer.WriteStartElement("log4j:NDC", "log4j", "NDC", "log4net"); - Transform.WriteEscapedXmlString(writer, valueStr, this.InvalidCharReplacement); + Transform.WriteEscapedXmlString(writer, valueStr, InvalidCharReplacement); writer.WriteEndElement(); } } @@ -211,10 +197,10 @@ protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) if (properties.Count > 0) { writer.WriteStartElement("log4j:properties", "log4j", "properties", "log4net"); - foreach (System.Collections.DictionaryEntry entry in properties) + foreach (KeyValuePair entry in properties) { writer.WriteStartElement("log4j:data", "log4j", "data", "log4net"); - writer.WriteAttributeString("name", (string)entry.Key); + writer.WriteAttributeString("name", entry.Key); // Use an ObjectRenderer to convert the object to a string string valueStr = loggingEvent.Repository.RendererMap.FindAndRender(entry.Value); @@ -230,13 +216,13 @@ protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) { // Append the stack trace line writer.WriteStartElement("log4j:throwable", "log4j", "data", "log4net"); - Transform.WriteEscapedXmlString(writer, exceptionStr, this.InvalidCharReplacement); + Transform.WriteEscapedXmlString(writer, exceptionStr, InvalidCharReplacement); writer.WriteEndElement(); } if (LocationInfo) { - LocationInfo locationInfo = loggingEvent.LocationInformation; + LocationInfo? locationInfo = loggingEvent.LocationInformation; writer.WriteStartElement("log4j:locationInfo", "log4j", "locationInfo", "log4net"); writer.WriteAttributeString("class", locationInfo.ClassName); diff --git a/src/log4net/LogManager.cs b/src/log4net/LogManager.cs index 939295e0..c78b7f06 100644 --- a/src/log4net/LogManager.cs +++ b/src/log4net/LogManager.cs @@ -19,7 +19,7 @@ using System; using System.Reflection; - +using log4net.Appender; using log4net.Core; using log4net.Repository; @@ -55,24 +55,8 @@ namespace log4net /// /// Nicko Cadell /// Gert Driesen - public sealed class LogManager + public static class LogManager { - #region Private Instance Constructors - - /// - /// Initializes a new instance of the class. - /// - /// - /// Uses a private access modifier to prevent instantiation of this class. - /// - private LogManager() - { - } - - #endregion Private Instance Constructors - - #region Type Specific Manager Methods - /// Returns the named logger if it exists. /// /// Returns the named logger if it exists. @@ -85,7 +69,7 @@ private LogManager() /// /// The fully qualified logger name to look for. /// The logger found, or null if no logger could be found. - public static ILog Exists(string name) + public static ILog? Exists(string name) { return Exists(Assembly.GetCallingAssembly(), name); } @@ -142,7 +126,7 @@ public static ILog GetLogger(string name) /// The logger found, or null if the logger doesn't exist in the specified /// repository. /// - public static ILog Exists(string repository, string name) + public static ILog? Exists(string repository, string name) { return WrapLogger(LoggerManager.Exists(repository, name)); } @@ -157,13 +141,13 @@ public static ILog Exists(string repository, string name) /// null. /// /// - /// The assembly to use to lookup the repository. + /// The assembly to use to look up the repository. /// The fully qualified logger name to look for. /// /// The logger, or null if the logger doesn't exist in the specified /// assembly's repository. /// - public static ILog Exists(Assembly repositoryAssembly, string name) + public static ILog? Exists(Assembly repositoryAssembly, string name) { return WrapLogger(LoggerManager.Exists(repositoryAssembly, name)); } @@ -184,7 +168,7 @@ public static ILog[] GetCurrentLoggers(string repository) /// /// Returns all the currently defined loggers in the specified assembly's repository. /// - /// The assembly to use to lookup the repository. + /// The assembly to use to look up the repository. /// /// The root logger is not included in the returned array. /// @@ -215,7 +199,7 @@ public static ILog[] GetCurrentLoggers(Assembly repositoryAssembly) /// The logger with the name specified. public static ILog GetLogger(string repository, string name) { - return WrapLogger(LoggerManager.GetLogger(repository, name)); + return WrapLogger(LoggerManager.GetLogger(repository, name))!; } /// @@ -234,12 +218,12 @@ public static ILog GetLogger(string repository, string name) /// log4net. /// /// - /// The assembly to use to lookup the repository. + /// The assembly to use to look up the repository. /// The name of the logger to retrieve. /// The logger with the name specified. public static ILog GetLogger(Assembly repositoryAssembly, string name) { - return WrapLogger(LoggerManager.GetLogger(repositoryAssembly, name)); + return WrapLogger(LoggerManager.GetLogger(repositoryAssembly, name))!; } /// @@ -252,7 +236,7 @@ public static ILog GetLogger(Assembly repositoryAssembly, string name) /// The logger with the name specified. public static ILog GetLogger(Type type) { - return GetLogger(Assembly.GetCallingAssembly(), type.FullName); + return GetLogger(Assembly.GetCallingAssembly(), type.FullName!); } /// @@ -266,7 +250,7 @@ public static ILog GetLogger(Type type) /// The logger with the name specified. public static ILog GetLogger(string repository, Type type) { - return WrapLogger(LoggerManager.GetLogger(repository, type)); + return WrapLogger(LoggerManager.GetLogger(repository, type))!; } /// @@ -275,18 +259,14 @@ public static ILog GetLogger(string repository, Type type) /// /// Gets the logger for the fully qualified name of the type specified. /// - /// The assembly to use to lookup the repository. + /// The assembly to use to look up the repository. /// The full name of will be used as the name of the logger to retrieve. /// The logger with the name specified. public static ILog GetLogger(Assembly repositoryAssembly, Type type) { - return WrapLogger(LoggerManager.GetLogger(repositoryAssembly, type)); + return WrapLogger(LoggerManager.GetLogger(repositoryAssembly, type))!; } - #endregion Type Specific Manager Methods - - #region Domain & Repository Manager Methods - /// /// Shuts down the log4net system. /// @@ -301,7 +281,7 @@ public static ILog GetLogger(Assembly repositoryAssembly, Type type) /// Otherwise, pending logging events might be lost. /// /// The shutdown method is careful to close nested - /// appenders before closing regular appenders. This is allows + /// appenders before closing regular appenders. This allows /// configurations where a regular appender is attached to a logger /// and again to a nested appender. /// @@ -325,7 +305,7 @@ public static void Shutdown() /// Otherwise, pending logging events might be lost. /// /// The shutdown method is careful to close nested - /// appenders before closing regular appenders. This is allows + /// appenders before closing regular appenders. This allows /// configurations where a regular appender is attached to a logger /// and again to a nested appender. /// @@ -349,12 +329,12 @@ public static void ShutdownRepository() /// Otherwise, pending logging events might be lost. /// /// The shutdown method is careful to close nested - /// appenders before closing regular appenders. This is allows + /// appenders before closing regular appenders. This allows /// configurations where a regular appender is attached to a logger /// and again to a nested appender. /// /// - /// The repository to shutdown. + /// The repository to shut down. public static void ShutdownRepository(string repository) { LoggerManager.ShutdownRepository(repository); @@ -376,12 +356,12 @@ public static void ShutdownRepository(string repository) /// /// /// The shutdown method is careful to close nested - /// appenders before closing regular appenders. This is allows + /// appenders before closing regular appenders. This allows /// configurations where a regular appender is attached to a logger /// and again to a nested appender. /// /// - /// The assembly to use to lookup the repository. + /// The assembly to use to look up the repository. public static void ShutdownRepository(Assembly repositoryAssembly) { LoggerManager.ShutdownRepository(repositoryAssembly); @@ -438,7 +418,7 @@ public static void ResetConfiguration(string repository) /// message disabling is set to its default "off" value. /// /// - /// The assembly to use to lookup the repository to reset. + /// The assembly to use to look up the repository to reset. public static void ResetConfiguration(Assembly repositoryAssembly) { LoggerManager.ResetConfiguration(repositoryAssembly); @@ -488,7 +468,7 @@ public static ILoggerRepository GetLoggerRepository(string repository) /// by the argument. /// /// - /// The assembly to use to lookup the repository. + /// The assembly to use to look up the repository. [Obsolete("Use GetRepository instead of GetLoggerRepository")] public static ILoggerRepository GetLoggerRepository(Assembly repositoryAssembly) { @@ -537,7 +517,7 @@ public static ILoggerRepository GetRepository(string repository) /// by the argument. /// /// - /// The assembly to use to lookup the repository. + /// The assembly to use to look up the repository. public static ILoggerRepository GetRepository(Assembly repositoryAssembly) { return LoggerManager.GetRepository(repositoryAssembly); @@ -738,33 +718,26 @@ public static ILoggerRepository[] GetAllRepositories() /// /// Flushes logging events buffered in all configured appenders in the default repository. /// - /// The maximum time in milliseconds to wait for logging events from asycnhronous appenders to be flushed. + /// The maximum time in milliseconds to wait for logging events from asynchronous appenders to be flushed. /// True if all logging events were flushed successfully, else false. public static bool Flush(int millisecondsTimeout) { - Appender.IFlushable flushableRepository = LoggerManager.GetRepository(Assembly.GetCallingAssembly()) as Appender.IFlushable; - if (flushableRepository == null) + if (LoggerManager.GetRepository(Assembly.GetCallingAssembly()) is not IFlushable flushableRepository) { return false; } - else - { - return flushableRepository.Flush(millisecondsTimeout); - } - } - #endregion Domain & Repository Manager Methods - - #region Extension Handlers + return flushableRepository.Flush(millisecondsTimeout); + } /// /// Looks up the wrapper object for the logger specified. /// /// The logger to get the wrapper for. /// The wrapper for the logger specified. - private static ILog WrapLogger(ILogger logger) + private static ILog? WrapLogger(ILogger? logger) { - return (ILog)s_wrapperMap.GetWrapper(logger); + return (ILog?)s_wrapperMap.GetWrapper(logger); } /// @@ -793,15 +766,9 @@ private static ILoggerWrapper WrapperCreationHandler(ILogger logger) return new LogImpl(logger); } - #endregion - - #region Private Static Fields - /// /// The wrapper map to use to hold the objects. /// - private static readonly WrapperMap s_wrapperMap = new WrapperMap(new WrapperCreationHandler(WrapperCreationHandler)); - - #endregion Private Static Fields + private static readonly WrapperMap s_wrapperMap = new(WrapperCreationHandler); } } \ No newline at end of file diff --git a/src/log4net/LogicalThreadContext.cs b/src/log4net/LogicalThreadContext.cs index ca399f66..f19e230b 100644 --- a/src/log4net/LogicalThreadContext.cs +++ b/src/log4net/LogicalThreadContext.cs @@ -82,73 +82,22 @@ namespace log4net /// /// /// Nicko Cadell - public sealed class LogicalThreadContext + public static class LogicalThreadContext { - #region Private Instance Constructors - - /// - /// Private Constructor. - /// - /// - /// - /// Uses a private access modifier to prevent instantiation of this class. - /// - /// - private LogicalThreadContext() - { - } - - #endregion Private Instance Constructors - - #region Public Static Properties - /// /// The thread properties map /// - /// - /// The thread properties map - /// /// /// /// The LogicalThreadContext properties override any /// or properties with the same name. /// /// - public static LogicalThreadContextProperties Properties - { - get { return s_properties; } - } + public static LogicalThreadContextProperties Properties { get; } = new(); /// - /// The thread stacks - /// - /// - /// stack map - /// - /// - /// /// The logical thread stacks. - /// - /// - public static LogicalThreadContextStacks Stacks - { - get { return s_stacks; } - } - - #endregion Public Static Properties - - #region Private Static Fields - - /// - /// The thread context properties instance - /// - private static readonly LogicalThreadContextProperties s_properties = new LogicalThreadContextProperties(); - - /// - /// The thread context stacks instance /// - private static readonly LogicalThreadContextStacks s_stacks = new LogicalThreadContextStacks(s_properties); - - #endregion Private Static Fields + public static LogicalThreadContextStacks Stacks { get; } = new(Properties); } } \ No newline at end of file diff --git a/src/log4net/NDC.cs b/src/log4net/NDC.cs index 9109cc6c..ea939c9f 100644 --- a/src/log4net/NDC.cs +++ b/src/log4net/NDC.cs @@ -44,7 +44,7 @@ namespace log4net /// come into play. /// /// - /// Note that NDCs are managed on a per thread basis. The NDC class + /// Note that NDCs are managed on a per-thread basis. The NDC class /// is made up of static methods that operate on the context of the /// calling thread. /// @@ -62,24 +62,8 @@ namespace log4net /// Nicko Cadell /// Gert Driesen /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ - public sealed class NDC + public static class NDC { - #region Private Instance Constructors - - /// - /// Initializes a new instance of the class. - /// - /// - /// Uses a private access modifier to prevent instantiation of this class. - /// - private NDC() - { - } - - #endregion Private Instance Constructors - - #region Public Static Properties - /// /// Gets the current context depth. /// @@ -106,10 +90,6 @@ public static int Depth get { return ThreadContext.Stacks["NDC"].Count; } } - #endregion Public Static Properties - - #region Public Static Methods - /// /// Clears all the contextual information held on the current thread. /// @@ -201,7 +181,7 @@ public static void Inherit(Stack stack) /// /// /*[Obsolete("NDC has been replaced by ThreadContext.Stacks")]*/ - public static string Pop() + public static string? Pop() { return ThreadContext.Stacks["NDC"].Pop(); } @@ -324,7 +304,7 @@ public static void SetMaxDepth(int maxDepth) { if (maxDepth >= 0) { - log4net.Util.ThreadContextStack stack = ThreadContext.Stacks["NDC"]; + Util.ThreadContextStack stack = ThreadContext.Stacks["NDC"]; if (maxDepth == 0) { @@ -339,7 +319,5 @@ public static void SetMaxDepth(int maxDepth) } } } - - #endregion Public Static Methods } -} \ No newline at end of file +} diff --git a/src/log4net/Repository/Hierarchy/DefaultLoggerFactory.cs b/src/log4net/Repository/Hierarchy/DefaultLoggerFactory.cs index 2f55243e..3aea766b 100644 --- a/src/log4net/Repository/Hierarchy/DefaultLoggerFactory.cs +++ b/src/log4net/Repository/Hierarchy/DefaultLoggerFactory.cs @@ -35,55 +35,27 @@ namespace log4net.Repository.Hierarchy /// Gert Driesen internal class DefaultLoggerFactory : ILoggerFactory { - #region Internal Instance Constructors - /// - /// Default constructor - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - internal DefaultLoggerFactory() - { - } - - #endregion Internal Instance Constructors - - #region Implementation of ILoggerFactory - - /// - /// Create a new instance + /// Create a new instance with the specified name. /// /// The that will own the . - /// The name of the . + /// The name of the . If null, the root logger is returned. /// The instance for the specified name. /// /// - /// Create a new instance with the - /// specified name. - /// - /// /// Called by the to create /// new named instances. /// - /// - /// If the is null then the root logger - /// must be returned. - /// /// - public Logger CreateLogger(ILoggerRepository repository, string name) + public Logger CreateLogger(ILoggerRepository repository, string? name) { - if (name == null) + if (name is null) { return new RootLogger(repository.LevelMap.LookupWithDefault(Level.Debug)); } return new LoggerImpl(name); } - #endregion - /// /// Default internal subclass of /// @@ -97,15 +69,10 @@ public Logger CreateLogger(ILoggerRepository repository, string name) internal sealed class LoggerImpl : Logger { /// - /// Construct a new Logger - /// - /// the name of the logger - /// - /// /// Initializes a new instance of the class /// with the specified name. - /// - /// + /// + /// the name of the logger internal LoggerImpl(string name) : base(name) { } diff --git a/src/log4net/Repository/Hierarchy/Hierarchy.cs b/src/log4net/Repository/Hierarchy/Hierarchy.cs index 144b5c40..56dd2963 100644 --- a/src/log4net/Repository/Hierarchy/Hierarchy.cs +++ b/src/log4net/Repository/Hierarchy/Hierarchy.cs @@ -18,16 +18,15 @@ #endregion using System; -using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; using log4net.Appender; using log4net.Core; -using log4net.Repository; using log4net.Util; namespace log4net.Repository.Hierarchy { - #region LoggerCreationEvent - /// /// Delegate used to handle logger creation event notifications. /// @@ -51,12 +50,7 @@ namespace log4net.Repository.Hierarchy /// public class LoggerCreationEventArgs : EventArgs { - /// - /// The created - /// - private Logger m_log; - - /// + /// /// Constructor /// /// The that has been created. @@ -68,7 +62,7 @@ public class LoggerCreationEventArgs : EventArgs /// public LoggerCreationEventArgs(Logger log) { - m_log = log; + Logger = log; } /// @@ -82,14 +76,9 @@ public LoggerCreationEventArgs(Logger log) /// The that has been created. /// /// - public Logger Logger - { - get { return m_log; } - } + public Logger Logger { get; } } - #endregion LoggerCreationEvent - /// /// Hierarchical organization of loggers /// @@ -121,8 +110,6 @@ public Logger Logger /// Gert Driesen public class Hierarchy : LoggerRepositorySkeleton, IBasicRepositoryConfigurator, IXmlRepositoryConfigurator { - #region Public Events - /// /// Event used to notify that a logger has been created. /// @@ -131,15 +118,7 @@ public class Hierarchy : LoggerRepositorySkeleton, IBasicRepositoryConfigurator, /// Event raised when a logger is created. /// /// - public event LoggerCreationEventHandler LoggerCreatedEvent - { - add { m_loggerCreatedEvent += value; } - remove { m_loggerCreatedEvent -= value; } - } - - #endregion Public Events - - #region Public Instance Constructors + public event LoggerCreationEventHandler? LoggerCreatedEvent; /// /// Default constructor @@ -193,20 +172,14 @@ public Hierarchy(ILoggerFactory loggerFactory) : this(new PropertiesDictionary() /// public Hierarchy(PropertiesDictionary properties, ILoggerFactory loggerFactory) : base(properties) { - if (loggerFactory == null) + if (loggerFactory is null) { - throw new ArgumentNullException("loggerFactory"); + throw new ArgumentNullException(nameof(loggerFactory)); } m_defaultFactory = loggerFactory; - - m_ht = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable()); } - #endregion Public Instance Constructors - - #region Public Instance Properties - /// /// Has no appender warning been emitted /// @@ -216,11 +189,7 @@ public Hierarchy(PropertiesDictionary properties, ILoggerFactory loggerFactory) /// about not having an appender warning. /// /// - public bool EmittedNoAppenderWarning - { - get { return m_emittedNoAppenderWarning; } - set { m_emittedNoAppenderWarning = value; } - } + public bool EmittedNoAppenderWarning { get; set; } /// /// Get the root of this hierarchy @@ -234,11 +203,11 @@ public Logger Root { get { - if (m_root == null) + if (m_root is null) { lock (this) { - if (m_root == null) + if (m_root is null) { // Create the root logger Logger root = m_defaultFactory.CreateLogger(this, null); @@ -256,7 +225,6 @@ public Logger Root /// /// Gets or sets the default instance. /// - /// The default /// /// /// The logger factory is used to create logger instances. @@ -264,21 +232,13 @@ public Logger Root /// public ILoggerFactory LoggerFactory { - get { return m_defaultFactory; } + get => m_defaultFactory; set { - if (value == null) - { - throw new ArgumentNullException("value"); - } - m_defaultFactory = value; + m_defaultFactory = value ?? throw new ArgumentNullException(nameof(value)); } } - #endregion Public Instance Properties - - #region Override Implementation of LoggerRepositorySkeleton - /// /// Test if a logger exists /// @@ -290,17 +250,15 @@ public ILoggerFactory LoggerFactory /// its reference, otherwise returns null. /// /// - public override ILogger Exists(string name) + public override ILogger? Exists(string name) { - if (name == null) + if (name is null) { - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); } - lock (m_ht) - { - return m_ht[new LoggerKey(name)] as Logger; - } + m_ht.TryGetValue(new LoggerKey(name), out object? o); + return o as Logger; } /// @@ -319,20 +277,17 @@ public override ILogger[] GetCurrentLoggers() // The accumulation in loggers is necessary because not all elements in // ht are Logger objects as there might be some ProvisionNodes // as well. - lock (m_ht) - { - System.Collections.ArrayList loggers = new System.Collections.ArrayList(m_ht.Count); + var loggers = new List(m_ht.Count); - // Iterate through m_ht values - foreach (object node in m_ht.Values) + // Iterate through m_ht values + foreach (object node in m_ht.Values) + { + if (node is Logger logger) { - if (node is Logger) - { - loggers.Add(node); - } + loggers.Add(logger); } - return (Logger[])loggers.ToArray(typeof(Logger)); } + return loggers.ToArray(); } /// @@ -356,7 +311,7 @@ public override ILogger GetLogger(string name) { if (name == null) { - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); } return GetLogger(name, m_defaultFactory); @@ -378,34 +333,31 @@ public override ILogger GetLogger(string name) /// /// /// The Shutdown method is careful to close nested - /// appenders before closing regular appenders. This is allows + /// appenders before closing regular appenders. This allows /// configurations where a regular appender is attached to a logger /// and again to a nested appender. /// /// public override void Shutdown() { - LogLog.Debug(declaringType, "Shutdown called on Hierarchy [" + this.Name + "]"); + LogLog.Debug(declaringType, $"Shutdown called on Hierarchy [{Name}]"); // begin by closing nested appenders Root.CloseNestedAppenders(); - lock (m_ht) - { - ILogger[] currentLoggers = this.GetCurrentLoggers(); + ILogger[] currentLoggers = GetCurrentLoggers(); - foreach (Logger logger in currentLoggers) - { - logger.CloseNestedAppenders(); - } + foreach (Logger logger in currentLoggers.OfType()) + { + logger.CloseNestedAppenders(); + } - // then, remove all appenders - Root.RemoveAllAppenders(); + // then, remove all appenders + Root.RemoveAllAppenders(); - foreach (Logger logger in currentLoggers) - { - logger.RemoveAllAppenders(); - } + foreach (Logger logger in currentLoggers.OfType()) + { + logger.RemoveAllAppenders(); } base.Shutdown(); @@ -436,16 +388,12 @@ public override void ResetConfiguration() Root.Level = LevelMap.LookupWithDefault(Level.Debug); Threshold = LevelMap.LookupWithDefault(Level.All); - // the synchronization is needed to prevent hashtable surprises - lock (m_ht) - { - Shutdown(); // nested locks are OK + Shutdown(); // nested locks are OK - foreach (Logger l in this.GetCurrentLoggers()) - { - l.Level = null; - l.Additivity = true; - } + foreach (Logger logger in GetCurrentLoggers().OfType()) + { + logger.Level = null; + logger.Additivity = true; } base.ResetConfiguration(); @@ -472,12 +420,15 @@ public override void ResetConfiguration() /// public override void Log(LoggingEvent logEvent) { - if (logEvent == null) + if (logEvent is null) { - throw new ArgumentNullException("logEvent"); + throw new ArgumentNullException(nameof(logEvent)); } - this.GetLogger(logEvent.LoggerName, m_defaultFactory).Log(logEvent); + if (logEvent.LoggerName is not null) + { + GetLogger(logEvent.LoggerName, m_defaultFactory).Log(logEvent); + } } /// @@ -494,38 +445,31 @@ public override void Log(LoggingEvent logEvent) /// The list returned is unordered but does not contain duplicates. /// /// - public override Appender.IAppender[] GetAppenders() + public override IAppender[] GetAppenders() { - System.Collections.ArrayList appenderList = new System.Collections.ArrayList(); + var appenderList = new List(); CollectAppenders(appenderList, Root); - foreach (Logger logger in GetCurrentLoggers()) + foreach (Logger logger in GetCurrentLoggers().OfType()) { CollectAppenders(appenderList, logger); } - return (Appender.IAppender[])appenderList.ToArray(typeof(Appender.IAppender)); + return appenderList.ToArray(); } - #endregion Override Implementation of LoggerRepositorySkeleton - - #region Private Static Methods - /// /// Collect the appenders from an . /// The appender may also be a container. /// - /// - /// - private static void CollectAppender(System.Collections.ArrayList appenderList, Appender.IAppender appender) + private static void CollectAppender(List appenderList, IAppender appender) { if (!appenderList.Contains(appender)) { appenderList.Add(appender); - IAppenderAttachable container = appender as IAppenderAttachable; - if (container != null) + if (appender is IAppenderAttachable container) { CollectAppenders(appenderList, container); } @@ -535,20 +479,14 @@ private static void CollectAppender(System.Collections.ArrayList appenderList, A /// /// Collect the appenders from an container /// - /// - /// - private static void CollectAppenders(System.Collections.ArrayList appenderList, IAppenderAttachable container) + private static void CollectAppenders(List appenderList, IAppenderAttachable container) { - foreach (Appender.IAppender appender in container.Appenders) + foreach (IAppender appender in container.Appenders) { CollectAppender(appenderList, appender); } } - #endregion - - #region Implementation of IBasicRepositoryConfigurator - /// /// Initialize the log4net system using the specified appender /// @@ -580,7 +518,7 @@ void IBasicRepositoryConfigurator.Configure(params IAppender[] appenders) /// protected void BasicRepositoryConfigure(params IAppender[] appenders) { - ArrayList configurationMessages = new ArrayList(); + var configurationMessages = new List(); using (new LogLog.LogReceivedAdapter(configurationMessages)) { @@ -598,10 +536,6 @@ protected void BasicRepositoryConfigure(params IAppender[] appenders) OnConfigurationChanged(new ConfigurationChangedEventArgs(configurationMessages)); } - #endregion Implementation of IBasicRepositoryConfigurator - - #region Implementation of IXmlRepositoryConfigurator - /// /// Initialize the log4net system using the specified config /// @@ -624,11 +558,11 @@ void IXmlRepositoryConfigurator.Configure(System.Xml.XmlElement element) /// protected void XmlRepositoryConfigure(System.Xml.XmlElement element) { - ArrayList configurationMessages = new ArrayList(); + var configurationMessages = new List(); using (new LogLog.LogReceivedAdapter(configurationMessages)) { - XmlHierarchyConfigurator config = new XmlHierarchyConfigurator(this); + var config = new XmlHierarchyConfigurator(this); config.Configure(element); } @@ -640,10 +574,6 @@ protected void XmlRepositoryConfigure(System.Xml.XmlElement element) OnConfigurationChanged(new ConfigurationChangedEventArgs(configurationMessages)); } - #endregion Implementation of IXmlRepositoryConfigurator - - #region Public Instance Methods - /// /// Test if this hierarchy is disabled for the specified . /// @@ -667,10 +597,9 @@ protected void XmlRepositoryConfigure(System.Xml.XmlElement element) /// public bool IsDisabled(Level level) { - // Cast level to object for performance - if ((object)level == null) + if (level is null) { - throw new ArgumentNullException("level"); + throw new ArgumentNullException(nameof(level)); } if (Configured) @@ -700,10 +629,7 @@ public bool IsDisabled(Level level) /// public void Clear() { - lock (m_ht) - { - m_ht.Clear(); - } + m_ht.Clear(); } /// @@ -725,61 +651,52 @@ public Logger GetLogger(string name, ILoggerFactory factory) { if (name == null) { - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); } if (factory == null) { - throw new ArgumentNullException("factory"); + throw new ArgumentNullException(nameof(factory)); } - LoggerKey key = new LoggerKey(name); + var key = new LoggerKey(name); // Synchronize to prevent write conflicts. Read conflicts (in // GetEffectiveLevel() method) are possible only if variable // assignments are non-atomic. - lock (m_ht) + if (!m_ht.TryGetValue(key, out object? node)) { - Logger logger = null; + return CreateLogger(null); + } - Object node = m_ht[key]; - if (node == null) - { - logger = factory.CreateLogger(this, name); - logger.Hierarchy = this; - m_ht[key] = logger; - UpdateParents(logger); - OnLoggerCreationEvent(logger); - return logger; - } + if (node is Logger nodeLogger) + { + return nodeLogger; + } - Logger nodeLogger = node as Logger; - if (nodeLogger != null) - { - return nodeLogger; - } + if (node is ProvisionNode nodeProvisionNode) + { + return CreateLogger(l => UpdateChildren(nodeProvisionNode, l)); + } + + // It should be impossible to arrive here but let's keep the compiler happy. + return null!; - ProvisionNode nodeProvisionNode = node as ProvisionNode; - if (nodeProvisionNode != null) + Logger CreateLogger(Action? extraInit) + { + // Use GetOrAdd in case the logger was added after checking above. + return (Logger)m_ht.GetOrAdd(key, _ => { - logger = factory.CreateLogger(this, name); + Logger logger = factory.CreateLogger(this, name); logger.Hierarchy = this; - m_ht[key] = logger; - UpdateChildren(nodeProvisionNode, logger); + extraInit?.Invoke(logger); UpdateParents(logger); OnLoggerCreationEvent(logger); return logger; - } - - // It should be impossible to arrive here but let's keep the compiler happy. - return null; + }); } } - #endregion Public Instance Methods - - #region Protected Instance Methods - /// /// Sends a logger creation event to all registered listeners /// @@ -789,17 +706,9 @@ public Logger GetLogger(string name, ILoggerFactory factory) /// protected virtual void OnLoggerCreationEvent(Logger logger) { - LoggerCreationEventHandler handler = m_loggerCreatedEvent; - if (handler != null) - { - handler(this, new LoggerCreationEventArgs(logger)); - } + LoggerCreatedEvent?.Invoke(this, new LoggerCreationEventArgs(logger)); } - #endregion Protected Instance Methods - - #region Private Instance Methods - /// /// Updates all the parents of the specified logger /// @@ -822,7 +731,7 @@ protected virtual void OnLoggerCreationEvent(Logger logger) /// /// The entry is 's nearest existing parent. We /// update 's parent field with this entry. We also break from - /// he loop because updating our parent's parent is our parent's + /// the loop because updating our parent's parent is our parent's /// responsibility. /// /// @@ -846,40 +755,35 @@ private void UpdateParents(Logger log) { string substr = name.Substring(0, i); - LoggerKey key = new LoggerKey(substr); // simple constructor - Object node = m_ht[key]; + var key = new LoggerKey(substr); + m_ht.TryGetValue(key, out object? node); + // Create a provision node for a future parent. - if (node == null) + if (node is null) { - ProvisionNode pn = new ProvisionNode(log); - m_ht[key] = pn; + m_ht[key] = new ProvisionNode(log); } else { - Logger nodeLogger = node as Logger; - if (nodeLogger != null) + if (node is Logger nodeLogger) { parentFound = true; log.Parent = nodeLogger; break; // no need to update the ancestors of the closest ancestor } + + if (node is ProvisionNode nodeProvisionNode) + { + nodeProvisionNode.Add(log); + } else { - ProvisionNode nodeProvisionNode = node as ProvisionNode; - if (nodeProvisionNode != null) - { - nodeProvisionNode.Add(log); - } - else - { - LogLog.Error(declaringType, "Unexpected object type [" + node.GetType() + "] in ht.", new LogException()); - } + LogLog.Error(declaringType, $"Unexpected object type [{node.GetType()}] in ht.", new LogException()); } } if (i == 0) { - // logger name starts with a dot - // and we've hit the start + // logger name starts with a dot and we've hit the start break; } } @@ -887,15 +791,13 @@ private void UpdateParents(Logger log) // If we could not find any existing parents, then link with root. if (!parentFound) { - log.Parent = this.Root; + log.Parent = Root; } } /// /// Replace a with a in the hierarchy. /// - /// - /// /// /// /// We update the links for all the children that placed themselves @@ -917,13 +819,11 @@ private void UpdateParents(Logger log) /// private static void UpdateChildren(ProvisionNode pn, Logger log) { - for (int i = 0; i < pn.Count; i++) + foreach (Logger childLogger in pn) { - Logger childLogger = (Logger)pn[i]; - // Unless this child already points to a correct (lower) parent, // make log.Parent point to childLogger.Parent and childLogger.Parent to log. - if (!childLogger.Parent.Name.StartsWith(log.Name)) + if (childLogger.Parent is not null && !childLogger.Parent.Name.StartsWith(log.Name, StringComparison.Ordinal)) { log.Parent = childLogger.Parent; childLogger.Parent = log; @@ -937,27 +837,31 @@ private static void UpdateChildren(ProvisionNode pn, Logger log) /// the level values /// /// - /// Define or redefine a Level using the values in the argument - /// - /// /// Supports setting levels via the configuration file. /// /// internal void AddLevel(LevelEntry levelEntry) { - if (levelEntry == null) throw new ArgumentNullException("levelEntry"); - if (levelEntry.Name == null) throw new ArgumentNullException("levelEntry.Name"); + if (levelEntry is null) + { + throw new ArgumentNullException(nameof(levelEntry)); + } + if (levelEntry.Name is null) + { + throw new ArgumentNullException("levelEntry.Name"); + } // Lookup replacement value if (levelEntry.Value == -1) { - Level previousLevel = LevelMap[levelEntry.Name]; - if (previousLevel == null) + if (LevelMap[levelEntry.Name] is Level previousLevel) { - throw new InvalidOperationException("Cannot redefine level [" + levelEntry.Name + "] because it is not defined in the LevelMap. To define the level supply the level value."); + levelEntry.Value = previousLevel.Value; + } + else + { + throw new InvalidOperationException($"Cannot redefine level [{levelEntry.Name}] because it is not defined in the LevelMap. To define the level supply the level value."); } - - levelEntry.Value = previousLevel.Value; } LevelMap.Add(levelEntry.Name, levelEntry.Value, levelEntry.DisplayName); @@ -971,12 +875,8 @@ internal void AddLevel(LevelEntry levelEntry) /// A class to hold the value, name and display name for a level /// /// - internal class LevelEntry + internal sealed class LevelEntry { - private int m_levelValue = -1; - private string m_levelName = null; - private string m_levelDisplayName = null; - /// /// Value of the level /// @@ -986,11 +886,7 @@ internal class LevelEntry /// up for the current level with the same name. /// /// - public int Value - { - get { return m_levelValue; } - set { m_levelValue = value; } - } + public int Value { get; set; } = -1; /// /// Name of the level @@ -1003,11 +899,7 @@ public int Value /// The name of the level. /// /// - public string Name - { - get { return m_levelName; } - set { m_levelName = value; } - } + public string? Name { get; set; } /// /// Display name for the level @@ -1020,11 +912,7 @@ public string Name /// The display name of the level. /// /// - public string DisplayName - { - get { return m_levelDisplayName; } - set { m_levelDisplayName = value; } - } + public string? DisplayName { get; set; } /// /// Override Object.ToString to return sensible debug info @@ -1032,7 +920,7 @@ public string DisplayName /// string info about this object public override string ToString() { - return "LevelEntry(Value=" + m_levelValue + ", Name=" + m_levelName + ", DisplayName=" + m_levelDisplayName + ")"; + return $"LevelEntry(Value={Value}, Name={Name}, DisplayName={DisplayName})"; } } @@ -1050,28 +938,22 @@ public override string ToString() /// internal void AddProperty(PropertyEntry propertyEntry) { - if (propertyEntry == null) throw new ArgumentNullException("propertyEntry"); - if (propertyEntry.Key == null) throw new ArgumentNullException("propertyEntry.Key"); + if (propertyEntry is null) + { + throw new ArgumentNullException(nameof(propertyEntry)); + } + if (propertyEntry.Key is null) + { + throw new ArgumentNullException("propertyEntry.Key"); + } Properties[propertyEntry.Key] = propertyEntry.Value; } - #endregion Private Instance Methods - - #region Private Instance Fields - private ILoggerFactory m_defaultFactory; - private System.Collections.Hashtable m_ht; - private Logger m_root; - - private bool m_emittedNoAppenderWarning = false; - - private event LoggerCreationEventHandler m_loggerCreatedEvent; - - #endregion Private Instance Fields - - #region Private Static Fields + private readonly ConcurrentDictionary m_ht = new(LoggerKey.ComparerInstance); + private Logger? m_root; /// /// The fully qualified type of the Hierarchy class. @@ -1081,7 +963,5 @@ internal void AddProperty(PropertyEntry propertyEntry) /// log message. /// private static readonly Type declaringType = typeof(Hierarchy); - - #endregion Private Static Fields } } diff --git a/src/log4net/Repository/Hierarchy/ILoggerFactory.cs b/src/log4net/Repository/Hierarchy/ILoggerFactory.cs index 9826a97c..5720d4e7 100644 --- a/src/log4net/Repository/Hierarchy/ILoggerFactory.cs +++ b/src/log4net/Repository/Hierarchy/ILoggerFactory.cs @@ -59,6 +59,6 @@ public interface ILoggerFactory /// must be returned. /// /// - Logger CreateLogger(ILoggerRepository repository, string name); + Logger CreateLogger(ILoggerRepository repository, string? name); } } diff --git a/src/log4net/Repository/Hierarchy/Logger.cs b/src/log4net/Repository/Hierarchy/Logger.cs index 255a3b52..e04da5bd 100644 --- a/src/log4net/Repository/Hierarchy/Logger.cs +++ b/src/log4net/Repository/Hierarchy/Logger.cs @@ -142,7 +142,6 @@ public virtual Level EffectiveLevel /// Gets or sets the where this /// Logger instance is attached to. /// - /// The hierarchy that this logger belongs to. /// /// /// This logger must be attached to a single . @@ -160,11 +159,6 @@ public virtual Hierarchy? Hierarchy /// /// The of this logger. /// - /// - /// - /// The assigned can be null. - /// - /// public virtual Level? Level { get; set; } /// @@ -174,10 +168,6 @@ public virtual Hierarchy? Hierarchy /// An appender to add to this logger /// /// - /// Add to the list of appenders of this - /// Logger instance. - /// - /// /// If is already in the list of /// appenders, then it won't be added again. /// @@ -205,14 +195,10 @@ public virtual void AddAppender(IAppender newAppender) /// Get the appenders contained in this logger as an /// . /// - /// A collection of the appenders in this logger - /// - /// - /// Get the appenders contained in this logger as an - /// . If no appenders + /// + /// A collection of the appenders in this logger. If no appenders /// can be found, then a is returned. - /// - /// + /// public virtual AppenderCollection Appenders { get @@ -241,11 +227,6 @@ public virtual AppenderCollection Appenders /// /// The name of the appender to lookup /// The appender with the name specified, or null. - /// - /// - /// Returns the named appender, or null if the appender is not found. - /// - /// public virtual IAppender? GetAppender(string? name) { m_appenderLock.AcquireReaderLock(); @@ -265,13 +246,10 @@ public virtual AppenderCollection Appenders } /// - /// Remove all previously added appenders from this Logger instance. + /// Removes all previously added appenders from this Logger instance. /// /// /// - /// Remove all previously added appenders from this Logger instance. - /// - /// /// This is useful when re-reading configuration information. /// /// @@ -299,7 +277,6 @@ public virtual void RemoveAllAppenders() /// The appender removed from the list /// /// - /// Remove the appender passed as parameter form the list of appenders. /// The appender removed is not closed. /// If you are discarding the appender you must call /// on the appender removed. @@ -329,7 +306,6 @@ public virtual void RemoveAllAppenders() /// The appender removed from the list /// /// - /// Remove the named appender passed as parameter form the list of appenders. /// The appender removed is not closed. /// If you are discarding the appender you must call /// on the appender removed. @@ -355,18 +331,11 @@ public virtual void RemoveAllAppenders() /// /// Gets the logger name. /// - /// - /// The name of the logger. - /// - /// - /// - /// The name of this logger - /// - /// public virtual string Name { get; } /// - /// This generic form is intended to be used by wrappers. + /// Generates a logging event for the specified using + /// the and . /// /// The declaring type of the method that is /// the stack boundary into the logging system for this call. @@ -375,8 +344,7 @@ public virtual void RemoveAllAppenders() /// The exception to log, including its stack trace. /// /// - /// Generate a logging event for the specified using - /// the and . + /// This generic form is intended to be used by wrappers. /// /// /// This method must not throw any exception to the caller. @@ -398,13 +366,13 @@ public virtual void Log(Type? callerStackBoundaryDeclaringType, Level? level, ob } /// - /// This is the most generic printing method that is intended to be used - /// by wrappers. + /// Logs the specified logging event through this logger. /// /// The event being logged. /// /// - /// Logs the specified logging event through this logger. + /// This is the most generic printing method that is intended to be used + /// by wrappers. /// /// /// This method must not throw any exception to the caller. @@ -437,9 +405,6 @@ public virtual void Log(LoggingEvent? logEvent) /// /// /// - /// Test if this logger is going to log events of the specified . - /// - /// /// This method must not throw any exception to the caller. /// /// @@ -467,15 +432,6 @@ public virtual bool IsEnabledFor(Level? level) /// Gets the where this /// Logger instance is attached to. /// - /// - /// The that this logger belongs to. - /// - /// - /// - /// Gets the where this - /// Logger instance is attached to. - /// - /// public ILoggerRepository? Repository => m_hierarchy; /// diff --git a/src/log4net/Repository/Hierarchy/LoggerKey.cs b/src/log4net/Repository/Hierarchy/LoggerKey.cs index ee721656..de16cbcd 100644 --- a/src/log4net/Repository/Hierarchy/LoggerKey.cs +++ b/src/log4net/Repository/Hierarchy/LoggerKey.cs @@ -18,6 +18,7 @@ #endregion using System; +using System.Collections.Generic; namespace log4net.Repository.Hierarchy { @@ -38,10 +39,8 @@ namespace log4net.Repository.Hierarchy /// /// Nicko Cadell /// Gert Driesen - internal sealed class LoggerKey + internal readonly struct LoggerKey { - #region Internal Instance Constructors - /// /// Construct key with string name /// @@ -68,10 +67,6 @@ internal LoggerKey(string name) m_hashCache = name.GetHashCode(); } - #endregion Internal Instance Constructors - - #region Override implementation of Object - /// /// Returns a hash code for the current instance. /// @@ -86,43 +81,19 @@ public override int GetHashCode() return m_hashCache; } - /// - /// Determines whether two instances - /// are equal. - /// - /// The to compare with the current . - /// - /// true if the specified is equal to the current ; otherwise, false. - /// - /// - /// - /// Compares the references of the interned strings. - /// - /// - public override bool Equals(object obj) + private readonly string m_name; + private readonly int m_hashCache; + + public static Comparer ComparerInstance { get; } = new(); + + public sealed class Comparer : IEqualityComparer { - // Compare reference type of this against argument - if (((object)this) == obj) + public bool Equals(LoggerKey x, LoggerKey y) { - return true; + return x.m_hashCache == y.m_hashCache && x.m_name == y.m_name; } - LoggerKey objKey = obj as LoggerKey; - if (objKey != null) - { - // Compare reference types rather than string's overloaded == - return (((object)m_name) == ((object)objKey.m_name)); - } - return false; + public int GetHashCode(LoggerKey obj) => obj.m_hashCache; } - - #endregion - - #region Private Instance Fields - - private readonly string m_name; - private readonly int m_hashCache; - - #endregion Private Instance Fields } -} \ No newline at end of file +} diff --git a/src/log4net/Repository/Hierarchy/ProvisionNode.cs b/src/log4net/Repository/Hierarchy/ProvisionNode.cs index 9262a474..47628519 100644 --- a/src/log4net/Repository/Hierarchy/ProvisionNode.cs +++ b/src/log4net/Repository/Hierarchy/ProvisionNode.cs @@ -17,8 +17,7 @@ // #endregion -using System; -using System.Collections; +using System.Collections.Generic; namespace log4net.Repository.Hierarchy { @@ -38,7 +37,7 @@ namespace log4net.Repository.Hierarchy /// /// Nicko Cadell /// Gert Driesen - internal sealed class ProvisionNode : ArrayList + internal sealed class ProvisionNode : List { /// /// Create a new provision node with child node @@ -50,9 +49,9 @@ internal sealed class ProvisionNode : ArrayList /// with the specified child logger. /// /// - internal ProvisionNode(Logger log) : base() + internal ProvisionNode(Logger log) { - this.Add(log); + Add(log); } } } diff --git a/src/log4net/Repository/Hierarchy/XmlHierarchyConfigurator.cs b/src/log4net/Repository/Hierarchy/XmlHierarchyConfigurator.cs index 7f149ac6..a1d7769e 100644 --- a/src/log4net/Repository/Hierarchy/XmlHierarchyConfigurator.cs +++ b/src/log4net/Repository/Hierarchy/XmlHierarchyConfigurator.cs @@ -19,6 +19,7 @@ using System; using System.Collections; +using System.Collections.Generic; using System.Globalization; using System.Reflection; using System.Xml; @@ -48,8 +49,6 @@ private enum ConfigUpdateMode Overwrite } - #region Public Instance Constructors - /// /// Construct the configurator for a hierarchy /// @@ -63,13 +62,8 @@ private enum ConfigUpdateMode public XmlHierarchyConfigurator(Hierarchy hierarchy) { m_hierarchy = hierarchy; - m_appenderBag = new Hashtable(); } - #endregion Public Instance Constructors - - #region Public Instance Methods - /// /// Configure the hierarchy by parsing a DOM tree of XML elements. /// @@ -79,9 +73,9 @@ public XmlHierarchyConfigurator(Hierarchy hierarchy) /// Configure the hierarchy by parsing a DOM tree of XML elements. /// /// - public void Configure(XmlElement element) + public void Configure(XmlElement? element) { - if (element == null || m_hierarchy == null) + if (element is null) { return; } @@ -90,7 +84,7 @@ public void Configure(XmlElement element) if (rootElementName != CONFIGURATION_TAG) { - LogLog.Error(declaringType, "Xml element is - not a <" + CONFIGURATION_TAG + "> element."); + LogLog.Error(declaringType, $"Xml element is - not a <{CONFIGURATION_TAG}> element."); return; } @@ -98,7 +92,7 @@ public void Configure(XmlElement element) { // Look for a emitDebug attribute to enable internal debug string emitDebugAttribute = element.GetAttribute(EMIT_INTERNAL_DEBUG_ATTR); - LogLog.Debug(declaringType, EMIT_INTERNAL_DEBUG_ATTR + " attribute [" + emitDebugAttribute + "]."); + LogLog.Debug(declaringType, $"{EMIT_INTERNAL_DEBUG_ATTR} attribute [{emitDebugAttribute}]."); if (emitDebugAttribute.Length > 0 && emitDebugAttribute != "null") { @@ -106,7 +100,7 @@ public void Configure(XmlElement element) } else { - LogLog.Debug(declaringType, "Ignoring " + EMIT_INTERNAL_DEBUG_ATTR + " attribute."); + LogLog.Debug(declaringType, $"Ignoring {EMIT_INTERNAL_DEBUG_ATTR} attribute."); } } @@ -114,7 +108,7 @@ public void Configure(XmlElement element) { // Look for a debug attribute to enable internal debug string debugAttribute = element.GetAttribute(INTERNAL_DEBUG_ATTR); - LogLog.Debug(declaringType, INTERNAL_DEBUG_ATTR + " attribute [" + debugAttribute + "]."); + LogLog.Debug(declaringType, $"{INTERNAL_DEBUG_ATTR} attribute [{debugAttribute}]."); if (debugAttribute.Length > 0 && debugAttribute != "null") { @@ -122,38 +116,45 @@ public void Configure(XmlElement element) } else { - LogLog.Debug(declaringType, "Ignoring " + INTERNAL_DEBUG_ATTR + " attribute."); + LogLog.Debug(declaringType, $"Ignoring {INTERNAL_DEBUG_ATTR} attribute."); } string confDebug = element.GetAttribute(CONFIG_DEBUG_ATTR); if (confDebug.Length > 0 && confDebug != "null") { - LogLog.Warn(declaringType, "The \"" + CONFIG_DEBUG_ATTR + "\" attribute is deprecated."); - LogLog.Warn(declaringType, "Use the \"" + INTERNAL_DEBUG_ATTR + "\" attribute instead."); + LogLog.Warn(declaringType, $"The \"{CONFIG_DEBUG_ATTR}\" attribute is deprecated."); + LogLog.Warn(declaringType, $"Use the \"{INTERNAL_DEBUG_ATTR}\" attribute instead."); LogLog.InternalDebugging = OptionConverter.ToBoolean(confDebug, true); } } // Default mode is merge - ConfigUpdateMode configUpdateMode = ConfigUpdateMode.Merge; + ConfigUpdateMode? configUpdateMode = ConfigUpdateMode.Merge; // Look for the config update attribute - string configUpdateModeAttribute = element.GetAttribute(CONFIG_UPDATE_MODE_ATTR); - if (configUpdateModeAttribute != null && configUpdateModeAttribute.Length > 0) + string? configUpdateModeAttribute = element.GetAttribute(CONFIG_UPDATE_MODE_ATTR); + if (!string.IsNullOrEmpty(configUpdateModeAttribute)) { // Parse the attribute try { - configUpdateMode = (ConfigUpdateMode)OptionConverter.ConvertStringTo(typeof(ConfigUpdateMode), configUpdateModeAttribute); + if (OptionConverter.ConvertStringTo(typeof(ConfigUpdateMode), configUpdateModeAttribute) is ConfigUpdateMode mode) + { + configUpdateMode = mode; + } + else + { + LogLog.Error(declaringType, $"Invalid {CONFIG_UPDATE_MODE_ATTR} attribute value [{configUpdateModeAttribute}]"); + } } catch { - LogLog.Error(declaringType, "Invalid " + CONFIG_UPDATE_MODE_ATTR + " attribute value [" + configUpdateModeAttribute + "]"); + LogLog.Error(declaringType, $"Invalid {CONFIG_UPDATE_MODE_ATTR} attribute value [{configUpdateModeAttribute}]"); } } // IMPL: The IFormatProvider argument to Enum.ToString() is deprecated in .NET 2.0 - LogLog.Debug(declaringType, "Configuration update mode [" + configUpdateMode.ToString() + "]."); + LogLog.Debug(declaringType, $"Configuration update mode [{configUpdateMode}]."); // Only reset configuration if overwrite flag specified if (configUpdateMode == ConfigUpdateMode.Overwrite) @@ -206,27 +207,23 @@ public void Configure(XmlElement element) // Lastly set the hierarchy threshold string thresholdStr = element.GetAttribute(THRESHOLD_ATTR); - LogLog.Debug(declaringType, "Hierarchy Threshold [" + thresholdStr + "]"); + LogLog.Debug(declaringType, $"Hierarchy Threshold [{thresholdStr}]"); if (thresholdStr.Length > 0 && thresholdStr != "null") { Level thresholdLevel = (Level)ConvertStringTo(typeof(Level), thresholdStr); - if (thresholdLevel != null) + if (thresholdLevel is not null) { m_hierarchy.Threshold = thresholdLevel; } else { - LogLog.Warn(declaringType, "Unable to set hierarchy threshold using value [" + thresholdStr + "] (with acceptable conversion types)"); + LogLog.Warn(declaringType, $"Unable to set hierarchy threshold using value [{thresholdStr}] (with acceptable conversion types)"); } } // Done reading config } - #endregion Public Instance Methods - - #region Protected Instance Methods - /// /// Parse appenders by IDREF. /// @@ -238,47 +235,42 @@ public void Configure(XmlElement element) /// the appender. /// /// - protected IAppender FindAppenderByReference(XmlElement appenderRef) + protected IAppender? FindAppenderByReference(XmlElement appenderRef) { - string appenderName = appenderRef.GetAttribute(REF_ATTR); + string? appenderName = appenderRef.GetAttribute(REF_ATTR); - IAppender appender = (IAppender)m_appenderBag[appenderName]; - if (appender != null) + if (m_appenderBag.TryGetValue(appenderName, out IAppender? appender)) { return appender; } - else - { - // Find the element with that id - XmlElement element = null; - if (appenderName != null && appenderName.Length > 0) - { - foreach (XmlElement curAppenderElement in appenderRef.OwnerDocument.GetElementsByTagName(APPENDER_TAG)) - { - if (curAppenderElement.GetAttribute("name") == appenderName) - { - element = curAppenderElement; - break; - } - } - } + // Find the element with that id + XmlElement? element = null; - if (element == null) - { - LogLog.Error(declaringType, "XmlHierarchyConfigurator: No appender named [" + appenderName + "] could be found."); - return null; - } - else + if (!string.IsNullOrEmpty(appenderName) && appenderRef.OwnerDocument is not null) + { + foreach (XmlElement curAppenderElement in appenderRef.OwnerDocument.GetElementsByTagName(APPENDER_TAG)) { - appender = ParseAppender(element); - if (appender != null) + if (curAppenderElement.GetAttribute("name") == appenderName) { - m_appenderBag[appenderName] = appender; + element = curAppenderElement; + break; } - return appender; } } + + if (element is null) + { + LogLog.Error(declaringType, $"XmlHierarchyConfigurator: No appender named [{appenderName}] could be found."); + return null; + } + + appender = ParseAppender(element); + if (appender is not null) + { + m_appenderBag[appenderName] = appender; + } + return appender; } /// @@ -292,20 +284,20 @@ protected IAppender FindAppenderByReference(XmlElement appenderRef) /// the appender instance. /// /// - protected IAppender ParseAppender(XmlElement appenderElement) + protected IAppender? ParseAppender(XmlElement appenderElement) { string appenderName = appenderElement.GetAttribute(NAME_ATTR); string typeName = appenderElement.GetAttribute(TYPE_ATTR); - LogLog.Debug(declaringType, "Loading Appender [" + appenderName + "] type: [" + typeName + "]"); + LogLog.Debug(declaringType, $"Loading Appender [{appenderName}] type: [{typeName}]"); try { - IAppender appender = (IAppender)Activator.CreateInstance(SystemInfo.GetTypeFromString(typeName, true, true)); + IAppender appender = (IAppender)Activator.CreateInstance(SystemInfo.GetTypeFromString(typeName, true, true)!); appender.Name = appenderName; foreach (XmlNode currentNode in appenderElement.ChildNodes) { - /* We're only interested in Elements */ + // We're only interested in Elements if (currentNode.NodeType == XmlNodeType.Element) { XmlElement currentElement = (XmlElement)currentNode; @@ -315,20 +307,19 @@ protected IAppender ParseAppender(XmlElement appenderElement) { string refName = currentElement.GetAttribute(REF_ATTR); - IAppenderAttachable appenderContainer = appender as IAppenderAttachable; - if (appenderContainer != null) + if (appender is IAppenderAttachable appenderContainer) { - LogLog.Debug(declaringType, "Attaching appender named [" + refName + "] to appender named [" + appender.Name + "]."); + LogLog.Debug(declaringType, $"Attaching appender named [{refName}] to appender named [{appender.Name}]."); IAppender referencedAppender = FindAppenderByReference(currentElement); - if (referencedAppender != null) + if (referencedAppender is not null) { appenderContainer.AddAppender(referencedAppender); } } else { - LogLog.Error(declaringType, "Requesting attachment of appender named [" + refName + "] to appender named [" + appender.Name + "] which does not implement log4net.Core.IAppenderAttachable."); + LogLog.Error(declaringType, $"Requesting attachment of appender named [{refName}] to appender named [{appender.Name}] which does not implement log4net.Core.IAppenderAttachable."); } } else @@ -339,20 +330,19 @@ protected IAppender ParseAppender(XmlElement appenderElement) } } - IOptionHandler optionHandler = appender as IOptionHandler; - if (optionHandler != null) + if (appender is IOptionHandler optionHandler) { optionHandler.ActivateOptions(); } - LogLog.Debug(declaringType, "Created Appender [" + appenderName + "]"); + LogLog.Debug(declaringType, $"Created Appender [{appenderName}]"); return appender; } catch (Exception ex) { // Yes, it's ugly. But all exceptions point to the same problem: we can't create an Appender - LogLog.Error(declaringType, "Could not create Appender [" + appenderName + "] of type [" + typeName + "]. Reported error follows.", ex); + LogLog.Error(declaringType, $"Could not create Appender [{appenderName}] of type [{typeName}]. Reported error follows.", ex); return null; } } @@ -371,19 +361,21 @@ protected void ParseLogger(XmlElement loggerElement) // Create a new log4net.Logger object from the element. string loggerName = loggerElement.GetAttribute(NAME_ATTR); - LogLog.Debug(declaringType, "Retrieving an instance of log4net.Repository.Logger for logger [" + loggerName + "]."); - Logger log = m_hierarchy.GetLogger(loggerName) as Logger; + LogLog.Debug(declaringType, $"Retrieving an instance of log4net.Repository.Logger for logger [{loggerName}]."); // Setting up a logger needs to be an atomic operation, in order // to protect potential log operations while logger // configuration is in progress. - lock (log) + if (m_hierarchy.GetLogger(loggerName) is Logger log) { - bool additivity = OptionConverter.ToBoolean(loggerElement.GetAttribute(ADDITIVITY_ATTR), true); + lock (log) + { + bool additivity = OptionConverter.ToBoolean(loggerElement.GetAttribute(ADDITIVITY_ATTR), true); - LogLog.Debug(declaringType, "Setting [" + log.Name + "] additivity to [" + additivity + "]."); - log.Additivity = additivity; - ParseChildrenOfLoggerElement(loggerElement, log, false); + LogLog.Debug(declaringType, $"Setting [{log.Name}] additivity to [{additivity}]."); + log.Additivity = additivity; + ParseChildrenOfLoggerElement(loggerElement, log, false); + } } } @@ -433,17 +425,17 @@ protected void ParseChildrenOfLoggerElement(XmlElement catElement, Logger log, b { IAppender appender = FindAppenderByReference(currentElement); string refName = currentElement.GetAttribute(REF_ATTR); - if (appender != null) + if (appender is not null) { - LogLog.Debug(declaringType, "Adding appender named [" + refName + "] to logger [" + log.Name + "]."); + LogLog.Debug(declaringType, $"Adding appender named [{refName}] to logger [{log.Name}]."); log.AddAppender(appender); } else { - LogLog.Error(declaringType, "Appender named [" + refName + "] not found."); + LogLog.Error(declaringType, $"Appender named [{refName}] not found."); } } - else if (currentElement.LocalName == LEVEL_TAG || currentElement.LocalName == PRIORITY_TAG) + else if (currentElement.LocalName is LEVEL_TAG or PRIORITY_TAG) { ParseLevel(currentElement, log, isRoot); } @@ -454,8 +446,7 @@ protected void ParseChildrenOfLoggerElement(XmlElement catElement, Logger log, b } } - IOptionHandler optionHandler = log as IOptionHandler; - if (optionHandler != null) + if (log is IOptionHandler optionHandler) { optionHandler.ActivateOptions(); } @@ -475,23 +466,21 @@ protected void ParseRenderer(XmlElement element) string renderingClassName = element.GetAttribute(RENDERING_TYPE_ATTR); string renderedClassName = element.GetAttribute(RENDERED_TYPE_ATTR); - LogLog.Debug(declaringType, "Rendering class [" + renderingClassName + "], Rendered class [" + renderedClassName + "]."); + LogLog.Debug(declaringType, $"Rendering class [{renderingClassName}], Rendered class [{renderedClassName}]."); IObjectRenderer renderer = (IObjectRenderer)OptionConverter.InstantiateByClassName(renderingClassName, typeof(IObjectRenderer), null); - if (renderer == null) + if (renderer is null) { - LogLog.Error(declaringType, "Could not instantiate renderer [" + renderingClassName + "]."); + LogLog.Error(declaringType, $"Could not instantiate renderer [{renderingClassName}]."); return; } - else + + try { - try - { - m_hierarchy.RendererMap.Put(SystemInfo.GetTypeFromString(renderedClassName, true, true), renderer); - } - catch (Exception e) - { - LogLog.Error(declaringType, "Could not find class [" + renderedClassName + "].", e); - } + m_hierarchy.RendererMap.Put(SystemInfo.GetTypeFromString(renderedClassName, true, true)!, renderer); + } + catch (Exception e) + { + LogLog.Error(declaringType, $"Could not find class [{renderedClassName}].", e); } } @@ -515,7 +504,7 @@ protected void ParseLevel(XmlElement element, Logger log, bool isRoot) } string levelStr = element.GetAttribute(VALUE_ATTR); - LogLog.Debug(declaringType, "Logger [" + loggerName + "] Level string is [" + levelStr + "]."); + LogLog.Debug(declaringType, $"Logger [{loggerName}] Level string is [{levelStr}]."); if (INHERITED == levelStr) { @@ -525,20 +514,20 @@ protected void ParseLevel(XmlElement element, Logger log, bool isRoot) } else { - LogLog.Debug(declaringType, "Logger [" + loggerName + "] level set to inherit from parent."); + LogLog.Debug(declaringType, $"Logger [{loggerName}] level set to inherit from parent."); log.Level = null; } } else { - log.Level = log.Hierarchy.LevelMap[levelStr]; - if (log.Level == null) + log.Level = log.Hierarchy?.LevelMap[levelStr]; + if (log.Level is null) { - LogLog.Error(declaringType, "Undefined level [" + levelStr + "] on Logger [" + loggerName + "]."); + LogLog.Error(declaringType, $"Undefined level [{levelStr}] on Logger [{loggerName}]."); } else { - LogLog.Debug(declaringType, "Logger [" + loggerName + "] level set to [name=\"" + log.Level.Name + "\",value=" + log.Level.Value + "]."); + LogLog.Debug(declaringType, $"Logger [{loggerName}] level set to [name=\"{log.Level.Name}\",value={log.Level.Value}]."); } } } @@ -565,21 +554,20 @@ protected void SetParameter(XmlElement element, object target) string name = element.GetAttribute(NAME_ATTR); // If the name attribute does not exist then use the name of the element - if (element.LocalName != PARAM_TAG || name == null || name.Length == 0) + if (element.LocalName != PARAM_TAG || name.Length == 0) { name = element.LocalName; } // Look for the property on the target object Type targetType = target.GetType(); - Type propertyType = null; + Type? propertyType = null; - PropertyInfo propInfo = null; - MethodInfo methInfo = null; + MethodInfo? methInfo = null; // Try to find a writable property - propInfo = targetType.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.IgnoreCase); - if (propInfo != null && propInfo.CanWrite) + PropertyInfo? propInfo = targetType.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.IgnoreCase); + if (propInfo is not null && propInfo.CanWrite) { // found a property propertyType = propInfo.PropertyType; @@ -590,22 +578,21 @@ protected void SetParameter(XmlElement element, object target) // look for a method with the signature Add(type) methInfo = FindMethodInfo(targetType, name); - - if (methInfo != null) + if (methInfo is not null) { propertyType = methInfo.GetParameters()[0].ParameterType; } } - if (propertyType == null) + if (propertyType is null) { - LogLog.Error(declaringType, "XmlHierarchyConfigurator: Cannot find Property [" + name + "] to set object on [" + target.ToString() + "]"); + LogLog.Error(declaringType, $"XmlHierarchyConfigurator: Cannot find Property [{name}] to set object on [{target}]"); } else { - string propertyValue = null; + string? propertyValue = null; - if (element.GetAttributeNode(VALUE_ATTR) != null) + if (element.GetAttributeNode(VALUE_ATTR) is not null) { propertyValue = element.GetAttribute(VALUE_ATTR); } @@ -614,9 +601,9 @@ protected void SetParameter(XmlElement element, object target) // Concatenate the CDATA and Text nodes together foreach (XmlNode childNode in element.ChildNodes) { - if (childNode.NodeType == XmlNodeType.CDATA || childNode.NodeType == XmlNodeType.Text) + if (childNode.NodeType is XmlNodeType.CDATA or XmlNodeType.Text) { - if (propertyValue == null) + if (propertyValue is null) { propertyValue = childNode.InnerText; } @@ -628,7 +615,7 @@ protected void SetParameter(XmlElement element, object target) } } - if (propertyValue != null) + if (propertyValue is not null) { try { @@ -652,14 +639,14 @@ protected void SetParameter(XmlElement element, object target) // Check if a specific subtype is specified on the element using the 'type' attribute string subTypeString = element.GetAttribute(TYPE_ATTR); - if (subTypeString != null && subTypeString.Length > 0) + if (subTypeString.Length > 0) { // Read the explicit subtype try { - Type subType = SystemInfo.GetTypeFromString(subTypeString, true, true); + Type subType = SystemInfo.GetTypeFromString(subTypeString, true, true)!; - LogLog.Debug(declaringType, "Parameter [" + name + "] specified subtype [" + subType.FullName + "]"); + LogLog.Debug(declaringType, $"Parameter [{name}] specified subtype [{subType.FullName}]"); if (!propertyType.IsAssignableFrom(subType)) { @@ -669,12 +656,12 @@ protected void SetParameter(XmlElement element, object target) // Must re-convert to the real property type parsedObjectConversionTargetType = propertyType; - // Use sub type as intermediary type + // Use subtype as intermediary type propertyType = subType; } else { - LogLog.Error(declaringType, "subtype [" + subType.FullName + "] set on [" + name + "] is not a subclass of property type [" + propertyType.FullName + "] and there are no acceptable type conversions."); + LogLog.Error(declaringType, $"subtype [{subType.FullName}] set on [{name}] is not a subclass of property type [{propertyType.FullName}] and there are no acceptable type conversions."); } } else @@ -686,28 +673,28 @@ protected void SetParameter(XmlElement element, object target) } catch (Exception ex) { - LogLog.Error(declaringType, "Failed to find type [" + subTypeString + "] set on [" + name + "]", ex); + LogLog.Error(declaringType, $"Failed to find type [{subTypeString}] set on [{name}]", ex); } } // Now try to convert the string value to an acceptable type // to pass to this property. - object convertedValue = ConvertStringTo(propertyType, propertyValue); + object? convertedValue = ConvertStringTo(propertyType, propertyValue); // Check if we need to do an additional conversion - if (convertedValue != null && parsedObjectConversionTargetType != null) + if (convertedValue is not null && parsedObjectConversionTargetType is not null) { - LogLog.Debug(declaringType, "Performing additional conversion of value from [" + convertedValue.GetType().Name + "] to [" + parsedObjectConversionTargetType.Name + "]"); + LogLog.Debug(declaringType, $"Performing additional conversion of value from [{convertedValue.GetType().Name}] to [{parsedObjectConversionTargetType.Name}]"); convertedValue = OptionConverter.ConvertTypeTo(convertedValue, parsedObjectConversionTargetType); } - if (convertedValue != null) + if (convertedValue is not null) { - if (propInfo != null) + if (propInfo is not null) { // Got a converted result - LogLog.Debug(declaringType, "Setting Property [" + propInfo.Name + "] to " + convertedValue.GetType().Name + " value [" + convertedValue.ToString() + "]"); + LogLog.Debug(declaringType, $"Setting Property [{propInfo.Name}] to {convertedValue.GetType().Name} value [{convertedValue}]"); try { @@ -716,33 +703,33 @@ protected void SetParameter(XmlElement element, object target) } catch (TargetInvocationException targetInvocationEx) { - LogLog.Error(declaringType, "Failed to set parameter [" + propInfo.Name + "] on object [" + target + "] using value [" + convertedValue + "]", targetInvocationEx.InnerException); + LogLog.Error(declaringType, $"Failed to set parameter [{propInfo.Name}] on object [{target}] using value [{convertedValue}]", targetInvocationEx.InnerException); } } - else if (methInfo != null) + else { // Got a converted result - LogLog.Debug(declaringType, "Setting Collection Property [" + methInfo.Name + "] to " + convertedValue.GetType().Name + " value [" + convertedValue.ToString() + "]"); + LogLog.Debug(declaringType, $"Setting Collection Property [{methInfo.Name}] to {convertedValue.GetType().Name} value [{convertedValue}]"); try { // Pass to the property - methInfo.Invoke(target, BindingFlags.InvokeMethod, null, new object[] { convertedValue }, CultureInfo.InvariantCulture); + methInfo.Invoke(target, BindingFlags.InvokeMethod, null, new[] { convertedValue }, CultureInfo.InvariantCulture); } catch (TargetInvocationException targetInvocationEx) { - LogLog.Error(declaringType, "Failed to set parameter [" + name + "] on object [" + target + "] using value [" + convertedValue + "]", targetInvocationEx.InnerException); + LogLog.Error(declaringType, $"Failed to set parameter [{name}] on object [{target}] using value [{convertedValue}]", targetInvocationEx.InnerException); } } } else { - LogLog.Warn(declaringType, "Unable to set property [" + name + "] on object [" + target + "] using value [" + propertyValue + "] (with acceptable conversion types)"); + LogLog.Warn(declaringType, $"Unable to set property [{name}] on object [{target}] using value [{propertyValue}] (with acceptable conversion types)"); } } else { - object createdObject = null; + object? createdObject; if (propertyType == typeof(string) && !HasAttributesOrElements(element)) { @@ -751,12 +738,12 @@ protected void SetParameter(XmlElement element, object target) // This is necessary because while the String is a class it does not have // a default constructor that creates an empty string, which is the behavior // we are trying to simulate and would be expected from CreateObjectFromXml - createdObject = ""; + createdObject = string.Empty; } else { // No value specified - Type defaultObjectType = null; + Type? defaultObjectType = null; if (IsTypeConstructible(propertyType)) { defaultObjectType = propertyType; @@ -765,16 +752,16 @@ protected void SetParameter(XmlElement element, object target) createdObject = CreateObjectFromXml(element, defaultObjectType, propertyType); } - if (createdObject == null) + if (createdObject is null) { - LogLog.Error(declaringType, "Failed to create object to set param: " + name); + LogLog.Error(declaringType, $"Failed to create object to set param: {name}"); } else { - if (propInfo != null) + if (propInfo is not null) { // Got a converted result - LogLog.Debug(declaringType, "Setting Property [" + propInfo.Name + "] to object [" + createdObject + "]"); + LogLog.Debug(declaringType, $"Setting Property [{propInfo.Name}] to object [{createdObject}]"); try { @@ -783,22 +770,22 @@ protected void SetParameter(XmlElement element, object target) } catch (TargetInvocationException targetInvocationEx) { - LogLog.Error(declaringType, "Failed to set parameter [" + propInfo.Name + "] on object [" + target + "] using value [" + createdObject + "]", targetInvocationEx.InnerException); + LogLog.Error(declaringType, $"Failed to set parameter [{propInfo.Name}] on object [{target}] using value [{createdObject}]", targetInvocationEx.InnerException); } } - else if (methInfo != null) + else { // Got a converted result - LogLog.Debug(declaringType, "Setting Collection Property [" + methInfo.Name + "] to object [" + createdObject + "]"); + LogLog.Debug(declaringType, $"Setting Collection Property [{methInfo.Name}] to object [{createdObject}]"); try { // Pass to the property - methInfo.Invoke(target, BindingFlags.InvokeMethod, null, new object[] { createdObject }, CultureInfo.InvariantCulture); + methInfo.Invoke(target, BindingFlags.InvokeMethod, null, new[] { createdObject }, CultureInfo.InvariantCulture); } catch (TargetInvocationException targetInvocationEx) { - LogLog.Error(declaringType, "Failed to set parameter [" + methInfo.Name + "] on object [" + target + "] using value [" + createdObject + "]", targetInvocationEx.InnerException); + LogLog.Error(declaringType, $"Failed to set parameter [{methInfo.Name}] on object [{target}] using value [{createdObject}]", targetInvocationEx.InnerException); } } } @@ -832,8 +819,8 @@ private static bool IsTypeConstructible(Type type) { if (type.IsClass && !type.IsAbstract) { - ConstructorInfo defaultConstructor = type.GetConstructor(new Type[0]); - if (defaultConstructor != null && !defaultConstructor.IsAbstract && !defaultConstructor.IsPrivate) + ConstructorInfo defaultConstructor = type.GetConstructor(Type.EmptyTypes); + if (defaultConstructor is not null && !defaultConstructor.IsAbstract && !defaultConstructor.IsPrivate) { return true; } @@ -854,7 +841,7 @@ private static bool IsTypeConstructible(Type type) /// The method must take a single parameter. /// /// - private MethodInfo FindMethodInfo(Type targetType, string name) + private static MethodInfo? FindMethodInfo(Type targetType, string name) { string requiredMethodNameA = name; string requiredMethodNameB = "Add" + name; @@ -873,7 +860,7 @@ private MethodInfo FindMethodInfo(Type targetType, string name) // Found matching method name // Look for version with one arg only - System.Reflection.ParameterInfo[] methParams = methInfo.GetParameters(); + ParameterInfo[] methParams = methInfo.GetParameters(); if (methParams.Length == 1) { return methInfo; @@ -895,17 +882,17 @@ private MethodInfo FindMethodInfo(Type targetType, string name) /// null when the conversion could not be performed. /// /// - protected object ConvertStringTo(Type type, string value) + protected object? ConvertStringTo(Type type, string value) { // Hack to allow use of Level in property if (typeof(Level) == type) { // Property wants a level - Level levelValue = m_hierarchy.LevelMap[value]; + Level? levelValue = m_hierarchy.LevelMap[value]; - if (levelValue == null) + if (levelValue is null) { - LogLog.Error(declaringType, "XmlHierarchyConfigurator: Unknown Level Specified [" + value + "]"); + LogLog.Error(declaringType, $"XmlHierarchyConfigurator: Unknown Level Specified [{value}]"); } return levelValue; @@ -932,24 +919,22 @@ protected object ConvertStringTo(Type type, string value) /// type. /// /// - protected object CreateObjectFromXml(XmlElement element, Type defaultTargetType, Type typeConstraint) + protected object? CreateObjectFromXml(XmlElement element, Type? defaultTargetType, Type? typeConstraint) { - Type objectType = null; + Type? objectType; // Get the object type string objectTypeString = element.GetAttribute(TYPE_ATTR); - if (objectTypeString == null || objectTypeString.Length == 0) + if (objectTypeString.Length == 0) { - if (defaultTargetType == null) + if (defaultTargetType is null) { - LogLog.Error(declaringType, "Object type not specified. Cannot create object of type [" + typeConstraint.FullName + "]. Missing Value or Type."); + LogLog.Error(declaringType, $"Object type not specified. Cannot create object of type [{typeConstraint?.FullName}]. Missing Value or Type."); return null; } - else - { - // Use the default object type - objectType = defaultTargetType; - } + + // Use the default object type + objectType = defaultTargetType; } else { @@ -960,7 +945,7 @@ protected object CreateObjectFromXml(XmlElement element, Type defaultTargetType, } catch (Exception ex) { - LogLog.Error(declaringType, "Failed to find type [" + objectTypeString + "]", ex); + LogLog.Error(declaringType, $"Failed to find type [{objectTypeString}]", ex); return null; } } @@ -968,7 +953,7 @@ protected object CreateObjectFromXml(XmlElement element, Type defaultTargetType, bool requiresConversion = false; // Got the object type. Check that it meets the typeConstraint - if (typeConstraint != null) + if (typeConstraint is not null) { if (!typeConstraint.IsAssignableFrom(objectType)) { @@ -979,21 +964,22 @@ protected object CreateObjectFromXml(XmlElement element, Type defaultTargetType, } else { - LogLog.Error(declaringType, "Object type [" + objectType.FullName + "] is not assignable to type [" + typeConstraint.FullName + "]. There are no acceptable type conversions."); + LogLog.Error(declaringType, $"Object type [{objectType!.FullName}] is not assignable to type [{typeConstraint.FullName}]. There are no acceptable type conversions."); return null; } } } // Create using the default constructor - object createdObject = null; + object? createdObject; try { - createdObject = Activator.CreateInstance(objectType); + createdObject = Activator.CreateInstance(objectType!); } catch (Exception createInstanceEx) { - LogLog.Error(declaringType, "XmlHierarchyConfigurator: Failed to construct object of type [" + objectType.FullName + "] Exception: " + createInstanceEx.ToString()); + LogLog.Error(declaringType, $"XmlHierarchyConfigurator: Failed to construct object of type [{objectType!.FullName}] Exception: {createInstanceEx}"); + return null; } // Set any params on object @@ -1006,8 +992,7 @@ protected object CreateObjectFromXml(XmlElement element, Type defaultTargetType, } // Check if we need to call ActivateOptions - IOptionHandler optionHandler = createdObject as IOptionHandler; - if (optionHandler != null) + if (createdObject is IOptionHandler optionHandler) { optionHandler.ActivateOptions(); } @@ -1019,16 +1004,12 @@ protected object CreateObjectFromXml(XmlElement element, Type defaultTargetType, // Convert the object type return OptionConverter.ConvertTypeTo(createdObject, typeConstraint); } - else - { - // The object is of the correct type - return createdObject; - } - } - #endregion Protected Instance Methods + // The object is of the correct type + return createdObject; + } - private bool HasCaseInsensitiveEnvironment + private static bool HasCaseInsensitiveEnvironment { get { @@ -1037,12 +1018,8 @@ private bool HasCaseInsensitiveEnvironment } } - private IDictionary CreateCaseInsensitiveWrapper(IDictionary dict) + private static IDictionary CreateCaseInsensitiveWrapper(IDictionary dict) { - if (dict == null) - { - return dict; - } Hashtable hash = SystemInfo.CreateCaseInsensitiveHashtable(); foreach (DictionaryEntry entry in dict) { @@ -1051,8 +1028,6 @@ private IDictionary CreateCaseInsensitiveWrapper(IDictionary dict) return hash; } - #region Private Constants - // String constants used while parsing the XML data private const string CONFIGURATION_TAG = "log4net"; private const string RENDERER_TAG = "renderer"; @@ -1084,24 +1059,16 @@ private IDictionary CreateCaseInsensitiveWrapper(IDictionary dict) // flag used on the level element private const string INHERITED = "inherited"; - #endregion Private Constants - - #region Private Instance Fields - /// /// key: appenderName, value: appender. /// - private Hashtable m_appenderBag; + private readonly Dictionary m_appenderBag = new(StringComparer.Ordinal); /// /// The Hierarchy being configured. /// private readonly Hierarchy m_hierarchy; - #endregion Private Instance Fields - - #region Private Static Fields - /// /// The fully qualified type of the XmlHierarchyConfigurator class. /// @@ -1110,7 +1077,5 @@ private IDictionary CreateCaseInsensitiveWrapper(IDictionary dict) /// log message. /// private static readonly Type declaringType = typeof(XmlHierarchyConfigurator); - - #endregion Private Static Fields } } diff --git a/src/log4net/Repository/ILoggerRepository.cs b/src/log4net/Repository/ILoggerRepository.cs index ac6638a3..ad0b0d9e 100644 --- a/src/log4net/Repository/ILoggerRepository.cs +++ b/src/log4net/Repository/ILoggerRepository.cs @@ -174,17 +174,17 @@ public interface ILoggerRepository /// /// Event to notify that the repository has been shut down. /// - event LoggerRepositoryShutdownEventHandler ShutdownEvent; + event LoggerRepositoryShutdownEventHandler? ShutdownEvent; /// /// Event to notify that the repository has had its configuration reset to default. /// - event LoggerRepositoryConfigurationResetEventHandler ConfigurationReset; + event LoggerRepositoryConfigurationResetEventHandler? ConfigurationReset; /// /// Event to notify that the repository's configuration has changed. /// - event LoggerRepositoryConfigurationChangedEventHandler ConfigurationChanged; + event LoggerRepositoryConfigurationChangedEventHandler? ConfigurationChanged; /// /// Repository specific properties. diff --git a/src/log4net/Repository/LoggerRepositorySkeleton.cs b/src/log4net/Repository/LoggerRepositorySkeleton.cs index 11afa005..ed045593 100644 --- a/src/log4net/Repository/LoggerRepositorySkeleton.cs +++ b/src/log4net/Repository/LoggerRepositorySkeleton.cs @@ -24,6 +24,7 @@ using log4net.Util; using log4net.Plugin; using System.Threading; +using log4net.Appender; namespace log4net.Repository { @@ -41,25 +42,12 @@ namespace log4net.Repository /// /// Nicko Cadell /// Gert Driesen - public abstract class LoggerRepositorySkeleton : ILoggerRepository, Appender.IFlushable + public abstract class LoggerRepositorySkeleton : ILoggerRepository, IFlushable { - #region Member Variables - - private string m_name; - private RendererMap m_rendererMap; - private PluginMap m_pluginMap; - private LevelMap m_levelMap; - private Level m_threshold; - private bool m_configured; - private ICollection m_configurationMessages; - private event LoggerRepositoryShutdownEventHandler m_shutdownEvent; - private event LoggerRepositoryConfigurationResetEventHandler m_configurationResetEvent; - private event LoggerRepositoryConfigurationChangedEventHandler m_configurationChangedEvent; - private PropertiesDictionary m_properties; - - #endregion - - #region Constructors + private readonly RendererMap m_rendererMap = new(); + private readonly LevelMap m_levelMap = new(); + private Level m_threshold = Level.All; // Don't disable any levels by default. + private ICollection m_configurationMessages = EmptyCollection.Instance; /// /// Default Constructor @@ -84,23 +72,11 @@ protected LoggerRepositorySkeleton() : this(new PropertiesDictionary()) /// protected LoggerRepositorySkeleton(PropertiesDictionary properties) { - m_properties = properties; - m_rendererMap = new RendererMap(); - m_pluginMap = new PluginMap(this); - m_levelMap = new LevelMap(); - m_configurationMessages = EmptyCollection.Instance; - m_configured = false; - + Properties = properties; + PluginMap = new PluginMap(this); AddBuiltinLevels(); - - // Don't disable any levels by default. - m_threshold = Level.All; } - #endregion - - #region Implementation of ILoggerRepository - /// /// The name of the repository /// @@ -114,11 +90,7 @@ protected LoggerRepositorySkeleton(PropertiesDictionary properties) /// stored by the . /// /// - public virtual string Name - { - get { return m_name; } - set { m_name = value; } - } + public virtual string? Name { get; set; } /// /// The threshold for all events in this repository @@ -133,10 +105,10 @@ public virtual string Name /// public virtual Level Threshold { - get { return m_threshold; } + get => m_threshold; set { - if (value != null) + if (value is not null) { m_threshold = value; } @@ -164,10 +136,7 @@ public virtual Level Threshold /// objects. /// /// - public virtual RendererMap RendererMap - { - get { return m_rendererMap; } - } + public virtual RendererMap RendererMap => m_rendererMap; /// /// The plugin map for this repository. @@ -181,10 +150,7 @@ public virtual RendererMap RendererMap /// that have been attached to this repository. /// /// - public virtual PluginMap PluginMap - { - get { return m_pluginMap; } - } + public virtual PluginMap PluginMap { get; } /// /// Get the level map for the Repository. @@ -199,10 +165,7 @@ public virtual PluginMap PluginMap /// this repository. /// /// - public virtual LevelMap LevelMap - { - get { return m_levelMap; } - } + public virtual LevelMap LevelMap => m_levelMap; /// /// Test if logger exists @@ -328,20 +291,16 @@ public virtual void ResetConfiguration() /// Flag indicates if this repository has been configured. /// /// - public virtual bool Configured - { - get { return m_configured; } - set { m_configured = value; } - } + public virtual bool Configured { get; set; } /// - /// Contains a list of internal messages captures during the + /// Contains a list of internal messages captured during the /// last configuration. /// public virtual ICollection ConfigurationMessages { - get { return m_configurationMessages; } - set { m_configurationMessages = value; } + get => m_configurationMessages; + set => m_configurationMessages = value; } /// @@ -355,11 +314,7 @@ public virtual ICollection ConfigurationMessages /// Event raised when the repository has been shutdown. /// /// - public event LoggerRepositoryShutdownEventHandler ShutdownEvent - { - add { m_shutdownEvent += value; } - remove { m_shutdownEvent -= value; } - } + public event LoggerRepositoryShutdownEventHandler? ShutdownEvent; /// /// Event to notify that the repository has had its configuration reset. @@ -373,11 +328,7 @@ public event LoggerRepositoryShutdownEventHandler ShutdownEvent /// reset to default. /// /// - public event LoggerRepositoryConfigurationResetEventHandler ConfigurationReset - { - add { m_configurationResetEvent += value; } - remove { m_configurationResetEvent -= value; } - } + public event LoggerRepositoryConfigurationResetEventHandler? ConfigurationReset; /// /// Event to notify that the repository has had its configuration changed. @@ -390,11 +341,7 @@ public event LoggerRepositoryConfigurationResetEventHandler ConfigurationReset /// Event raised when the repository's configuration has been changed. /// /// - public event LoggerRepositoryConfigurationChangedEventHandler ConfigurationChanged - { - add { m_configurationChangedEvent += value; } - remove { m_configurationChangedEvent -= value; } - } + public event LoggerRepositoryConfigurationChangedEventHandler? ConfigurationChanged; /// /// Repository specific properties @@ -405,10 +352,7 @@ public event LoggerRepositoryConfigurationChangedEventHandler ConfigurationChang /// /// These properties can be specified on a repository specific basis /// - public PropertiesDictionary Properties - { - get { return m_properties; } - } + public PropertiesDictionary Properties { get; } /// /// Returns all the Appenders that are configured as an Array. @@ -419,11 +363,7 @@ public PropertiesDictionary Properties /// Returns all the Appenders that are configured as an Array. /// /// - public abstract log4net.Appender.IAppender[] GetAppenders(); - - #endregion - - #region Private Static Fields + public abstract IAppender[] GetAppenders(); /// /// The fully qualified type of the LoggerRepositorySkeleton class. @@ -434,8 +374,6 @@ public PropertiesDictionary Properties /// private static readonly Type declaringType = typeof(LoggerRepositorySkeleton); - #endregion Private Static Fields - private void AddBuiltinLevels() { // Add the predefined levels to the map @@ -481,11 +419,11 @@ public virtual void AddRenderer(Type typeToRender, IObjectRenderer rendererInsta { if (typeToRender == null) { - throw new ArgumentNullException("typeToRender"); + throw new ArgumentNullException(nameof(typeToRender)); } if (rendererInstance == null) { - throw new ArgumentNullException("rendererInstance"); + throw new ArgumentNullException(nameof(rendererInstance)); } m_rendererMap.Put(typeToRender, rendererInstance); @@ -500,18 +438,10 @@ public virtual void AddRenderer(Type typeToRender, IObjectRenderer rendererInsta /// Notify any listeners that this repository is shutting down. /// /// - protected virtual void OnShutdown(EventArgs e) + protected virtual void OnShutdown(EventArgs? e) { - if (e == null) - { - e = EventArgs.Empty; - } - - LoggerRepositoryShutdownEventHandler handler = m_shutdownEvent; - if (handler != null) - { - handler(this, e); - } + e ??= EventArgs.Empty; + ShutdownEvent?.Invoke(this, e); } /// @@ -523,18 +453,10 @@ protected virtual void OnShutdown(EventArgs e) /// Notify any listeners that this repository's configuration has been reset. /// /// - protected virtual void OnConfigurationReset(EventArgs e) + protected virtual void OnConfigurationReset(EventArgs? e) { - if (e == null) - { - e = EventArgs.Empty; - } - - LoggerRepositoryConfigurationResetEventHandler handler = m_configurationResetEvent; - if (handler != null) - { - handler(this, e); - } + e ??= EventArgs.Empty; + ConfigurationReset?.Invoke(this, e); } /// @@ -546,18 +468,10 @@ protected virtual void OnConfigurationReset(EventArgs e) /// Notify any listeners that this repository's configuration has changed. /// /// - protected virtual void OnConfigurationChanged(EventArgs e) + protected virtual void OnConfigurationChanged(EventArgs? e) { - if (e == null) - { - e = EventArgs.Empty; - } - - LoggerRepositoryConfigurationChangedEventHandler handler = m_configurationChangedEvent; - if (handler != null) - { - handler(this, e); - } + e ??= EventArgs.Empty; + ConfigurationChanged?.Invoke(this, e); } /// @@ -589,12 +503,12 @@ private static int GetWaitTime(DateTime startTimeUtc, int millisecondsTimeout) /// /// Flushes all configured Appenders that implement . /// - /// The maximum time in milliseconds to wait for logging events from asycnhronous appenders to be flushed, + /// The maximum time in milliseconds to wait for logging events from asynchronous appenders to be flushed, /// or to wait indefinitely. /// True if all logging events were flushed successfully, else false. public bool Flush(int millisecondsTimeout) { - if (millisecondsTimeout < -1) throw new ArgumentOutOfRangeException("millisecondsTimeout", "Timeout must be -1 (Timeout.Infinite) or non-negative"); + if (millisecondsTimeout < -1) throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout), "Timeout must be -1 (Timeout.Infinite) or non-negative"); // Assume success until one of the appenders fails bool result = true; @@ -603,11 +517,14 @@ public bool Flush(int millisecondsTimeout) DateTime startTimeUtc = DateTime.UtcNow; // Do buffering appenders first. These may be forwarding to other appenders - foreach (log4net.Appender.IAppender appender in GetAppenders()) + foreach (IAppender appender in GetAppenders()) { - log4net.Appender.IFlushable flushable = appender as log4net.Appender.IFlushable; - if (flushable == null) continue; - if (appender is Appender.BufferingAppenderSkeleton) + if (appender is not IFlushable flushable) + { + continue; + } + + if (appender is BufferingAppenderSkeleton) { int timeout = GetWaitTime(startTimeUtc, millisecondsTimeout); if (!flushable.Flush(timeout)) result = false; @@ -615,11 +532,14 @@ public bool Flush(int millisecondsTimeout) } // Do non-buffering appenders. - foreach (log4net.Appender.IAppender appender in GetAppenders()) + foreach (IAppender appender in GetAppenders()) { - log4net.Appender.IFlushable flushable = appender as log4net.Appender.IFlushable; - if (flushable == null) continue; - if (!(appender is Appender.BufferingAppenderSkeleton)) + if (appender is not IFlushable flushable) + { + continue; + } + + if (appender is not BufferingAppenderSkeleton) { int timeout = GetWaitTime(startTimeUtc, millisecondsTimeout); if (!flushable.Flush(timeout)) result = false; diff --git a/src/log4net/ThreadContext.cs b/src/log4net/ThreadContext.cs index e84dba53..6d17de14 100644 --- a/src/log4net/ThreadContext.cs +++ b/src/log4net/ThreadContext.cs @@ -17,9 +17,6 @@ // #endregion -using System; -using System.Collections; - using log4net.Util; namespace log4net @@ -67,26 +64,8 @@ namespace log4net /// /// /// Nicko Cadell - public sealed class ThreadContext + public static class ThreadContext { - #region Private Instance Constructors - - /// - /// Private Constructor. - /// - /// - /// - /// Uses a private access modifier to prevent instantiation of this class. - /// - /// - private ThreadContext() - { - } - - #endregion Private Instance Constructors - - #region Public Static Properties - /// /// The thread properties map /// @@ -99,10 +78,7 @@ private ThreadContext() /// properties with the same name. /// /// - public static ThreadContextProperties Properties - { - get { return s_properties; } - } + public static ThreadContextProperties Properties { get; } = new(); /// /// The thread stacks @@ -115,25 +91,6 @@ public static ThreadContextProperties Properties /// The thread local stacks. /// /// - public static ThreadContextStacks Stacks - { - get { return s_stacks; } - } - - #endregion Public Static Properties - - #region Private Static Fields - - /// - /// The thread context properties instance - /// - private static readonly ThreadContextProperties s_properties = new ThreadContextProperties(); - - /// - /// The thread context stacks instance - /// - private static readonly ThreadContextStacks s_stacks = new ThreadContextStacks(s_properties); - - #endregion Private Static Fields + public static ThreadContextStacks Stacks { get; } = new(Properties); } } diff --git a/src/log4net/Util/CompositeProperties.cs b/src/log4net/Util/CompositeProperties.cs index 66ac7b7e..5e1350f8 100644 --- a/src/log4net/Util/CompositeProperties.cs +++ b/src/log4net/Util/CompositeProperties.cs @@ -17,8 +17,7 @@ // #endregion -using System; -using System.Collections; +using System.Collections.Generic; namespace log4net.Util { @@ -34,14 +33,8 @@ namespace log4net.Util /// Nicko Cadell public sealed class CompositeProperties { - #region Private Instance Fields - - private PropertiesDictionary m_flattened = null; - private ArrayList m_nestedProperties = new ArrayList(); - - #endregion Private Instance Fields - - #region Public Instance Constructors + private PropertiesDictionary? m_flattened; + private readonly List m_nestedProperties = new(); /// /// Constructor @@ -55,10 +48,6 @@ internal CompositeProperties() { } - #endregion Public Instance Constructors - - #region Public Instance Properties - /// /// Gets the value of a property /// @@ -78,12 +67,12 @@ internal CompositeProperties() /// null is returned. /// /// - public object this[string key] + public object? this[string key] { get { // Look in the flattened properties first - if (m_flattened != null) + if (m_flattened is not null) { return m_flattened[key]; } @@ -91,19 +80,15 @@ public object this[string key] // Look for the key in all the nested properties foreach (ReadOnlyPropertiesDictionary cur in m_nestedProperties) { - if (cur.Contains(key)) + if (cur.TryGetValue(key, out object? val)) { - return cur[key]; + return val; } } return null; } } - #endregion Public Instance Properties - - #region Public Instance Methods - /// /// Add a Properties Dictionary to this composite collection /// @@ -132,24 +117,22 @@ public void Add(ReadOnlyPropertiesDictionary properties) /// public PropertiesDictionary Flatten() { - if (m_flattened == null) + if (m_flattened is null) { m_flattened = new PropertiesDictionary(); for (int i = m_nestedProperties.Count; --i >= 0;) { - ReadOnlyPropertiesDictionary cur = (ReadOnlyPropertiesDictionary)m_nestedProperties[i]; + ReadOnlyPropertiesDictionary cur = m_nestedProperties[i]; - foreach (DictionaryEntry entry in cur) + foreach (KeyValuePair entry in cur) { - m_flattened[(string)entry.Key] = entry.Value; + m_flattened[entry.Key] = entry.Value; } } } return m_flattened; } - - #endregion Public Instance Methods } } diff --git a/src/log4net/Util/ContextPropertiesBase.cs b/src/log4net/Util/ContextPropertiesBase.cs index 47274615..b75b0d00 100644 --- a/src/log4net/Util/ContextPropertiesBase.cs +++ b/src/log4net/Util/ContextPropertiesBase.cs @@ -17,34 +17,19 @@ // #endregion -using System; -using System.Collections; +#nullable enable namespace log4net.Util { /// /// Base class for Context Properties implementations /// - /// - /// - /// This class defines a basic property get set accessor - /// - /// /// Nicko Cadell public abstract class ContextPropertiesBase { /// - /// Gets or sets the value of a property + /// Gets or sets the value of a property. /// - /// - /// The value for the property with the specified key - /// - /// - /// - /// Gets or sets the value of a property - /// - /// - public abstract object this[string key] { get; set; } + public abstract object? this[string key] { get; set; } } } - diff --git a/src/log4net/Util/GlobalContextProperties.cs b/src/log4net/Util/GlobalContextProperties.cs index d516804b..9d5c1cec 100644 --- a/src/log4net/Util/GlobalContextProperties.cs +++ b/src/log4net/Util/GlobalContextProperties.cs @@ -17,9 +17,6 @@ // #endregion -using System; -using System.Collections; - namespace log4net.Util { /// @@ -38,8 +35,6 @@ namespace log4net.Util /// Nicko Cadell public sealed class GlobalContextProperties : ContextPropertiesBase { - #region Private Instance Fields - /// /// The read only copy of the properties. /// @@ -49,16 +44,12 @@ public sealed class GlobalContextProperties : ContextPropertiesBase /// reordering reads and writes of this thread performed on different threads. /// /// - private volatile ReadOnlyPropertiesDictionary m_readOnlyProperties = new ReadOnlyPropertiesDictionary(); + private volatile ReadOnlyPropertiesDictionary m_readOnlyProperties = new(); /// /// Lock object used to synchronize updates within this instance /// - private readonly object m_syncRoot = new object(); - - #endregion Private Instance Fields - - #region Public Instance Constructors + private readonly object m_syncRoot = new(); /// /// Constructor @@ -72,10 +63,6 @@ internal GlobalContextProperties() { } - #endregion Public Instance Constructors - - #region Public Instance Properties - /// /// Gets or sets the value of a property /// @@ -89,29 +76,22 @@ internal GlobalContextProperties() /// the properties is created. /// /// - public override object this[string key] + public override object? this[string key] { - get - { - return m_readOnlyProperties[key]; - } + get => m_readOnlyProperties[key]; set { lock (m_syncRoot) { - PropertiesDictionary mutableProps = new PropertiesDictionary(m_readOnlyProperties); - - mutableProps[key] = value; - + var mutableProps = new PropertiesDictionary(m_readOnlyProperties) + { + [key] = value + }; m_readOnlyProperties = new ReadOnlyPropertiesDictionary(mutableProps); } } } - #endregion Public Instance Properties - - #region Public Instance Methods - /// /// Remove a property from the global context /// @@ -128,10 +108,8 @@ public void Remove(string key) { if (m_readOnlyProperties.Contains(key)) { - PropertiesDictionary mutableProps = new PropertiesDictionary(m_readOnlyProperties); - + var mutableProps = new PropertiesDictionary(m_readOnlyProperties); mutableProps.Remove(key); - m_readOnlyProperties = new ReadOnlyPropertiesDictionary(mutableProps); } } @@ -148,10 +126,6 @@ public void Clear() } } - #endregion Public Instance Methods - - #region Internal Instance Methods - /// /// Get a readonly immutable copy of the properties /// @@ -166,8 +140,5 @@ internal ReadOnlyPropertiesDictionary GetReadOnlyProperties() { return m_readOnlyProperties; } - - #endregion Internal Instance Methods } } - diff --git a/src/log4net/Util/LogLog.cs b/src/log4net/Util/LogLog.cs index 6a1d79ef..4ce84aa5 100644 --- a/src/log4net/Util/LogLog.cs +++ b/src/log4net/Util/LogLog.cs @@ -19,6 +19,7 @@ using System; using System.Collections; +using System.Collections.Generic; using System.Diagnostics; namespace log4net.Util @@ -28,7 +29,7 @@ namespace log4net.Util /// /// /// - public delegate void LogReceivedEventHandler(object source, LogReceivedEventArgs e); + public delegate void LogReceivedEventHandler(object? source, LogReceivedEventArgs e); /// /// Outputs log statements from within the log4net assembly. @@ -52,37 +53,22 @@ public sealed class LogLog /// /// The event raised when an internal message has been received. /// - public static event LogReceivedEventHandler LogReceived; - - private readonly Type source; - private readonly DateTime timeStampUtc; - private readonly string prefix; - private readonly string message; - private readonly Exception exception; + public static event LogReceivedEventHandler? LogReceived; /// /// The Type that generated the internal message. /// - public Type Source - { - get { return source; } - } + public Type Source { get; } /// /// The DateTime stamp of when the internal message was received. /// - public DateTime TimeStamp - { - get { return timeStampUtc.ToLocalTime(); } - } + public DateTime TimeStamp => TimeStampUtc.ToLocalTime(); /// /// The UTC DateTime stamp of when the internal message was received. /// - public DateTime TimeStampUtc - { - get { return timeStampUtc; } - } + public DateTime TimeStampUtc { get; } /// /// A string indicating the severity of the internal message. @@ -92,18 +78,12 @@ public DateTime TimeStampUtc /// "log4net:ERROR ", /// "log4net:WARN " /// - public string Prefix - { - get { return prefix; } - } + public string Prefix { get; } /// /// The internal log message. /// - public string Message - { - get { return message; } - } + public string Message { get; } /// /// The Exception related to the message. @@ -111,10 +91,7 @@ public string Message /// /// Optional. Will be null if no Exception was passed. /// - public Exception Exception - { - get { return exception; } - } + public Exception? Exception { get; } /// /// Formats Prefix, Source, and Message in the same format as the value @@ -126,29 +103,19 @@ public override string ToString() return Prefix + Source.Name + ": " + Message; } - #region Private Instance Constructors - /// /// Initializes a new instance of the class. /// - /// - /// - /// - /// - public LogLog(Type source, string prefix, string message, Exception exception) + public LogLog(Type source, string prefix, string message, Exception? exception) { - timeStampUtc = DateTime.UtcNow; + TimeStampUtc = DateTime.UtcNow; - this.source = source; - this.prefix = prefix; - this.message = message; - this.exception = exception; + Source = source; + Prefix = prefix; + Message = message; + Exception = exception; } - #endregion Private Instance Constructors - - #region Static Constructor - /// /// Static constructor that initializes logging by reading /// settings from the application configuration file. @@ -184,10 +151,6 @@ static LogLog() } } - #endregion Static Constructor - - #region Public Static Properties - /// /// Gets or sets a value indicating whether log4net internal logging /// is enabled or disabled. @@ -224,11 +187,7 @@ static LogLog() /// /// /// - public static bool InternalDebugging - { - get { return s_debugEnabled; } - set { s_debugEnabled = value; } - } + public static bool InternalDebugging { get; set; } /// /// Gets or sets a value indicating whether log4net should generate no output @@ -264,24 +223,12 @@ public static bool InternalDebugging /// /// /// - public static bool QuietMode - { - get { return s_quietMode; } - set { s_quietMode = value; } - } + public static bool QuietMode { get; set; } /// /// /// - public static bool EmitInternalMessages - { - get { return s_emitInternalMessages; } - set { s_emitInternalMessages = value; } - } - - #endregion Public Static Properties - - #region Public Static Methods + public static bool EmitInternalMessages { get; set; } = true; /// /// Raises the LogReceived event when an internal messages is received. @@ -290,12 +237,9 @@ public static bool EmitInternalMessages /// /// /// - public static void OnLogReceived(Type source, string prefix, string message, Exception exception) + public static void OnLogReceived(Type source, string prefix, string message, Exception? exception) { - if (LogReceived != null) - { - LogReceived(null, new LogReceivedEventArgs(new LogLog(source, prefix, message, exception))); - } + LogReceived?.Invoke(null, new LogReceivedEventArgs(new LogLog(source, prefix, message, exception))); } /// @@ -309,10 +253,7 @@ public static void OnLogReceived(Type source, string prefix, string message, Exc /// Test if LogLog.Debug is enabled for output. /// /// - public static bool IsDebugEnabled - { - get { return s_debugEnabled && !s_quietMode; } - } + public static bool IsDebugEnabled => InternalDebugging && !QuietMode; /// /// Writes log4net internal debug messages to the @@ -352,7 +293,7 @@ public static void Debug(Type source, string message) /// the string "log4net: ". /// /// - public static void Debug(Type source, string message, Exception exception) + public static void Debug(Type source, string message, Exception? exception) { if (IsDebugEnabled) { @@ -375,15 +316,7 @@ public static void Debug(Type source, string message, Exception exception) /// /// true if Warn is enabled /// - /// - /// - /// Test if LogLog.Warn is enabled for output. - /// - /// - public static bool IsWarnEnabled - { - get { return !s_quietMode; } - } + public static bool IsWarnEnabled => !QuietMode; /// /// Writes log4net internal warning messages to the @@ -423,7 +356,7 @@ public static void Warn(Type source, string message) /// the string "log4net:WARN ". /// /// - public static void Warn(Type source, string message, Exception exception) + public static void Warn(Type source, string message, Exception? exception) { if (IsWarnEnabled) { @@ -451,10 +384,7 @@ public static void Warn(Type source, string message, Exception exception) /// Test if LogLog.Error is enabled for output. /// /// - public static bool IsErrorEnabled - { - get { return !s_quietMode; } - } + public static bool IsErrorEnabled => !QuietMode; /// /// Writes log4net internal error messages to the @@ -494,7 +424,7 @@ public static void Error(Type source, string message) /// the string "log4net:ERROR ". /// /// - public static void Error(Type source, string message, Exception exception) + public static void Error(Type source, string message, Exception? exception) { if (IsErrorEnabled) { @@ -511,8 +441,6 @@ public static void Error(Type source, string message, Exception exception) } } - #endregion Public Static Methods - /// /// Writes output to the standard output stream. /// @@ -520,8 +448,6 @@ public static void Error(Type source, string message, Exception exception) /// /// /// Writes to both Console.Out and System.Diagnostics.Trace. - /// Note that the System.Diagnostics.Trace is not supported - /// on the Compact Framework. /// /// /// If the AppDomain is not configured with a config file then @@ -571,67 +497,45 @@ private static void EmitErrorLine(string message) } } - #region Private Static Fields - - /// - /// Default debug level - /// - private static bool s_debugEnabled = false; - - /// - /// In quietMode not even errors generate any output. - /// - private static bool s_quietMode = false; - - private static bool s_emitInternalMessages = true; - private const string PREFIX = "log4net: "; private const string ERR_PREFIX = "log4net:ERROR "; private const string WARN_PREFIX = "log4net:WARN "; - #endregion Private Static Fields - /// /// Subscribes to the LogLog.LogReceived event and stores messages /// to the supplied IList instance. /// public class LogReceivedAdapter : IDisposable { - private readonly IList items; - private readonly LogReceivedEventHandler handler; + private readonly LogReceivedEventHandler m_handler; /// /// /// /// - public LogReceivedAdapter(IList items) + public LogReceivedAdapter(List items) { - this.items = items; - - handler = new LogReceivedEventHandler(LogLog_LogReceived); - - LogReceived += handler; + Items = items; + m_handler = LogLog_LogReceived; + LogReceived += m_handler; } void LogLog_LogReceived(object source, LogReceivedEventArgs e) { - items.Add(e.LogLog); + Items.Add(e.LogLog); } /// /// /// - public IList Items - { - get { return items; } - } + public List Items { get; } /// /// /// public void Dispose() { - LogReceived -= handler; + LogReceived -= m_handler; } } } @@ -641,23 +545,18 @@ public void Dispose() /// public class LogReceivedEventArgs : EventArgs { - private readonly LogLog loglog; - /// /// /// /// public LogReceivedEventArgs(LogLog loglog) { - this.loglog = loglog; + this.LogLog = loglog; } /// /// /// - public LogLog LogLog - { - get { return loglog; } - } + public LogLog LogLog { get; } } } diff --git a/src/log4net/Util/LogicalThreadContextProperties.cs b/src/log4net/Util/LogicalThreadContextProperties.cs index 28020c5f..f42a6d20 100644 --- a/src/log4net/Util/LogicalThreadContextProperties.cs +++ b/src/log4net/Util/LogicalThreadContextProperties.cs @@ -26,6 +26,8 @@ using CallContext = System.Threading.AsyncLocal; #endif +#nullable enable + namespace log4net.Util { /// @@ -64,9 +66,7 @@ public sealed class LogicalThreadContextProperties : ContextPropertiesBase /// /// Flag used to disable this context if we don't have permission to access the CallContext. /// - private bool m_disabled = false; - - #region Public Instance Constructors + private bool m_disabled; /// /// Constructor @@ -80,49 +80,27 @@ internal LogicalThreadContextProperties() { } - #endregion Public Instance Constructors - - #region Public Instance Properties - - /// - /// Gets or sets the value of a property - /// - /// - /// The value for the property with the specified key - /// - /// - /// - /// Get or set the property value for the specified. - /// - /// - public override object this[string key] + /// + public override object? this[string key] { get { // Don't create the dictionary if it does not already exist - PropertiesDictionary dictionary = GetProperties(false); - if (dictionary != null) - { - return dictionary[key]; - } - return null; + PropertiesDictionary? dictionary = GetProperties(false); + return dictionary?[key]; } set { // Force the dictionary to be created - PropertiesDictionary props = GetProperties(true); + PropertiesDictionary props = GetProperties(true)!; // Reason for cloning the dictionary below: object instances set on the CallContext // need to be immutable to correctly flow through async/await - PropertiesDictionary immutableProps = new PropertiesDictionary(props); + var immutableProps = new PropertiesDictionary(props); immutableProps[key] = value; SetLogicalProperties(immutableProps); } } - #endregion Public Instance Properties - - #region Public Instance Methods - /// /// Remove a property /// @@ -134,7 +112,7 @@ public override object this[string key] /// public void Remove(string key) { - PropertiesDictionary dictionary = GetProperties(false); + PropertiesDictionary? dictionary = GetProperties(false); if (dictionary != null) { PropertiesDictionary immutableProps = new PropertiesDictionary(dictionary); @@ -153,22 +131,17 @@ public void Remove(string key) /// public void Clear() { - PropertiesDictionary dictionary = GetProperties(false); - if (dictionary != null) + PropertiesDictionary? dictionary = GetProperties(false); + if (dictionary is not null) { - PropertiesDictionary immutableProps = new PropertiesDictionary(); - SetLogicalProperties(immutableProps); + SetLogicalProperties(new PropertiesDictionary()); } } - #endregion Public Instance Methods - - #region Internal Instance Methods - /// /// Get the PropertiesDictionary stored in the LocalDataStoreSlot for this thread. /// - /// create the dictionary if it does not exist, otherwise return null if is does not exist + /// create the dictionary if it does not exist, otherwise return null if it does not exist /// the properties for this thread /// /// @@ -177,13 +150,13 @@ public void Clear() /// caller must clone the collection before doings so. /// /// - internal PropertiesDictionary GetProperties(bool create) + internal PropertiesDictionary? GetProperties(bool create) { if (!m_disabled) { try { - PropertiesDictionary properties = GetLogicalProperties(); + PropertiesDictionary? properties = GetLogicalProperties(); if (properties == null && create) { properties = new PropertiesDictionary(); @@ -208,20 +181,16 @@ internal PropertiesDictionary GetProperties(bool create) return null; } - #endregion Internal Instance Methods - - #region Private Static Methods - /// /// Gets the call context get data. /// - /// The peroperties dictionary stored in the call context + /// The properties dictionary stored in the call context /// /// The method GetData security link demand, therefore we must - /// put the method call in a seperate method that we can wrap in an exception handler. + /// put the method call in a separate method that we can wrap in an exception handler. /// - [System.Security.SecuritySafeCritical] - private static PropertiesDictionary GetLogicalProperties() + [SecuritySafeCritical] + private static PropertiesDictionary? GetLogicalProperties() { #if NETSTANDARD2_0_OR_GREATER return AsyncLocalDictionary.Value; @@ -236,9 +205,9 @@ private static PropertiesDictionary GetLogicalProperties() /// The properties. /// /// The method SetData has a security link demand, therefore we must - /// put the method call in a seperate method that we can wrap in an exception handler. + /// put the method call in a separate method that we can wrap in an exception handler. /// - [System.Security.SecuritySafeCritical] + [SecuritySafeCritical] private static void SetLogicalProperties(PropertiesDictionary properties) { #if NETSTANDARD2_0_OR_GREATER @@ -248,10 +217,6 @@ private static void SetLogicalProperties(PropertiesDictionary properties) #endif } - #endregion - - #region Private Static Fields - /// /// The fully qualified type of the LogicalThreadContextProperties class. /// @@ -260,7 +225,5 @@ private static void SetLogicalProperties(PropertiesDictionary properties) /// log message. /// private static readonly Type declaringType = typeof(LogicalThreadContextProperties); - - #endregion Private Static Fields } } \ No newline at end of file diff --git a/src/log4net/Util/LogicalThreadContextStack.cs b/src/log4net/Util/LogicalThreadContextStack.cs index 6a922488..fd407e37 100644 --- a/src/log4net/Util/LogicalThreadContextStack.cs +++ b/src/log4net/Util/LogicalThreadContextStack.cs @@ -18,13 +18,13 @@ #endregion using System; -using System.Collections; - +using System.Collections.Generic; using log4net.Core; +#nullable enable + namespace log4net.Util { - /// /// Delegate type used for LogicalThreadContextStack's callbacks. /// @@ -33,36 +33,25 @@ namespace log4net.Util /// /// Implementation of Stack for the /// - /// - /// - /// Implementation of Stack for the - /// - /// /// Nicko Cadell public sealed class LogicalThreadContextStack : IFixingRequired { - #region Private Instance Fields - /// /// The stack store. /// - private Stack m_stack = new Stack(); + private Stack m_stack = new(); /// /// The name of this within the /// . /// - private string m_propertyKey; + private readonly string m_propertyKey; /// /// The callback used to let the register a /// new instance of a . /// - private TwoArgAction m_registerNew; - - #endregion Private Instance Fields - - #region Public Instance Constructors + private readonly TwoArgAction m_registerNew; /// /// Internal constructor @@ -78,16 +67,9 @@ internal LogicalThreadContextStack(string propertyKey, TwoArgAction - /// The number of messages in the stack + /// Gets the number of messages in the stack. /// - /// - /// The current number of messages in the stack - /// /// /// /// The current number of messages in the stack. That is @@ -95,14 +77,7 @@ internal LogicalThreadContextStack(string propertyKey, TwoArgAction has been called. /// /// - public int Count - { - get { return m_stack.Count; } - } - - #endregion // Public Properties - - #region Public Methods + public int Count => m_stack.Count; /// /// Clears all the contextual information held in this stack. @@ -135,17 +110,16 @@ public void Clear() /// empty string (not ) is returned. /// /// - public string Pop() + public string? Pop() { // copy current stack - Stack stack = new Stack(new Stack(m_stack)); - string result = ""; + var stack = new Stack(new Stack(m_stack)); + string? result = string.Empty; if (stack.Count > 0) { - result = ((StackFrame)(stack.Pop())).Message; + result = stack.Pop().Message; } - LogicalThreadContextStack ltcs = new LogicalThreadContextStack(m_propertyKey, m_registerNew); - ltcs.m_stack = stack; + var ltcs = new LogicalThreadContextStack(m_propertyKey, m_registerNew) { m_stack = stack }; m_registerNew(m_propertyKey, ltcs); return result; } @@ -173,11 +147,11 @@ public string Pop() /// } /// /// - public IDisposable Push(string message) + public IDisposable Push(string? message) { // do modifications on a copy - Stack stack = new Stack(new Stack(m_stack)); - stack.Push(new StackFrame(message, (stack.Count > 0) ? (StackFrame)stack.Peek() : null)); + var stack = new Stack(new Stack(m_stack)); + stack.Push(new StackFrame(message, (stack.Count > 0) ? stack.Peek() : null)); LogicalThreadContextStack contextStack = new LogicalThreadContextStack(m_propertyKey, m_registerNew); contextStack.m_stack = stack; @@ -195,53 +169,30 @@ public IDisposable Push(string message) /// empty string (not ) is returned. /// /// - public string Peek() + public string? Peek() { - Stack stack = m_stack; + Stack stack = m_stack; if (stack.Count > 0) { - return ((StackFrame)stack.Peek()).Message; + return stack.Peek().Message; } - return ""; + return string.Empty; } - #endregion Public Methods - - #region Internal Methods - /// /// Gets the current context information for this stack. /// /// The current context information. - internal string GetFullMessage() + internal string? GetFullMessage() { - Stack stack = m_stack; + Stack stack = m_stack; if (stack.Count > 0) { - return ((StackFrame)(stack.Peek())).FullMessage; + return stack.Peek().FullMessage; } return null; } - /// - /// Gets and sets the internal stack used by this - /// - /// The internal storage stack - /// - /// - /// This property is provided only to support backward compatability - /// of the . Tytpically the internal stack should not - /// be modified. - /// - /// - internal Stack InternalStack - { - get { return m_stack; } - set { m_stack = value; } - } - - #endregion Internal Methods - /// /// Gets the current context information for this stack. /// @@ -251,44 +202,23 @@ internal Stack InternalStack /// Gets the current context information for this stack. /// /// - public override string ToString() + public override string? ToString() { return GetFullMessage(); } /// - /// Get a portable version of this object + /// Gets a cross-thread portable version of this object /// - /// the portable instance of this object - /// - /// - /// Get a cross thread portable version of this object - /// - /// - object IFixingRequired.GetFixedObject() - { - return GetFullMessage(); - } + object? IFixingRequired.GetFixedObject() => GetFullMessage(); /// /// Inner class used to represent a single context frame in the stack. /// - /// - /// - /// Inner class used to represent a single context frame in the stack. - /// - /// - private sealed class StackFrame + internal sealed class StackFrame { - #region Private Instance Fields - - private readonly string m_message; - private readonly StackFrame m_parent; - private string m_fullMessage = null; - - #endregion - - #region Internal Instance Constructors + private readonly StackFrame? m_parent; + private string? m_fullMessage; /// /// Constructor @@ -301,9 +231,9 @@ private sealed class StackFrame /// with the specified message and parent context. /// /// - internal StackFrame(string message, StackFrame parent) + internal StackFrame(string? message, StackFrame? parent) { - m_message = message; + Message = message; m_parent = parent; if (parent == null) @@ -312,10 +242,6 @@ internal StackFrame(string message, StackFrame parent) } } - #endregion Internal Instance Constructors - - #region Internal Instance Properties - /// /// Get the message. /// @@ -325,10 +251,7 @@ internal StackFrame(string message, StackFrame parent) /// Get the message. /// /// - internal string Message - { - get { return m_message; } - } + internal string? Message { get; } /// /// Gets the full text of the context down to the root level. @@ -341,19 +264,18 @@ internal string Message /// Gets the full text of the context down to the root level. /// /// - internal string FullMessage + internal string? FullMessage { get { if (m_fullMessage == null && m_parent != null) { - m_fullMessage = string.Concat(m_parent.FullMessage, " ", m_message); + m_fullMessage = string.Concat(m_parent.FullMessage, " ", Message); } + return m_fullMessage; } } - - #endregion Internal Instance Properties } /// @@ -365,23 +287,17 @@ internal string FullMessage /// with the pattern to remove the stack frame at the end of the scope. /// /// - private struct AutoPopStackFrame : IDisposable + private readonly struct AutoPopStackFrame : IDisposable { - #region Private Instance Fields - /// /// The depth to trim the stack to when this instance is disposed /// - private int m_frameDepth; + private readonly int m_frameDepth; /// /// The outer LogicalThreadContextStack. /// - private LogicalThreadContextStack m_logicalThreadContextStack; - - #endregion Private Instance Fields - - #region Internal Instance Constructors + private readonly LogicalThreadContextStack m_logicalThreadContextStack; /// /// Constructor @@ -400,10 +316,6 @@ internal AutoPopStackFrame(LogicalThreadContextStack logicalThreadContextStack, m_logicalThreadContextStack = logicalThreadContextStack; } - #endregion Internal Instance Constructors - - #region Implementation of IDisposable - /// /// Returns the stack to the correct depth. /// @@ -414,22 +326,20 @@ internal AutoPopStackFrame(LogicalThreadContextStack logicalThreadContextStack, /// public void Dispose() { - if (m_frameDepth >= 0 && m_logicalThreadContextStack.m_stack != null) + if (m_frameDepth >= 0) { - Stack stack = new Stack(new Stack(m_logicalThreadContextStack.m_stack)); + var stack = new Stack(new Stack(m_logicalThreadContextStack.m_stack)); while (stack.Count > m_frameDepth) { stack.Pop(); } - LogicalThreadContextStack ltcs = new LogicalThreadContextStack(m_logicalThreadContextStack.m_propertyKey, m_logicalThreadContextStack.m_registerNew); - ltcs.m_stack = stack; - m_logicalThreadContextStack.m_registerNew(m_logicalThreadContextStack.m_propertyKey, - ltcs); + var ltcs = new LogicalThreadContextStack(m_logicalThreadContextStack.m_propertyKey, m_logicalThreadContextStack.m_registerNew) + { + m_stack = stack + }; + m_logicalThreadContextStack.m_registerNew(m_logicalThreadContextStack.m_propertyKey, ltcs); } } - - #endregion Implementation of IDisposable } - } -} \ No newline at end of file +} diff --git a/src/log4net/Util/LogicalThreadContextStacks.cs b/src/log4net/Util/LogicalThreadContextStacks.cs index 0d32d80e..f797f48e 100644 --- a/src/log4net/Util/LogicalThreadContextStacks.cs +++ b/src/log4net/Util/LogicalThreadContextStacks.cs @@ -24,18 +24,11 @@ namespace log4net.Util /// /// Implementation of Stacks collection for the /// - /// - /// - /// Implementation of Stacks collection for the - /// - /// /// Nicko Cadell public sealed class LogicalThreadContextStacks { private readonly LogicalThreadContextProperties m_properties; - #region Public Instance Constructors - /// /// Internal constructor /// @@ -49,10 +42,6 @@ internal LogicalThreadContextStacks(LogicalThreadContextProperties properties) m_properties = properties; } - #endregion Public Instance Constructors - - #region Public Instance Properties - /// /// Gets the named thread context stack /// @@ -74,7 +63,7 @@ public LogicalThreadContextStack this[string key] if (propertyValue == null) { // Stack does not exist, create - stack = new LogicalThreadContextStack(key, registerNew); + stack = new LogicalThreadContextStack(key, RegisterNew); m_properties[key] = stack; } else @@ -96,7 +85,7 @@ public LogicalThreadContextStack this[string key] LogLog.Error(declaringType, "ThreadContextStacks: Request for stack named [" + key + "] failed because a property with the same name exists which is a [" + propertyValue.GetType().Name + "] with value [" + propertyValueString + "]"); - stack = new LogicalThreadContextStack(key, registerNew); + stack = new LogicalThreadContextStack(key, RegisterNew); } } @@ -104,19 +93,11 @@ public LogicalThreadContextStack this[string key] } } - #endregion Public Instance Properties - - #region Private Instance Fields - - private void registerNew(string stackName, LogicalThreadContextStack stack) + private void RegisterNew(string stackName, LogicalThreadContextStack stack) { m_properties[stackName] = stack; } - #endregion Private Instance Fields - - #region Private Static Fields - /// /// The fully qualified type of the ThreadContextStacks class. /// @@ -125,7 +106,5 @@ private void registerNew(string stackName, LogicalThreadContextStack stack) /// log message. /// private static readonly Type declaringType = typeof(LogicalThreadContextStacks); - - #endregion Private Static Fields } } \ No newline at end of file diff --git a/src/log4net/Util/OptionConverter.cs b/src/log4net/Util/OptionConverter.cs index 8171213c..8e5033e2 100644 --- a/src/log4net/Util/OptionConverter.cs +++ b/src/log4net/Util/OptionConverter.cs @@ -25,6 +25,8 @@ using log4net.Core; using log4net.Util.TypeConverters; +#nullable enable + namespace log4net.Util { /// @@ -37,26 +39,8 @@ namespace log4net.Util /// /// Nicko Cadell /// Gert Driesen - public sealed class OptionConverter + public static class OptionConverter { - #region Private Instance Constructors - - /// - /// Initializes a new instance of the class. - /// - /// - /// - /// Uses a private access modifier to prevent instantiation of this class. - /// - /// - private OptionConverter() - { - } - - #endregion Private Instance Constructors - - #region Public Static Methods - /// /// Converts a string to a value. /// @@ -70,9 +54,9 @@ private OptionConverter() /// Otherwise, is returned. /// /// - public static bool ToBoolean(string argValue, bool defaultValue) + public static bool ToBoolean(string? argValue, bool defaultValue) { - if (argValue != null && argValue.Length > 0) + if (!string.IsNullOrEmpty(argValue)) { try { @@ -80,7 +64,7 @@ public static bool ToBoolean(string argValue, bool defaultValue) } catch (Exception e) { - LogLog.Error(declaringType, "[" + argValue + "] is not in proper bool form.", e); + LogLog.Error(declaringType, $"[{argValue}] is not in proper bool form.", e); } } return defaultValue; @@ -102,9 +86,9 @@ public static bool ToBoolean(string argValue, bool defaultValue) /// cannot be converted to a value. /// /// - public static long ToFileSize(string argValue, long defaultValue) + public static long ToFileSize(string? argValue, long defaultValue) { - if (argValue == null) + if (argValue is null) { return defaultValue; } @@ -113,35 +97,32 @@ public static long ToFileSize(string argValue, long defaultValue) long multiplier = 1; int index; - if ((index = s.IndexOf("KB")) != -1) + if ((index = s.IndexOf("KB", StringComparison.Ordinal)) != -1) { multiplier = 1024; s = s.Substring(0, index); } - else if ((index = s.IndexOf("MB")) != -1) + else if ((index = s.IndexOf("MB", StringComparison.Ordinal)) != -1) { multiplier = 1024 * 1024; s = s.Substring(0, index); } - else if ((index = s.IndexOf("GB")) != -1) + else if ((index = s.IndexOf("GB", StringComparison.Ordinal)) != -1) { multiplier = 1024 * 1024 * 1024; s = s.Substring(0, index); } - if (s != null) - { - // Try again to remove whitespace between the number and the size specifier - s = s.Trim(); - long longVal; - if (SystemInfo.TryParse(s, out longVal)) - { - return longVal * multiplier; - } - else - { - LogLog.Error(declaringType, "OptionConverter: [" + s + "] is not in the correct file size syntax."); - } + // Try again to remove whitespace between the number and the size specifier + s = s.Trim(); + + if (SystemInfo.TryParse(s, out long longVal)) + { + return longVal * multiplier; + } + else + { + LogLog.Error(declaringType, $"OptionConverter: [{s}] is not in the correct file size syntax."); } return defaultValue; } @@ -161,11 +142,11 @@ public static long ToFileSize(string argValue, long defaultValue) /// to convert the string value into the specified target type. /// /// - public static object ConvertStringTo(Type target, string txt) + public static object? ConvertStringTo(Type target, string txt) { - if (target == null) + if (target is null) { - throw new ArgumentNullException("target"); + throw new ArgumentNullException(nameof(target)); } // If we want a string we already have the correct type @@ -175,8 +156,8 @@ public static object ConvertStringTo(Type target, string txt) } // First lets try to find a type converter - IConvertFrom typeConverter = ConverterRegistry.GetConvertFrom(target); - if (typeConverter != null && typeConverter.CanConvertFrom(typeof(string))) + IConvertFrom? typeConverter = ConverterRegistry.GetConvertFrom(target); + if (typeConverter is not null && typeConverter.CanConvertFrom(typeof(string))) { // Found appropriate converter return typeConverter.ConvertFrom(txt); @@ -196,8 +177,7 @@ public static object ConvertStringTo(Type target, string txt) // to an arbitrary type T there will be a static method defined on type T called Parse // that will take an argument of type string. i.e. T.Parse(string)->T we call this // method to convert the string to the type required by the property. - System.Reflection.MethodInfo meth = target.GetMethod("Parse", new Type[] { typeof(string) }); - if (meth != null) + if (target.GetMethod("Parse", new[] { typeof(string) }) is MethodInfo meth) { // Call the Parse method return meth.Invoke(null, BindingFlags.InvokeMethod, null, new object[] { txt }, CultureInfo.InvariantCulture); @@ -222,9 +202,9 @@ public static object ConvertStringTo(Type target, string txt) /// /// /// - public static bool CanConvertTypeTo(Type sourceType, Type targetType) + public static bool CanConvertTypeTo(Type? sourceType, Type? targetType) { - if (sourceType == null || targetType == null) + if (sourceType is null || targetType is null) { return false; } @@ -236,8 +216,7 @@ public static bool CanConvertTypeTo(Type sourceType, Type targetType) } // Look for a To converter - IConvertTo tcSource = ConverterRegistry.GetConvertTo(sourceType, targetType); - if (tcSource != null) + if (ConverterRegistry.GetConvertTo(sourceType, targetType) is IConvertTo tcSource) { if (tcSource.CanConvertTo(targetType)) { @@ -246,8 +225,7 @@ public static bool CanConvertTypeTo(Type sourceType, Type targetType) } // Look for a From converter - IConvertFrom tcTarget = ConverterRegistry.GetConvertFrom(targetType); - if (tcTarget != null) + if (ConverterRegistry.GetConvertFrom(targetType) is IConvertFrom tcTarget) { if (tcTarget.CanConvertFrom(sourceType)) { @@ -280,8 +258,7 @@ public static object ConvertTypeTo(object sourceInstance, Type targetType) } // Look for a TO converter - IConvertTo tcSource = ConverterRegistry.GetConvertTo(sourceType, targetType); - if (tcSource != null) + if (ConverterRegistry.GetConvertTo(sourceType, targetType) is IConvertTo tcSource) { if (tcSource.CanConvertTo(targetType)) { @@ -290,8 +267,7 @@ public static object ConvertTypeTo(object sourceInstance, Type targetType) } // Look for a FROM converter - IConvertFrom tcTarget = ConverterRegistry.GetConvertFrom(targetType); - if (tcTarget != null) + if (ConverterRegistry.GetConvertFrom(targetType) is IConvertFrom tcTarget) { if (tcTarget.CanConvertFrom(sourceType)) { @@ -299,41 +275,9 @@ public static object ConvertTypeTo(object sourceInstance, Type targetType) } } - throw new ArgumentException("Cannot convert source object [" + sourceInstance.ToString() + "] to target type [" + targetType.Name + "]", "sourceInstance"); + throw new ArgumentException($"Cannot convert source object [{sourceInstance}] to target type [{targetType.Name}]", nameof(sourceInstance)); } - // /// - // /// Finds the value corresponding to in - // /// and then perform variable substitution - // /// on the found value. - // /// - // /// The key to lookup. - // /// The association to use for lookups. - // /// The substituted result. - // public static string FindAndSubst(string key, System.Collections.IDictionary props) - // { - // if (props == null) - // { - // throw new ArgumentNullException("props"); - // } - // - // string v = props[key] as string; - // if (v == null) - // { - // return null; - // } - // - // try - // { - // return SubstituteVariables(v, props); - // } - // catch(Exception e) - // { - // LogLog.Error(declaringType, "OptionConverter: Bad option value [" + v + "].", e); - // return v; - // } - // } - /// /// Instantiates an object given a class name. /// @@ -351,23 +295,28 @@ public static object ConvertTypeTo(object sourceInstance, Type targetType) /// not be instantiated, then is returned. /// /// - public static object InstantiateByClassName(string className, Type superClass, object defaultValue) + public static object? InstantiateByClassName(string? className, Type superClass, object? defaultValue) { - if (className != null) + if (className is not null) { try { - Type classObj = SystemInfo.GetTypeFromString(className, true, true); - if (!superClass.IsAssignableFrom(classObj)) + Type? classObj = SystemInfo.GetTypeFromString(className, true, true); + if (classObj is not null) { - LogLog.Error(declaringType, "OptionConverter: A [" + className + "] object is not assignable to a [" + superClass.FullName + "] variable."); - return defaultValue; + if (!superClass.IsAssignableFrom(classObj)) + { + LogLog.Error(declaringType, $"OptionConverter: A [{className}] object is not assignable to a [{superClass.FullName}] variable."); + return defaultValue; + } + return Activator.CreateInstance(classObj); } - return Activator.CreateInstance(classObj); + + LogLog.Error(declaringType, $"Could not find class [{className}]."); } catch (Exception e) { - LogLog.Error(declaringType, "Could not instantiate class [" + className + "].", e); + LogLog.Error(declaringType, $"Could not instantiate class [{className}].", e); } } return defaultValue; @@ -425,7 +374,7 @@ public static string SubstituteVariables(string value, System.Collections.IDicti while (true) { - j = value.IndexOf(DELIM_START, i); + j = value.IndexOf(DELIM_START, i, StringComparison.Ordinal); if (j == -1) { if (i == 0) @@ -451,9 +400,7 @@ public static string SubstituteVariables(string value, System.Collections.IDicti j += DELIM_START_LEN; string key = value.Substring(j, k - j); - string replacement = props[key] as string; - - if (replacement != null) + if (props[key] is string replacement) { buf.Append(replacement); } @@ -463,10 +410,6 @@ public static string SubstituteVariables(string value, System.Collections.IDicti } } - #endregion Public Static Methods - - #region Private Static Methods - /// /// Converts the string representation of the name or numeric value of one or /// more enumerated constants to an equivalent enumerated object. @@ -475,15 +418,11 @@ public static string SubstituteVariables(string value, System.Collections.IDicti /// The enum string value. /// If true, ignore case; otherwise, regard case. /// An object of type whose value is represented by . - private static object ParseEnum(System.Type enumType, string value, bool ignoreCase) + private static object ParseEnum(Type enumType, string value, bool ignoreCase) { return Enum.Parse(enumType, value, ignoreCase); } - #endregion Private Static Methods - - #region Private Static Fields - /// /// The fully qualified type of the OptionConverter class. /// @@ -497,7 +436,5 @@ private static object ParseEnum(System.Type enumType, string value, bool ignoreC private const char DELIM_STOP = '}'; private const int DELIM_START_LEN = 2; private const int DELIM_STOP_LEN = 1; - - #endregion Private Static Fields } } \ No newline at end of file diff --git a/src/log4net/Util/PatternConverter.cs b/src/log4net/Util/PatternConverter.cs index efa921a0..d5b3a35c 100644 --- a/src/log4net/Util/PatternConverter.cs +++ b/src/log4net/Util/PatternConverter.cs @@ -40,8 +40,6 @@ namespace log4net.Util /// Gert Driesen public abstract class PatternConverter { - #region Protected Instance Constructors - /// /// Protected constructor /// @@ -54,25 +52,10 @@ protected PatternConverter() { } - #endregion Protected Instance Constructors - - #region Public Instance Properties - /// - /// Get the next pattern converter in the chain + /// Gets the next pattern converter in the chain. /// - /// - /// the next pattern converter in the chain - /// - /// - /// - /// Get the next pattern converter in the chain - /// - /// - public virtual PatternConverter Next - { - get { return m_next; } - } + public virtual PatternConverter? Next => m_next; /// /// Gets or sets the formatting info for this converter @@ -107,15 +90,7 @@ public virtual FormattingInfo FormattingInfo /// Gets or sets the option value for this converter /// /// - public virtual string Option - { - get { return m_option; } - set { m_option = value; } - } - - #endregion Public Instance Properties - - #region Protected Abstract Methods + public virtual string? Option { get; set; } /// /// Evaluate this pattern converter and write the output to a writer. @@ -130,10 +105,6 @@ public virtual string Option /// public abstract void Convert(TextWriter writer, object state); - #endregion Protected Abstract Methods - - #region Public Instance Methods - /// /// Set the next pattern converter in the chains /// @@ -141,7 +112,7 @@ public virtual string Option /// the next converter /// /// - /// The PatternConverter can merge with its neighbor during this method (or a sub class). + /// The PatternConverter can merge with its neighbor during this method (or a subclass). /// Therefore the return value may or may not be the value of the argument passed in. /// /// @@ -173,7 +144,7 @@ public virtual void Format(TextWriter writer, object state) } else { - string msg = null; + string? msg; int len; lock (m_formatWriter) { @@ -214,9 +185,17 @@ public virtual void Format(TextWriter writer, object state) } } - private static readonly string[] SPACES = { " ", " ", " ", " ", // 1,2,4,8 spaces - " ", // 16 spaces - " " }; // 32 spaces + private static readonly string[] SPACES = + { + // 1,2,4,8 spaces + " ", " ", " ", " ", + + // 16 spaces + " ", + + // 32 spaces + " " + }; /// /// Fast space padding method. @@ -245,25 +224,12 @@ protected static void SpacePad(TextWriter writer, int length) } } - #endregion Public Instance Methods - - #region Private Instance Fields - - private PatternConverter m_next; + private PatternConverter? m_next; private int m_min = -1; private int m_max = int.MaxValue; - private bool m_leftAlign = false; - - /// - /// The option string to the converter - /// - private string m_option = null; - - private ReusableStringWriter m_formatWriter = new ReusableStringWriter(System.Globalization.CultureInfo.InvariantCulture); + private bool m_leftAlign; - #endregion Private Instance Fields - - #region Constants + private readonly ReusableStringWriter m_formatWriter = new(System.Globalization.CultureInfo.InvariantCulture); /// /// Initial buffer size @@ -275,10 +241,6 @@ protected static void SpacePad(TextWriter writer, int length) /// private const int c_renderBufferMaxCapacity = 1024; - #endregion - - #region Static Methods - /// /// Write an dictionary to a /// @@ -304,7 +266,7 @@ protected static void WriteDictionary(TextWriter writer, ILoggerRepository repos } /// - /// Write an dictionary to a + /// Writes a dictionary to a /// /// the writer to write to /// a to use for object conversion @@ -360,16 +322,16 @@ protected static void WriteDictionary(TextWriter writer, ILoggerRepository repos /// the object's ToString method is called. /// /// - protected static void WriteObject(TextWriter writer, ILoggerRepository repository, object value) + protected static void WriteObject(TextWriter writer, ILoggerRepository? repository, object? value) { - if (repository != null) + if (repository is not null) { repository.RendererMap.FindAndRender(value, writer); } else { // Don't have a repository to render with so just have to rely on ToString - if (value == null) + if (value is null) { writer.Write(SystemInfo.NullText); } @@ -380,17 +342,9 @@ protected static void WriteObject(TextWriter writer, ILoggerRepository repositor } } - #endregion - - private PropertiesDictionary properties; - /// /// /// - public PropertiesDictionary Properties - { - get { return properties; } - set { properties = value; } - } + public PropertiesDictionary? Properties { get; set; } } } diff --git a/src/log4net/Util/PatternStringConverters/EnvironmentFolderPathPatternConverter.cs b/src/log4net/Util/PatternStringConverters/EnvironmentFolderPathPatternConverter.cs index fb2ba939..b59452ac 100644 --- a/src/log4net/Util/PatternStringConverters/EnvironmentFolderPathPatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/EnvironmentFolderPathPatternConverter.cs @@ -27,7 +27,6 @@ namespace log4net.Util.PatternStringConverters /// /// /// - /// Write an special path environment folder path to the output writer. /// The value of the determines /// the name of the variable to output. /// should be a value in the enumeration. @@ -37,7 +36,7 @@ namespace log4net.Util.PatternStringConverters internal sealed class EnvironmentFolderPathPatternConverter : PatternConverter { /// - /// Write an special path environment folder path to the output + /// Writes a special path environment folder path to the output /// /// the writer to write to /// null, state is not set diff --git a/src/log4net/Util/PatternStringConverters/EnvironmentPatternConverter.cs b/src/log4net/Util/PatternStringConverters/EnvironmentPatternConverter.cs index 44428e1e..98d77f04 100644 --- a/src/log4net/Util/PatternStringConverters/EnvironmentPatternConverter.cs +++ b/src/log4net/Util/PatternStringConverters/EnvironmentPatternConverter.cs @@ -64,7 +64,9 @@ public override void Convert(TextWriter writer, object state) envValue ??= Environment.GetEnvironmentVariable(Option, EnvironmentVariableTarget.Machine); if (envValue?.Length > 0) + { writer.Write(envValue); + } } } catch (System.Security.SecurityException secEx) @@ -80,8 +82,6 @@ public override void Convert(TextWriter writer, object state) } } - #region Private Static Fields - /// /// The fully qualified type of the EnvironmentPatternConverter class. /// @@ -90,7 +90,5 @@ public override void Convert(TextWriter writer, object state) /// log message. /// private static readonly Type declaringType = typeof(EnvironmentPatternConverter); - - #endregion Private Static Fields } -} \ No newline at end of file +} diff --git a/src/log4net/Util/PropertiesDictionary.cs b/src/log4net/Util/PropertiesDictionary.cs index 0bd500f1..ced2c727 100644 --- a/src/log4net/Util/PropertiesDictionary.cs +++ b/src/log4net/Util/PropertiesDictionary.cs @@ -19,8 +19,11 @@ using System; using System.Collections; +using System.Collections.Generic; using System.Runtime.Serialization; +#nullable enable + namespace log4net.Util { /// @@ -28,7 +31,7 @@ namespace log4net.Util /// /// /// - /// While this collection is serializable only member + /// While this collection is serializable, only member /// objects that are serializable will /// be serialized along with this collection. /// @@ -38,8 +41,6 @@ namespace log4net.Util [Serializable] public sealed class PropertiesDictionary : ReadOnlyPropertiesDictionary, ISerializable, IDictionary { - #region Public Instance Constructors - /// /// Constructor /// @@ -65,10 +66,6 @@ public PropertiesDictionary(ReadOnlyPropertiesDictionary propertiesDictionary) : { } - #endregion Public Instance Constructors - - #region Private Instance Constructors - /// /// Initializes a new instance of the class /// with serialized data. @@ -84,10 +81,6 @@ private PropertiesDictionary(SerializationInfo info, StreamingContext context) : { } - #endregion Protected Instance Constructors - - #region Public Instance Properties - /// /// Gets or sets the value of the property with the specified key. /// @@ -102,15 +95,19 @@ private PropertiesDictionary(SerializationInfo info, StreamingContext context) : /// a serialization operation is performed. /// /// - public override object this[string key] + public override object? this[string key] { - get { return InnerHashtable[key]; } - set { InnerHashtable[key] = value; } + get => base[key]; + set => InnerHashtable[key] = value; } - #endregion Public Instance Properties - - #region Public Instance Methods + /// + /// See . + /// + public override void Add(string key, object? value) + { + InnerHashtable.Add(key, value); + } /// /// Remove the entry with the specified key from this dictionary @@ -121,15 +118,11 @@ public override object this[string key] /// Remove the entry with the specified key from this dictionary /// /// - public void Remove(string key) + public override bool Remove(string key) { - InnerHashtable.Remove(key); + return InnerHashtable.Remove(key); } - #endregion Public Instance Methods - - #region Implementation of IDictionary - /// /// See /// @@ -155,22 +148,12 @@ IDictionaryEnumerator IDictionary.GetEnumerator() /// void IDictionary.Remove(object key) { - InnerHashtable.Remove(key); - } + if (key is not string k) + { + throw new ArgumentException("key must be a string"); + } - /// - /// See - /// - /// the key to lookup in the collection - /// true if the collection contains the specified key - /// - /// - /// Test if this collection contains a specified key. - /// - /// - bool IDictionary.Contains(object key) - { - return InnerHashtable.Contains(key); + InnerHashtable.Remove(k); } /// @@ -199,11 +182,11 @@ public override void Clear() /// Thrown if the is not a string void IDictionary.Add(object key, object value) { - if (!(key is string)) + if (key is not string k) { - throw new ArgumentException("key must be a string", "key"); + throw new ArgumentException("key must be a string", nameof(key)); } - InnerHashtable.Add(key, value); + InnerHashtable.Add(k, value); } /// @@ -218,10 +201,7 @@ void IDictionary.Add(object key, object value) /// returns false. /// /// - bool IDictionary.IsReadOnly - { - get { return false; } - } + bool IDictionary.IsReadOnly => false; /// /// See @@ -235,93 +215,25 @@ bool IDictionary.IsReadOnly /// /// /// Thrown if the is not a string - object IDictionary.this[object key] + object? IDictionary.this[object key] { get { - if (!(key is string)) + if (key is not string k) { - throw new ArgumentException("key must be a string", "key"); + throw new ArgumentException("key must be a string", nameof(key)); } - return InnerHashtable[key]; + InnerHashtable.TryGetValue(k, out object? val); + return val; } set { - if (!(key is string)) + if (key is not string k) { - throw new ArgumentException("key must be a string", "key"); + throw new ArgumentException("key must be a string", nameof(key)); } - InnerHashtable[key] = value; + InnerHashtable[k] = value; } } - - /// - /// See - /// - ICollection IDictionary.Values - { - get { return InnerHashtable.Values; } - } - - /// - /// See - /// - ICollection IDictionary.Keys - { - get { return InnerHashtable.Keys; } - } - - /// - /// See - /// - bool IDictionary.IsFixedSize - { - get { return false; } - } - - #endregion - - #region Implementation of ICollection - - /// - /// See - /// - /// - /// - void ICollection.CopyTo(Array array, int index) - { - InnerHashtable.CopyTo(array, index); - } - - /// - /// See - /// - bool ICollection.IsSynchronized - { - get { return InnerHashtable.IsSynchronized; } - } - - /// - /// See - /// - object ICollection.SyncRoot - { - get { return InnerHashtable.SyncRoot; } - } - - #endregion - - #region Implementation of IEnumerable - - /// - /// See - /// - IEnumerator IEnumerable.GetEnumerator() - { - return ((IEnumerable)InnerHashtable).GetEnumerator(); - } - - #endregion } } - diff --git a/src/log4net/Util/PropertyEntry.cs b/src/log4net/Util/PropertyEntry.cs index 379a2854..bac35c87 100644 --- a/src/log4net/Util/PropertyEntry.cs +++ b/src/log4net/Util/PropertyEntry.cs @@ -24,49 +24,17 @@ namespace log4net.Util /// /// A class to hold the key and data for a property set in the config file /// - /// - /// - /// A class to hold the key and data for a property set in the config file - /// - /// public class PropertyEntry { - private string m_key = null; - private object m_value = null; - /// /// Property Key /// - /// - /// Property Key - /// - /// - /// - /// Property Key. - /// - /// - public string Key - { - get { return m_key; } - set { m_key = value; } - } + public string? Key { get; set; } /// /// Property Value /// - /// - /// Property Value - /// - /// - /// - /// Property Value. - /// - /// - public object Value - { - get { return m_value; } - set { m_value = value; } - } + public object? Value { get; set; } /// /// Override Object.ToString to return sensible debug info @@ -74,7 +42,7 @@ public object Value /// string info about this object public override string ToString() { - return "PropertyEntry(Key=" + m_key + ", Value=" + m_value + ")"; + return $"PropertyEntry(Key={Key}, Value={Value})"; } } } diff --git a/src/log4net/Util/ReadOnlyPropertiesDictionary.cs b/src/log4net/Util/ReadOnlyPropertiesDictionary.cs index 10d77b51..1da7256c 100644 --- a/src/log4net/Util/ReadOnlyPropertiesDictionary.cs +++ b/src/log4net/Util/ReadOnlyPropertiesDictionary.cs @@ -19,9 +19,12 @@ using System; using System.Collections; +using System.Collections.Generic; using System.Runtime.Serialization; using System.Xml; +#nullable enable + namespace log4net.Util { /// @@ -29,10 +32,10 @@ namespace log4net.Util /// /// /// - /// This collection is readonly and cannot be modified. + /// This collection is readonly and cannot be modified. It is not thread-safe. /// /// - /// While this collection is serializable only member + /// While this collection is serializable, only member /// objects that are serializable will /// be serialized along with this collection. /// @@ -40,18 +43,9 @@ namespace log4net.Util /// Nicko Cadell /// Gert Driesen [Serializable] - public class ReadOnlyPropertiesDictionary : ISerializable, IDictionary + public class ReadOnlyPropertiesDictionary : ISerializable, IDictionary, IDictionary { - #region Private Instance Fields - - /// - /// The Hashtable used to store the properties data - /// - private readonly Hashtable m_hashtable = new Hashtable(); - - #endregion Private Instance Fields - - #region Public Instance Constructors + private const string ReadOnlyMessage = "This is a read-only dictionary and cannot be modified"; /// /// Constructor @@ -76,16 +70,12 @@ public ReadOnlyPropertiesDictionary() /// public ReadOnlyPropertiesDictionary(ReadOnlyPropertiesDictionary propertiesDictionary) { - foreach (DictionaryEntry entry in propertiesDictionary) + foreach (KeyValuePair entry in propertiesDictionary) { - InnerHashtable.Add(entry.Key, entry.Value); + InnerHashtable[entry.Key] = entry.Value; } } - #endregion Public Instance Constructors - - #region Private Instance Constructors - /// /// Deserialization constructor /// @@ -102,14 +92,10 @@ protected ReadOnlyPropertiesDictionary(SerializationInfo info, StreamingContext foreach (var entry in info) { // The keys are stored as Xml encoded names - InnerHashtable[XmlConvert.DecodeName(entry.Name)] = entry.Value; + InnerHashtable[XmlConvert.DecodeName(entry.Name) ?? string.Empty] = entry.Value; } } - #endregion Protected Instance Constructors - - #region Public Instance Properties - /// /// Gets the key names. /// @@ -127,10 +113,40 @@ public string[] GetKeys() } /// - /// Gets or sets the value of the property with the specified key. + /// See . + /// + public bool ContainsKey(string key) => InnerHashtable.ContainsKey(key); + + /// + /// See . + /// + public virtual void Add(string key, object? value) + { + throw new NotSupportedException(ReadOnlyMessage); + } + + /// + /// See . + /// + public virtual bool Remove(string key) + { + throw new NotSupportedException(ReadOnlyMessage); + } + + /// + /// See . + /// + public bool TryGetValue(string key, out object? value) + { + return InnerHashtable.TryGetValue(key, out value); + } + + /// + /// Gets or sets the value of the property with the specified key. /// /// - /// The value of the property with the specified key. + /// The value of the property with the specified key, or null if a property is not present in the dictionary. + /// Note this is the semantic, not that of . /// /// The key of the property to get or set. /// @@ -140,16 +156,16 @@ public string[] GetKeys() /// a serialization operation is performed. /// /// - public virtual object this[string key] + public virtual object? this[string key] { - get { return InnerHashtable[key]; } - set { throw new NotSupportedException("This is a Read Only Dictionary and can not be modified"); } + get + { + InnerHashtable.TryGetValue(key, out object? val); + return val; + } + set => throw new NotSupportedException(ReadOnlyMessage); } - #endregion Public Instance Properties - - #region Public Instance Methods - /// /// Test if the dictionary contains a specified key /// @@ -162,11 +178,9 @@ public virtual object this[string key] /// public bool Contains(string key) { - return InnerHashtable.Contains(key); + return InnerHashtable.ContainsKey(key); } - #endregion - /// /// The hashtable used to store the properties /// @@ -178,12 +192,7 @@ public bool Contains(string key) /// The hashtable used to store the properties /// /// - protected Hashtable InnerHashtable - { - get { return m_hashtable; } - } - - #region Implementation of ISerializable + protected Dictionary InnerHashtable { get; } = new(StringComparer.Ordinal); /// /// Serializes this object into the provided. @@ -199,39 +208,27 @@ protected Hashtable InnerHashtable [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, SerializationFormatter = true)] public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { - foreach (DictionaryEntry entry in InnerHashtable.Clone() as IDictionary) + foreach (KeyValuePair entry in InnerHashtable) { - var entryKey = entry.Key as string; - if (entryKey is null) - { - continue; - } - - var entryValue = entry.Value; - // If value is serializable then we add it to the list - var isSerializable = entryValue?.GetType().IsSerializable ?? false; + var isSerializable = entry.Value?.GetType().IsSerializable ?? false; if (!isSerializable) { continue; } - // Store the keys as an Xml encoded local name as it may contain colons (':') + // Store the keys as an XML encoded local name as it may contain colons (':') // which are NOT escaped by the Xml Serialization framework. // This must be a bug in the serialization framework as we cannot be expected // to know the implementation details of all the possible transport layers. - var localKeyName = XmlConvert.EncodeLocalName(entryKey); + var localKeyName = XmlConvert.EncodeLocalName(entry.Key); if (localKeyName is not null) { - info.AddValue(localKeyName, entryValue); + info.AddValue(localKeyName, entry.Value); } } } - #endregion Implementation of ISerializable - - #region Implementation of IDictionary - /// /// See /// @@ -240,132 +237,162 @@ IDictionaryEnumerator IDictionary.GetEnumerator() return InnerHashtable.GetEnumerator(); } + /// + /// See + /// + IEnumerator> IEnumerable>.GetEnumerator() + { + return InnerHashtable.GetEnumerator(); + } + /// /// See /// /// void IDictionary.Remove(object key) { - throw new NotSupportedException("This is a Read Only Dictionary and can not be modified"); + throw new NotSupportedException(ReadOnlyMessage); } /// /// See /// - /// - /// bool IDictionary.Contains(object key) { - return InnerHashtable.Contains(key); + if (key is not string k) + { + throw new ArgumentException("key must be a string"); + } + return InnerHashtable.ContainsKey(k); } /// - /// Remove all properties from the properties collection + /// See . /// - public virtual void Clear() + public void Add(KeyValuePair item) { - throw new NotSupportedException("This is a Read Only Dictionary and can not be modified"); + InnerHashtable.Add(item.Key, item.Value); } /// - /// See + /// Removes all properties from the properties collection /// - /// - /// - void IDictionary.Add(object key, object value) + public virtual void Clear() { - throw new NotSupportedException("This is a Read Only Dictionary and can not be modified"); + throw new NotSupportedException(ReadOnlyMessage); } /// - /// See + /// See . /// - bool IDictionary.IsReadOnly + public bool Contains(KeyValuePair item) { - get { return true; } + return InnerHashtable.TryGetValue(item.Key, out object? v) && item.Value == v; } /// - /// See + /// See . /// - object IDictionary.this[object key] + public void CopyTo(KeyValuePair[] array, int arrayIndex) { - get + int i = arrayIndex; + foreach (var kvp in InnerHashtable) { - if (!(key is string)) throw new ArgumentException("key must be a string"); - return InnerHashtable[key]; - } - set - { - throw new NotSupportedException("This is a Read Only Dictionary and can not be modified"); + array[i] = kvp; + i++; } } /// - /// See + /// See . /// - ICollection IDictionary.Values + public bool Remove(KeyValuePair item) { - get { return InnerHashtable.Values; } + return InnerHashtable.Remove(item.Key); } /// - /// See + /// See . /// - ICollection IDictionary.Keys + void IDictionary.Add(object key, object value) { - get { return InnerHashtable.Keys; } + throw new NotSupportedException(ReadOnlyMessage); } /// - /// See + /// See . /// - bool IDictionary.IsFixedSize + bool IDictionary.IsReadOnly => true; + + /// + /// See + /// + object? IDictionary.this[object key] { - get { return InnerHashtable.IsFixedSize; } + get + { + if (key is not string k) + { + throw new ArgumentException("key must be a string", nameof(key)); + } + InnerHashtable.TryGetValue(k, out object? val); + return val; + } + set => throw new NotSupportedException(ReadOnlyMessage); } - #endregion + /// + /// See . + /// + public ICollection Keys => InnerHashtable.Keys; - #region Implementation of ICollection + /// + /// See . + /// + public ICollection Values => InnerHashtable.Values; + + /// + /// See + /// + ICollection IDictionary.Values => InnerHashtable.Values; + + /// + /// See + /// + ICollection IDictionary.Keys => InnerHashtable.Keys; + + /// + /// See + /// + bool IDictionary.IsFixedSize => false; /// /// See /// - /// - /// void ICollection.CopyTo(Array array, int index) { - InnerHashtable.CopyTo(array, index); + ((ICollection)InnerHashtable).CopyTo(array, index); } /// /// See /// - bool ICollection.IsSynchronized - { - get { return InnerHashtable.IsSynchronized; } - } + bool ICollection.IsSynchronized => false; /// /// The number of properties in this collection /// - public int Count - { - get { return InnerHashtable.Count; } - } + public int Count => InnerHashtable.Count; /// - /// See + /// See . /// - object ICollection.SyncRoot - { - get { return InnerHashtable.SyncRoot; } - } + public bool IsReadOnly => true; - #endregion - - #region Implementation of IEnumerable + /// + /// See + /// + object ICollection.SyncRoot => InnerHashtable; /// /// See @@ -374,8 +401,5 @@ IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)InnerHashtable).GetEnumerator(); } - - #endregion } } - diff --git a/src/log4net/Util/SystemStringFormat.cs b/src/log4net/Util/SystemStringFormat.cs index 2a945315..65d7bc64 100644 --- a/src/log4net/Util/SystemStringFormat.cs +++ b/src/log4net/Util/SystemStringFormat.cs @@ -19,23 +19,16 @@ using System; using System.Text; -using System.Xml; -using System.Text.RegularExpressions; namespace log4net.Util { /// /// Utility class that represents a format string. /// - /// - /// - /// Utility class that represents a format string. - /// - /// /// Nicko Cadell public sealed class SystemStringFormat { - private readonly IFormatProvider m_provider; + private readonly IFormatProvider? m_provider; /// /// Format @@ -47,34 +40,28 @@ public sealed class SystemStringFormat /// public object[] Args { get; set; } - #region Constructor - /// /// Initialise the /// /// An that supplies culture-specific formatting information. /// A containing zero or more format items. /// An array containing zero or more objects to format. - public SystemStringFormat(IFormatProvider provider, string format, params object[] args) + public SystemStringFormat(IFormatProvider? provider, string format, params object[] args) { m_provider = provider; Format = format; Args = args; } - #endregion Constructor - /// /// Format the string and arguments /// /// the formatted string - public override string ToString() + public override string? ToString() { return StringFormat(m_provider, Format, Args); } - #region StringFormat - /// /// Replaces the format item in a specified with the text equivalent /// of the value of a corresponding instance in a specified array. @@ -93,28 +80,28 @@ public override string ToString() /// exception and arguments are returned in the result string. /// /// - private static string StringFormat(IFormatProvider provider, string format, params object[] args) + private static string? StringFormat(IFormatProvider? provider, string? format, params object[]? args) { try { // The format is missing, log null value - if (format == null) + if (format is null) { return null; } // The args are missing - should not happen unless we are called explicitly with a null array - if (args == null) + if (args is null) { return format; } // Try to format the string - return String.Format(provider, format, args); + return string.Format(provider, format, args); } catch (Exception ex) { - log4net.Util.LogLog.Warn(declaringType, "Exception while rendering format [" + format + "]", ex); + LogLog.Warn(declaringType, $"Exception while rendering format [{format}]", ex); return StringFormatError(ex, format, args); } } @@ -122,13 +109,13 @@ private static string StringFormat(IFormatProvider provider, string format, para /// /// Process an error during StringFormat /// - private static string StringFormatError(Exception formatException, string format, object[] args) + private static string StringFormatError(Exception? formatException, string? format, object[]? args) { try { - StringBuilder buf = new StringBuilder(""); + var buf = new StringBuilder("", 100); - if (formatException != null) + if (formatException is not null) { buf.Append("Exception during StringFormat: ").Append(formatException.Message); } @@ -146,7 +133,7 @@ private static string StringFormatError(Exception formatException, string format } catch (Exception ex) { - log4net.Util.LogLog.Error(declaringType, "INTERNAL ERROR during StringFormat error handling", ex); + LogLog.Error(declaringType, "INTERNAL ERROR during StringFormat error handling", ex); return "Exception during StringFormat. See Internal Log."; } } @@ -154,9 +141,9 @@ private static string StringFormatError(Exception formatException, string format /// /// Dump the contents of an array into a string builder /// - private static void RenderArray(Array array, StringBuilder buffer) + private static void RenderArray(Array? array, StringBuilder buffer) { - if (array == null) + if (array is null) { buffer.Append(SystemInfo.NullText); } @@ -164,7 +151,7 @@ private static void RenderArray(Array array, StringBuilder buffer) { if (array.Rank != 1) { - buffer.Append(array.ToString()); + buffer.Append(array); } else { @@ -188,9 +175,9 @@ private static void RenderArray(Array array, StringBuilder buffer) /// /// Dump an object to a string /// - private static void RenderObject(Object obj, StringBuilder buffer) + private static void RenderObject(object? obj, StringBuilder buffer) { - if (obj == null) + if (obj is null) { buffer.Append(SystemInfo.NullText); } @@ -207,10 +194,6 @@ private static void RenderObject(Object obj, StringBuilder buffer) } } - #endregion StringFormat - - #region Private Static Fields - /// /// The fully qualified type of the SystemStringFormat class. /// @@ -219,7 +202,5 @@ private static void RenderObject(Object obj, StringBuilder buffer) /// log message. /// private static readonly Type declaringType = typeof(SystemStringFormat); - - #endregion Private Static Fields } } diff --git a/src/log4net/Util/ThreadContextProperties.cs b/src/log4net/Util/ThreadContextProperties.cs index 39040a61..939f8f73 100644 --- a/src/log4net/Util/ThreadContextProperties.cs +++ b/src/log4net/Util/ThreadContextProperties.cs @@ -19,6 +19,8 @@ using System; +#nullable enable + namespace log4net.Util { /// @@ -33,17 +35,11 @@ namespace log4net.Util /// Nicko Cadell public sealed class ThreadContextProperties : ContextPropertiesBase { - #region Private Instance Fields - /// /// Each thread will automatically have its instance. /// [ThreadStatic] - private static PropertiesDictionary _dictionary; - - #endregion Private Instance Fields - - #region Public Instance Constructors + private static PropertiesDictionary? _dictionary; /// /// Internal constructor @@ -57,10 +53,6 @@ internal ThreadContextProperties() { } - #endregion Public Instance Constructors - - #region Public Instance Properties - /// /// Gets or sets the value of a property /// @@ -72,26 +64,12 @@ internal ThreadContextProperties() /// Gets or sets the value of a property /// /// - public override object this[string key] + public override object? this[string key] { - get - { - if (_dictionary != null) - { - return _dictionary[key]; - } - return null; - } - set - { - GetProperties(true)[key] = value; - } + get => _dictionary?[key]; + set => GetProperties(true)![key] = value; } - #endregion Public Instance Properties - - #region Public Instance Methods - /// /// Remove a property /// @@ -101,13 +79,7 @@ public override object this[string key] /// Remove a property /// /// - public void Remove(string key) - { - if (_dictionary != null) - { - _dictionary.Remove(key); - } - } + public void Remove(string key) => _dictionary?.Remove(key); /// /// Get the keys stored in the properties. @@ -116,14 +88,7 @@ public void Remove(string key) /// Gets the keys stored in the properties. /// /// a set of the defined keys - public string[] GetKeys() - { - if (_dictionary != null) - { - return _dictionary.GetKeys(); - } - return null; - } + public string[]? GetKeys() => _dictionary?.GetKeys(); /// /// Clear all properties @@ -133,22 +98,12 @@ public string[] GetKeys() /// Clear all properties /// /// - public void Clear() - { - if (_dictionary != null) - { - _dictionary.Clear(); - } - } - - #endregion Public Instance Methods - - #region Internal Instance Methods + public void Clear() => _dictionary?.Clear(); /// /// Get the PropertiesDictionary for this thread. /// - /// create the dictionary if it does not exist, otherwise return null if does not exist + /// create the dictionary if it does not exist, otherwise return null if it does not exist /// the properties for this thread /// /// @@ -157,15 +112,13 @@ public void Clear() /// caller must clone the collection before doing so. /// /// - internal PropertiesDictionary GetProperties(bool create) + internal PropertiesDictionary? GetProperties(bool create) { - if (_dictionary == null && create) + if (_dictionary is null && create) { _dictionary = new PropertiesDictionary(); } return _dictionary; } - - #endregion Internal Instance Methods } } \ No newline at end of file diff --git a/src/log4net/Util/ThreadContextStack.cs b/src/log4net/Util/ThreadContextStack.cs index 5beb1dd6..ff72943d 100644 --- a/src/log4net/Util/ThreadContextStack.cs +++ b/src/log4net/Util/ThreadContextStack.cs @@ -18,8 +18,8 @@ #endregion using System; - using System.Collections; +using System.Collections.Generic; using log4net.Core; @@ -36,16 +36,10 @@ namespace log4net.Util /// Nicko Cadell public sealed class ThreadContextStack : IFixingRequired { - #region Private Static Fields - /// /// The stack store. /// - private Stack m_stack = new Stack(); - - #endregion Private Static Fields - - #region Public Instance Constructors + private readonly Stack m_stack = new(); /// /// Internal constructor @@ -59,10 +53,6 @@ internal ThreadContextStack() { } - #endregion Public Instance Constructors - - #region Public Properties - /// /// The number of messages in the stack /// @@ -76,14 +66,7 @@ internal ThreadContextStack() /// minus the number of times has been called. /// /// - public int Count - { - get { return m_stack.Count; } - } - - #endregion // Public Properties - - #region Public Methods + public int Count => m_stack.Count; /// /// Clears all the contextual information held in this stack. @@ -100,10 +83,7 @@ public int Count /// syntax. /// /// - public void Clear() - { - m_stack.Clear(); - } + public void Clear() => m_stack.Clear(); /// /// Removes the top context from this stack. @@ -116,14 +96,14 @@ public void Clear() /// empty string (not ) is returned. /// /// - public string Pop() + public string? Pop() { - Stack stack = m_stack; + Stack stack = m_stack; if (stack.Count > 0) { - return ((StackFrame)(stack.Pop())).Message; + return stack.Pop().Message; } - return ""; + return string.Empty; } /// @@ -149,10 +129,10 @@ public string Pop() /// } /// /// - public IDisposable Push(string message) + public IDisposable Push(string? message) { - Stack stack = m_stack; - stack.Push(new StackFrame(message, (stack.Count > 0) ? (StackFrame)stack.Peek() : null)); + Stack stack = m_stack; + stack.Push(new StackFrame(message, (stack.Count > 0) ? stack.Peek() : null)); return new AutoPopStackFrame(stack, stack.Count - 1); } @@ -167,30 +147,26 @@ public IDisposable Push(string message) /// empty string (not ) is returned. /// /// - public string Peek() + public string? Peek() { - Stack stack = m_stack; + Stack stack = m_stack; if (stack.Count > 0) { - return ((StackFrame)stack.Peek()).Message; + return stack.Peek().Message; } return ""; } - #endregion Public Methods - - #region Internal Methods - /// /// Gets the current context information for this stack. /// /// The current context information. - internal string GetFullMessage() + internal string? GetFullMessage() { - Stack stack = m_stack; + Stack stack = m_stack; if (stack.Count > 0) { - return ((StackFrame)(stack.Peek())).FullMessage; + return stack.Peek().FullMessage; } return null; } @@ -201,46 +177,34 @@ internal string GetFullMessage() /// The internal storage stack /// /// - /// This property is provided only to support backward compatability - /// of the . Tytpically the internal stack should not + /// This property is provided only to support backward compatibility + /// of the . Typically the internal stack should not /// be modified. /// /// internal Stack InternalStack { - get { return m_stack; } - set { m_stack = value; } + get => new Stack(new Stack(m_stack)); + set + { + m_stack.Clear(); + var frames = (StackFrame[])value.ToArray(); + for (int i = frames.Length - 1; i >= 0; i--) + { + m_stack.Push(frames[i]); + } + } } - #endregion Internal Methods - /// /// Gets the current context information for this stack. /// - /// Gets the current context information - /// - /// - /// Gets the current context information for this stack. - /// - /// - public override string ToString() - { - return GetFullMessage(); - } + public override string? ToString() => GetFullMessage(); /// /// Get a portable version of this object /// - /// the portable instance of this object - /// - /// - /// Get a cross thread portable version of this object - /// - /// - object IFixingRequired.GetFixedObject() - { - return GetFullMessage(); - } + object? IFixingRequired.GetFixedObject() => GetFullMessage(); /// /// Inner class used to represent a single context frame in the stack. @@ -250,17 +214,10 @@ object IFixingRequired.GetFixedObject() /// Inner class used to represent a single context frame in the stack. /// /// - private sealed class StackFrame + internal sealed class StackFrame { - #region Private Instance Fields - - private readonly string m_message; - private readonly StackFrame m_parent; - private string m_fullMessage = null; - - #endregion - - #region Internal Instance Constructors + private readonly StackFrame? m_parent; + private string? m_fullMessage; /// /// Constructor @@ -273,21 +230,17 @@ private sealed class StackFrame /// with the specified message and parent context. /// /// - internal StackFrame(string message, StackFrame parent) + internal StackFrame(string? message, StackFrame? parent) { - m_message = message; + Message = message; m_parent = parent; - if (parent == null) + if (parent is null) { m_fullMessage = message; } } - #endregion Internal Instance Constructors - - #region Internal Instance Properties - /// /// Get the message. /// @@ -297,10 +250,7 @@ internal StackFrame(string message, StackFrame parent) /// Get the message. /// /// - internal string Message - { - get { return m_message; } - } + internal string? Message { get; } /// /// Gets the full text of the context down to the root level. @@ -313,19 +263,17 @@ internal string Message /// Gets the full text of the context down to the root level. /// /// - internal string FullMessage + internal string? FullMessage { get { - if (m_fullMessage == null && m_parent != null) + if (m_fullMessage is null && m_parent is not null) { - m_fullMessage = string.Concat(m_parent.FullMessage, " ", m_message); + m_fullMessage = string.Concat(m_parent.FullMessage, " ", Message); } return m_fullMessage; } } - - #endregion Internal Instance Properties } /// @@ -337,56 +285,36 @@ internal string FullMessage /// with the pattern to remove the stack frame at the end of the scope. /// /// - private struct AutoPopStackFrame : IDisposable + private readonly struct AutoPopStackFrame : IDisposable { - #region Private Instance Fields - /// /// The ThreadContextStack internal stack /// - private Stack m_frameStack; + private readonly Stack m_frameStack; /// /// The depth to trim the stack to when this instance is disposed /// - private int m_frameDepth; - - #endregion Private Instance Fields - - #region Internal Instance Constructors + private readonly int m_frameDepth; /// - /// Constructor + /// Initializes a new instance of the class with + /// the specified stack and return depth. /// /// The internal stack used by the ThreadContextStack. /// The depth to return the stack to when this object is disposed. - /// - /// - /// Initializes a new instance of the class with - /// the specified stack and return depth. - /// - /// - internal AutoPopStackFrame(Stack frameStack, int frameDepth) + internal AutoPopStackFrame(Stack frameStack, int frameDepth) { m_frameStack = frameStack; m_frameDepth = frameDepth; } - #endregion Internal Instance Constructors - - #region Implementation of IDisposable - /// /// Returns the stack to the correct depth. /// - /// - /// - /// Returns the stack to the correct depth. - /// - /// public void Dispose() { - if (m_frameDepth >= 0 && m_frameStack != null) + if (m_frameDepth >= 0) { while (m_frameStack.Count > m_frameDepth) { @@ -394,8 +322,6 @@ public void Dispose() } } } - - #endregion Implementation of IDisposable } } -} \ No newline at end of file +} diff --git a/src/log4net/Util/TypeConverters/ConverterRegistry.cs b/src/log4net/Util/TypeConverters/ConverterRegistry.cs index eaf29ada..fb0b4cad 100644 --- a/src/log4net/Util/TypeConverters/ConverterRegistry.cs +++ b/src/log4net/Util/TypeConverters/ConverterRegistry.cs @@ -18,7 +18,7 @@ #endregion using System; -using System.Collections; +using System.Collections.Concurrent; namespace log4net.Util.TypeConverters { @@ -41,24 +41,8 @@ namespace log4net.Util.TypeConverters /// /// Nicko Cadell /// Gert Driesen - public sealed class ConverterRegistry + public static class ConverterRegistry { - #region Private Constructors - - /// - /// Private constructor - /// - /// - /// Initializes a new instance of the class. - /// - private ConverterRegistry() - { - } - - #endregion Private Constructors - - #region Static Constructor - /// /// Static constructor. /// @@ -72,16 +56,12 @@ static ConverterRegistry() // Add predefined converters here AddConverter(typeof(bool), typeof(BooleanConverter)); AddConverter(typeof(System.Text.Encoding), typeof(EncodingConverter)); - AddConverter(typeof(System.Type), typeof(TypeConverter)); - AddConverter(typeof(log4net.Layout.PatternLayout), typeof(PatternLayoutConverter)); - AddConverter(typeof(log4net.Util.PatternString), typeof(PatternStringConverter)); + AddConverter(typeof(Type), typeof(TypeConverter)); + AddConverter(typeof(Layout.PatternLayout), typeof(PatternLayoutConverter)); + AddConverter(typeof(PatternString), typeof(PatternStringConverter)); AddConverter(typeof(System.Net.IPAddress), typeof(IPAddressConverter)); } - #endregion Static Constructor - - #region Public Static Methods - /// /// Adds a converter for a specific type. /// @@ -92,13 +72,17 @@ static ConverterRegistry() /// Adds a converter instance for a specific type. /// /// - public static void AddConverter(Type destinationType, object converter) + public static void AddConverter(Type? destinationType, object? converter) { - if (destinationType != null && converter != null) + if (destinationType is not null && converter is not null) { - lock (s_type2converter) + if (converter is IConvertTo convertTo) { - s_type2converter[destinationType] = converter; + s_type2ConvertTo[destinationType] = convertTo; + } + else if (converter is IConvertFrom convertFrom) + { + s_type2ConvertFrom[destinationType] = convertFrom; } } } @@ -132,32 +116,26 @@ public static void AddConverter(Type destinationType, Type converterType) /// Gets the type converter to use to convert values to the destination type. /// /// - public static IConvertTo GetConvertTo(Type sourceType, Type destinationType) + public static IConvertTo? GetConvertTo(Type sourceType, Type destinationType) { // TODO: Support inheriting type converters. // i.e. getting a type converter for a base of sourceType // TODO: Is destinationType required? We don't use it for anything. - lock (s_type2converter) + // Look up in the static registry + if (!s_type2ConvertTo.TryGetValue(sourceType, out IConvertTo? converter)) { - // Lookup in the static registry - IConvertTo converter = s_type2converter[sourceType] as IConvertTo; - - if (converter == null) + // Look up using attributes + converter = GetConverterFromAttribute(sourceType) as IConvertTo; + if (converter is not null) { - // Lookup using attributes - converter = GetConverterFromAttribute(sourceType) as IConvertTo; - - if (converter != null) - { - // Store in registry - s_type2converter[sourceType] = converter; - } + // Store in registry + s_type2ConvertTo[sourceType] = converter; } - - return converter; } + + return converter; } /// @@ -173,30 +151,24 @@ public static IConvertTo GetConvertTo(Type sourceType, Type destinationType) /// Gets the type converter to use to convert values to the destination type. /// /// - public static IConvertFrom GetConvertFrom(Type destinationType) + public static IConvertFrom? GetConvertFrom(Type destinationType) { // TODO: Support inheriting type converters. // i.e. getting a type converter for a base of destinationType - lock (s_type2converter) + // Lookup in the static registry + if (!s_type2ConvertFrom.TryGetValue(destinationType, out IConvertFrom? converter)) { - // Lookup in the static registry - IConvertFrom converter = s_type2converter[destinationType] as IConvertFrom; - - if (converter == null) + // Look up using attributes + converter = GetConverterFromAttribute(destinationType) as IConvertFrom; + if (converter is not null) { - // Lookup using attributes - converter = GetConverterFromAttribute(destinationType) as IConvertFrom; - - if (converter != null) - { - // Store in registry - s_type2converter[destinationType] = converter; - } + // Store in registry + s_type2ConvertFrom[destinationType] = converter; } - - return converter; } + + return converter; } /// @@ -208,24 +180,18 @@ public static IConvertFrom GetConvertFrom(Type destinationType) /// The type converter instance to use for type conversions or null /// if no type converter is found. /// - private static object GetConverterFromAttribute(Type destinationType) + private static object? GetConverterFromAttribute(Type destinationType) { // Look for an attribute on the destination type - var attributes = destinationType - .GetCustomAttributes(typeof(TypeConverterAttribute), true); - if (attributes is null) - { - // I assume the original null check is perhaps for CF or older .NET versions -- please leave in place - return null; - } - + object[] attributes = destinationType.GetCustomAttributes(typeof(TypeConverterAttribute), true); foreach (var attribute in attributes) { - var tcAttr = attribute as TypeConverterAttribute; - if (tcAttr != null) + if (attribute is TypeConverterAttribute tcAttr) { - var converterType = SystemInfo.GetTypeFromString(destinationType, tcAttr.ConverterTypeName, false, true); - return CreateConverterInstance(converterType); + if (SystemInfo.GetTypeFromString(destinationType, tcAttr.ConverterTypeName, false, true) is Type converterType) + { + return CreateConverterInstance(converterType); + } } } @@ -248,13 +214,8 @@ private static object GetConverterFromAttribute(Type destinationType) /// and must have a public default (no argument) constructor. /// /// - private static object CreateConverterInstance(Type converterType) + private static object? CreateConverterInstance(Type converterType) { - if (converterType == null) - { - throw new ArgumentNullException("converterType", "CreateConverterInstance cannot create instance, converterType is null"); - } - // Check type is a converter if (typeof(IConvertFrom).IsAssignableFrom(converterType) || typeof(IConvertTo).IsAssignableFrom(converterType)) { @@ -265,20 +226,16 @@ private static object CreateConverterInstance(Type converterType) } catch (Exception ex) { - LogLog.Error(declaringType, "Cannot CreateConverterInstance of type [" + converterType.FullName + "], Exception in call to Activator.CreateInstance", ex); + LogLog.Error(declaringType, $"Cannot CreateConverterInstance of type [{converterType.FullName}], exception in call to Activator.CreateInstance", ex); } } else { - LogLog.Error(declaringType, "Cannot CreateConverterInstance of type [" + converterType.FullName + "], type does not implement IConvertFrom or IConvertTo"); + LogLog.Error(declaringType, $"Cannot CreateConverterInstance of type [{converterType.FullName}], type does not implement IConvertFrom or IConvertTo"); } return null; } - #endregion Public Static Methods - - #region Private Static Fields - /// /// The fully qualified type of the ConverterRegistry class. /// @@ -288,11 +245,7 @@ private static object CreateConverterInstance(Type converterType) /// private static readonly Type declaringType = typeof(ConverterRegistry); - /// - /// Mapping from to type converter. - /// - private static Hashtable s_type2converter = new Hashtable(); - - #endregion + private static readonly ConcurrentDictionary s_type2ConvertTo = new(); + private static readonly ConcurrentDictionary s_type2ConvertFrom = new(); } }