From 91d5c2f4c4800c30dd67a25df26265f96ca67ed5 Mon Sep 17 00:00:00 2001 From: Charles Lowell Date: Fri, 23 Oct 2015 16:46:30 -0700 Subject: [PATCH] LOG4NET-467: Add support for .NET Core --- .gitignore | 230 +++++++++++++++++++ netstandard/global.json | 3 + netstandard/log4net.netstandard.sln | 34 +++ netstandard/log4net.tests/ApplicationException.cs | 8 + .../log4net.tests/CompatibilityExtensions.cs | 19 ++ .../log4net.tests/ExpectedExceptionAttribute.cs | 66 ++++++ netstandard/log4net.tests/log4net.tests.xproj | 46 ++++ netstandard/log4net.tests/project.json | 44 ++++ netstandard/log4net/CompatibilityExtensions.cs | 34 +++ netstandard/log4net/log4net.xproj | 244 +++++++++++++++++++++ netstandard/log4net/project.json | 94 ++++++++ src/Appender/AnsiColorTerminalAppender.cs | 7 +- src/Appender/AppenderCollection.cs | 11 +- src/Appender/AppenderSkeleton.cs | 4 +- src/Appender/ConsoleAppender.cs | 7 +- src/Appender/DebugAppender.cs | 3 +- src/Appender/FileAppender.cs | 23 +- src/Appender/LocalSyslogAppender.cs | 8 +- src/Appender/ManagedColoredConsoleAppender.cs | 8 +- src/Appender/NetSendAppender.cs | 4 +- src/Appender/OutputDebugStringAppender.cs | 9 +- src/Appender/RemoteSyslogAppender.cs | 4 + src/Appender/TelnetAppender.cs | 27 ++- src/Appender/UdpAppender.cs | 8 + src/AssemblyInfo.cs | 2 + src/Config/BasicConfigurator.cs | 34 +-- src/Config/PluginAttribute.cs | 5 +- src/Config/XmlConfigurator.cs | 156 ++++++------- src/Core/DefaultRepositorySelector.cs | 22 +- src/Core/ExceptionEvaluator.cs | 3 + src/Core/Level.cs | 4 + src/Core/LevelCollection.cs | 11 +- src/Core/LocationInfo.cs | 6 +- src/Core/LogException.cs | 6 +- src/Core/LoggerManager.cs | 25 ++- src/Core/LoggingEvent.cs | 14 +- src/Filter/StringMatchFilter.cs | 4 + src/Layout/Pattern/DatePatternConverter.cs | 25 ++- src/Layout/Pattern/ExceptionPatternConverter.cs | 2 + src/Layout/PatternLayout.cs | 7 +- src/Layout/RawLayoutConverter.cs | 3 + src/Layout/XmlLayout.cs | 2 +- src/Layout/XmlLayoutBase.cs | 11 +- src/LogManager.cs | 112 ++++++---- src/ObjectRenderer/RendererMap.cs | 8 + src/Plugin/PluginCollection.cs | 11 +- src/Repository/Hierarchy/Logger.cs | 10 +- src/Repository/Hierarchy/LoggerKey.cs | 4 +- .../Hierarchy/XmlHierarchyConfigurator.cs | 46 +++- src/Util/ILogExtensions.cs | 2 +- src/Util/LogLog.cs | 2 + src/Util/NativeError.cs | 4 +- src/Util/OptionConverter.cs | 12 + src/Util/PatternParser.cs | 12 + src/Util/PatternString.cs | 7 +- .../DatePatternConverter.cs | 25 ++- .../IdentityPatternConverter.cs | 2 +- .../NewLinePatternConverter.cs | 14 ++ .../ProcessIdPatternConverter.cs | 2 +- .../PropertyPatternConverter.cs | 2 +- .../UserNamePatternConverter.cs | 2 +- src/Util/PropertiesDictionary.cs | 2 +- src/Util/ReadOnlyPropertiesDictionary.cs | 14 +- src/Util/SystemInfo.cs | 41 +++- src/Util/SystemStringFormat.cs | 6 +- src/Util/TextWriterAdapter.cs | 7 + .../ConversionNotSupportedException.cs | 8 +- src/Util/TypeConverters/ConverterRegistry.cs | 3 + src/Util/TypeConverters/IPAddressConverter.cs | 4 + src/Util/TypeConverters/PatternStringConverter.cs | 3 + src/Util/TypeConverters/TypeConverter.cs | 7 + tests/src/Appender/RollingFileAppenderTest.cs | 22 +- tests/src/Appender/SmtpPickupDirAppenderTest.cs | 6 +- tests/src/Appender/TraceAppenderTest.cs | 2 + tests/src/Core/FixingTest.cs | 6 + tests/src/Core/StringFormatTest.cs | 2 + tests/src/Hierarchy/Hierarchy.cs | 7 +- tests/src/Hierarchy/Logger.cs | 54 +++-- .../src/Hierarchy/XmlHierarchyConfiguratorTest.cs | 2 + tests/src/Layout/PatternLayoutTest.cs | 6 + tests/src/Layout/XmlLayoutTest.cs | 13 +- tests/src/Util/SystemInfoTest.cs | 57 +++-- tests/src/Utils.cs | 32 ++- 83 files changed, 1572 insertions(+), 296 deletions(-) create mode 100644 .gitignore create mode 100644 netstandard/global.json create mode 100644 netstandard/log4net.netstandard.sln create mode 100644 netstandard/log4net.tests/ApplicationException.cs create mode 100644 netstandard/log4net.tests/CompatibilityExtensions.cs create mode 100644 netstandard/log4net.tests/ExpectedExceptionAttribute.cs create mode 100644 netstandard/log4net.tests/log4net.tests.xproj create mode 100644 netstandard/log4net.tests/project.json create mode 100644 netstandard/log4net/CompatibilityExtensions.cs create mode 100644 netstandard/log4net/log4net.xproj create mode 100644 netstandard/log4net/project.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1ce22ce --- /dev/null +++ b/.gitignore @@ -0,0 +1,230 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Azure Emulator +efc/ +rfc/ + +# Windows Store app package directory +AppPackages/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe + +# FAKE - F# Make +.fake/ \ No newline at end of file diff --git a/netstandard/global.json b/netstandard/global.json new file mode 100644 index 0000000..200ddfd --- /dev/null +++ b/netstandard/global.json @@ -0,0 +1,3 @@ +{ + "projects": [ "log4net", "log4net.tests" ] +} diff --git a/netstandard/log4net.netstandard.sln b/netstandard/log4net.netstandard.sln new file mode 100644 index 0000000..255db0f --- /dev/null +++ b/netstandard/log4net.netstandard.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "log4net", "log4net\log4net.xproj", "{00764202-B361-4BC8-A1B9-01D87F9D2D51}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "log4net.tests", "log4net.tests\log4net.tests.xproj", "{6A78D53B-C864-4316-AA00-F2EBFE975223}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4BB38D1C-1862-432B-881C-925714F7F997}" + ProjectSection(SolutionItems) = preProject + global.json = global.json + nuget.config = nuget.config + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {00764202-B361-4BC8-A1B9-01D87F9D2D51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {00764202-B361-4BC8-A1B9-01D87F9D2D51}.Debug|Any CPU.Build.0 = Debug|Any CPU + {00764202-B361-4BC8-A1B9-01D87F9D2D51}.Release|Any CPU.ActiveCfg = Release|Any CPU + {00764202-B361-4BC8-A1B9-01D87F9D2D51}.Release|Any CPU.Build.0 = Release|Any CPU + {6A78D53B-C864-4316-AA00-F2EBFE975223}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6A78D53B-C864-4316-AA00-F2EBFE975223}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6A78D53B-C864-4316-AA00-F2EBFE975223}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6A78D53B-C864-4316-AA00-F2EBFE975223}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/netstandard/log4net.tests/ApplicationException.cs b/netstandard/log4net.tests/ApplicationException.cs new file mode 100644 index 0000000..9d48f1d --- /dev/null +++ b/netstandard/log4net.tests/ApplicationException.cs @@ -0,0 +1,8 @@ +using System; + +namespace log4net.Tests +{ + public class ApplicationException : Exception + { + } +} diff --git a/netstandard/log4net.tests/CompatibilityExtensions.cs b/netstandard/log4net.tests/CompatibilityExtensions.cs new file mode 100644 index 0000000..e8a9cbb --- /dev/null +++ b/netstandard/log4net.tests/CompatibilityExtensions.cs @@ -0,0 +1,19 @@ +using System; +using System.IO; +using System.Reflection; +using System.Threading; + +namespace log4net +{ + internal static class CompatibilityExtensions + { + public static void Close(this Mutex mutex) => mutex.Dispose(); + public static void Close(this Stream stream) => stream.Dispose(); + public static void Close(this StreamReader streamReader) => streamReader.Dispose(); + + public static ConstructorInfo GetConstructor(this Type type, BindingFlags bindingAttr, object binder, Type[] types, object[] modifiers) + { + return type.GetConstructor(types); + } + } +} diff --git a/netstandard/log4net.tests/ExpectedExceptionAttribute.cs b/netstandard/log4net.tests/ExpectedExceptionAttribute.cs new file mode 100644 index 0000000..454743a --- /dev/null +++ b/netstandard/log4net.tests/ExpectedExceptionAttribute.cs @@ -0,0 +1,66 @@ +// https://github.com/nunit/nunit-csharp-samples/blob/master/ExpectedExceptionExample/ExpectedExceptionAttribute.cs + +using System; +using NUnit.Framework.Interfaces; +using NUnit.Framework.Internal; +using NUnit.Framework.Internal.Commands; + +namespace NUnit.Framework +{ + /// + /// A simple ExpectedExceptionAttribute + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] + public class ExpectedExceptionAttribute : NUnitAttribute, IWrapTestMethod + { + private readonly Type _expectedExceptionType; + + public ExpectedExceptionAttribute(Type type) + { + _expectedExceptionType = type; + } + + public TestCommand Wrap(TestCommand command) + { + return new ExpectedExceptionCommand(command, _expectedExceptionType); + } + + private class ExpectedExceptionCommand : DelegatingTestCommand + { + private readonly Type _expectedType; + + public ExpectedExceptionCommand(TestCommand innerCommand, Type expectedType) + : base(innerCommand) + { + _expectedType = expectedType; + } + + public override TestResult Execute(TestExecutionContext context) + { + Type caughtType = null; + + try + { + innerCommand.Execute(context); + } + catch (Exception ex) + { + if (ex is NUnitException) + ex = ex.InnerException; + caughtType = ex.GetType(); + } + + if (caughtType == _expectedType) + context.CurrentResult.SetResult(ResultState.Success); + else if (caughtType != null) + context.CurrentResult.SetResult(ResultState.Failure, + string.Format("Expected {0} but got {1}", _expectedType.Name, caughtType.Name)); + else + context.CurrentResult.SetResult(ResultState.Failure, + string.Format("Expected {0} but no exception was thrown", _expectedType.Name)); + + return context.CurrentResult; + } + } + } +} diff --git a/netstandard/log4net.tests/log4net.tests.xproj b/netstandard/log4net.tests/log4net.tests.xproj new file mode 100644 index 0000000..a7218c6 --- /dev/null +++ b/netstandard/log4net.tests/log4net.tests.xproj @@ -0,0 +1,46 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 6a78d53b-c864-4316-aa00-f2ebfe975223 + log4net.tests + ..\artifacts\obj\$(MSBuildProjectName) + ..\..\build\netstandard\ + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2.0 + + + True + + + \ No newline at end of file diff --git a/netstandard/log4net.tests/project.json b/netstandard/log4net.tests/project.json new file mode 100644 index 0000000..4bbe2bb --- /dev/null +++ b/netstandard/log4net.tests/project.json @@ -0,0 +1,44 @@ +{ + "version": "1.0.0-*", + "buildOptions": { + "compile": [ + "../../tests/src/*.cs", + "../../tests/src/Appender/AppenderCollectionTest.cs", + "../../tests/src/Appender/BufferingAppenderTest.cs", + "../../tests/src/Appender/CountingAppender.cs", + "../../tests/src/Appender/MemoryAppenderTest.cs", + "../../tests/src/Appender/RollingFileAppenderTest.cs", + "../../tests/src/Appender/SmtpPickupDirAppenderTest.cs", + "../../tests/src/Appender/StringAppender.cs", + "../../tests/src/Appender/TraceAppenderTest.cs", + "../../tests/src/Context/ThreadContextTest.cs", + "../../tests/src/Core/**/*.cs", + "../../tests/src/DateFormatter/**/*.cs", + "../../tests/src/Hierarchy/**/*.cs", + "../../tests/src/Layout/**/*.cs", + "../../tests/src/LoggerRepository/**/*.cs", + "../../tests/src/Util/CyclicBufferTest.cs", + "../../tests/src/Util/LogLogTest.cs", + "../../tests/src/Util/PatternConverterTest.cs", + "../../tests/src/Util/RandomStringPatternConverterTest.cs", + "../../tests/src/Util/SystemInfoTest.cs", + "../../tests/src/Util/TransformTest.cs" + ], + "define": [ "NETSTANDARD1_3" ] + }, + "frameworks": { + "netcoreapp1.0": { + "dependencies": { + "Microsoft.NETCore.App": { + "version": "1.0.0", + "type": "platform" + }, + "dotnet-test-nunit": "3.4.0-beta-1", + "log4net": "3.0.0", + "NUnit": "3.4.1" + }, + "imports": [ "portable-net45+win8" ] + } + }, + "testRunner": "nunit" +} diff --git a/netstandard/log4net/CompatibilityExtensions.cs b/netstandard/log4net/CompatibilityExtensions.cs new file mode 100644 index 0000000..6486f2a --- /dev/null +++ b/netstandard/log4net/CompatibilityExtensions.cs @@ -0,0 +1,34 @@ +#if NETSTANDARD1_3 + +using System; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Reflection; +using System.Threading; +using System.Xml; + +namespace log4net +{ + internal static class CompatibilityExtensions + { + public static void Close(this Mutex mutex) => mutex.Dispose(); + public static void Close(this Socket socket) => socket.Dispose(); + public static void Close(this Stream stream) => stream.Dispose(); + public static void Close(this StreamWriter streamWriter) => streamWriter.Dispose(); + public static void Close(this UdpClient client) => client.Dispose(); + public static void Close(this WebResponse response) => response.Dispose(); + public static void Close(this XmlWriter xmlWriter) => xmlWriter.Dispose(); + + public static Attribute[] GetCustomAttributes(this Type type, Type other, bool inherit) => type.GetTypeInfo().GetCustomAttributes(other, inherit).ToArray(); + public static bool IsAssignableFrom(this Type type, Type other) => type.GetTypeInfo().IsAssignableFrom(other.GetTypeInfo()); + public static bool IsSubclassOf(this Type type, Type t) => type.GetTypeInfo().IsSubclassOf(t); + + public static string ToLower(this string s, CultureInfo cultureInfo) => cultureInfo.TextInfo.ToLower(s); + public static string ToUpper(this string s, CultureInfo cultureInfo) => cultureInfo.TextInfo.ToUpper(s); + } +} + +#endif diff --git a/netstandard/log4net/log4net.xproj b/netstandard/log4net/log4net.xproj new file mode 100644 index 0000000..a58f384 --- /dev/null +++ b/netstandard/log4net/log4net.xproj @@ -0,0 +1,244 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 00764202-b361-4bc8-a1b9-01d87f9d2d51 + log4net + ..\artifacts\obj\$(MSBuildProjectName) + ..\..\build\netstandard\ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2.0 + + + \ No newline at end of file diff --git a/netstandard/log4net/project.json b/netstandard/log4net/project.json new file mode 100644 index 0000000..a597f81 --- /dev/null +++ b/netstandard/log4net/project.json @@ -0,0 +1,94 @@ +{ + "name": "log4net", + "version": "3.0.0", + "frameworks": { + "netstandard1.3": { + "buildOptions": { + "compile": { + "include": [ "*.cs", "../../src/**/*.cs" ], + "exclude": [ + "../../src/Appender/AdoNetAppender.cs", + "../../src/Appender/AspNetTraceAppender.cs", + "../../src/Appender/ColoredConsoleAppender.cs", + "../../src/Appender/EventLogAppender.cs", + "../../src/Appender/NetSendAppender.cs", + "../../src/Appender/RemotingAppender.cs", + "../../src/Appender/SmtpAppender.cs", + "../../src/LogicalThreadContext.cs", + "../../src/Config/DOMConfigurator.cs", + "../../src/Config/DOMConfiguratorAttribute.cs", + "../../src/Config/Log4NetConfigurationSectionHandler.cs", + "../../src/Layout/Pattern/AspNetCachePatternConverter.cs", + "../../src/Layout/Pattern/AspNetContextPatternConverter.cs", + "../../src/Layout/Pattern/AspNetPatternConverter.cs", + "../../src/Layout/Pattern/AspNetRequestPatternConverter.cs", + "../../src/Layout/Pattern/AspNetSessionPatternConverter.cs", + "../../src/Layout/Pattern/StackTraceDetailPatternConverter.cs", + "../../src/Layout/Pattern/StackTracePatternConverter.cs", + "../../src/Plugin/RemoteLoggingServerPlugin.cs", + "../../src/Util/PatternStringConverters/EnvironmentFolderPathPatternConverter.cs", + "../../src/Util/LogicalThreadContextProperties.cs", + "../../src/Util/LogicalThreadContextStacks.cs", + "../../src/Util/NativeError.cs", + "../../src/Util/WindowsSecurityContext.cs" + ] + }, + "define": [ "HAS_READERWRITERLOCKSLIM", "NETSTANDARD1_3" ] + }, + "dependencies": { + "System.AppContext": "4.1.0", + "System.Collections.NonGeneric": "4.0.1", + "System.Console": "4.0.0", + "System.Diagnostics.Debug": "4.0.11", + "System.Diagnostics.Process": "4.1.0", + "System.Diagnostics.StackTrace": "4.0.1", + "System.Diagnostics.TraceSource": "4.0.0", + "System.IO.FileSystem": "4.0.1", + "System.IO.FileSystem.Watcher": "4.0.0", + "System.Linq": "4.1.0", + "System.Net.NameResolution": "4.0.0", + "System.Net.Requests": "4.0.11", + "System.Net.Sockets": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.InteropServices": "4.1.0", + "System.Runtime.InteropServices.RuntimeInformation": "4.0.0", + "System.Runtime.Serialization.Formatters": "4.0.0-rc3-24212-01", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Thread": "4.0.0", + "System.Threading.Timer": "4.0.1", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XmlDocument": "4.0.1" + } + }, + "net40": { + "buildOptions": { + "compile": "../../src/**/*.cs", + "define": [ "TRACE", "STRONG", "NET", "NET_2_0", "NET_4_0" ] + }, + "frameworkAssemblies": { + "System": { "type": "build" }, + "System.Configuration": { "type": "build" }, + "System.Data": { "type": "build" }, + "System.Web": { "type": "build" }, + "System.Xml": { "type": "build" } + } + }, + "net45": { + "buildOptions": { + "compile": "../../src/**/*.cs", + "define": [ "TRACE", "STRONG", "NET", "NET_2_0", "NET_4_0", "NET_4_5" ] + }, + "frameworkAssemblies": { + "System": { "type": "build" }, + "System.Configuration": { "type": "build" }, + "System.Data": { "type": "build" }, + "System.Web": { "type": "build" }, + "System.Xml": { "type": "build" } + } + } + } +} diff --git a/src/Appender/AnsiColorTerminalAppender.cs b/src/Appender/AnsiColorTerminalAppender.cs index 3ad375f..9f7018f 100644 --- a/src/Appender/AnsiColorTerminalAppender.cs +++ b/src/Appender/AnsiColorTerminalAppender.cs @@ -252,8 +252,11 @@ namespace log4net.Appender set { string trimmedTargetName = value.Trim(); - - if (string.Compare(ConsoleError, trimmedTargetName, true, CultureInfo.InvariantCulture) == 0) +#if NETSTANDARD1_3 + if (CultureInfo.InvariantCulture.CompareInfo.Compare(ConsoleError, trimmedTargetName, CompareOptions.IgnoreCase) == 0) +#else + if (string.Compare(ConsoleError, trimmedTargetName, true, CultureInfo.InvariantCulture) == 0) +#endif { m_writeToErrorStream = true; } diff --git a/src/Appender/AppenderCollection.cs b/src/Appender/AppenderCollection.cs index 53ea990..21987b8 100644 --- a/src/Appender/AppenderCollection.cs +++ b/src/Appender/AppenderCollection.cs @@ -26,7 +26,10 @@ namespace log4net.Appender /// A strongly-typed collection of objects. /// /// Nicko Cadell - public class AppenderCollection : ICollection, IList, IEnumerable, ICloneable + public class AppenderCollection : ICollection, IList, IEnumerable +#if !NETSTANDARD1_3 + , ICloneable +#endif { #region Interfaces /// @@ -216,10 +219,10 @@ namespace log4net.Appender /// /// Gets a value indicating whether access to the collection is synchronized (thread-safe). /// - /// true if access to the ICollection is synchronized (thread-safe); otherwise, false. + /// false, because the backing type is an array, which is never thread-safe. public virtual bool IsSynchronized { - get { return m_array.IsSynchronized; } + get { return false; } } /// @@ -227,7 +230,7 @@ namespace log4net.Appender /// public virtual object SyncRoot { - get { return m_array.SyncRoot; } + get { return m_array; } } #endregion diff --git a/src/Appender/AppenderSkeleton.cs b/src/Appender/AppenderSkeleton.cs index bc11683..a3415e3 100644 --- a/src/Appender/AppenderSkeleton.cs +++ b/src/Appender/AppenderSkeleton.cs @@ -321,7 +321,7 @@ namespace log4net.Appender { ErrorHandler.Error("Failed in DoAppend", ex); } -#if !MONO && !NET_2_0 +#if !MONO && !NET_2_0 && !NETSTANDARD1_3 // on .NET 2.0 (and higher) and Mono (all profiles), // exceptions that do not derive from System.Exception will be // wrapped in a RuntimeWrappedException by the runtime, and as @@ -428,7 +428,7 @@ namespace log4net.Appender { ErrorHandler.Error("Failed in Bulk DoAppend", ex); } -#if !MONO && !NET_2_0 +#if !MONO && !NET_2_0 && !NETSTANDARD1_3 // on .NET 2.0 (and higher) and Mono (all profiles), // exceptions that do not derive from System.Exception will be // wrapped in a RuntimeWrappedException by the runtime, and as diff --git a/src/Appender/ConsoleAppender.cs b/src/Appender/ConsoleAppender.cs index 84ad172..d037f80 100644 --- a/src/Appender/ConsoleAppender.cs +++ b/src/Appender/ConsoleAppender.cs @@ -120,8 +120,11 @@ namespace log4net.Appender set { string v = value.Trim(); - - if (string.Compare(ConsoleError, v, true, CultureInfo.InvariantCulture) == 0) +#if NETSTANDARD1_3 + if (CultureInfo.InvariantCulture.CompareInfo.Compare(ConsoleError, v, CompareOptions.IgnoreCase) == 0) +#else + if (string.Compare(ConsoleError, v, true, CultureInfo.InvariantCulture) == 0) +#endif { m_writeToErrorStream = true; } diff --git a/src/Appender/DebugAppender.cs b/src/Appender/DebugAppender.cs index c2c9226..d3cea92 100644 --- a/src/Appender/DebugAppender.cs +++ b/src/Appender/DebugAppender.cs @@ -121,7 +121,7 @@ namespace log4net.Appender // Write the string to the Debug system // System.Diagnostics.Debug.Write(RenderLoggingEvent(loggingEvent), loggingEvent.LoggerName); - +#if !NETSTANDARD1_3 // // Flush the Debug system if needed // @@ -129,6 +129,7 @@ namespace log4net.Appender { System.Diagnostics.Debug.Flush(); } +#endif } /// diff --git a/src/Appender/FileAppender.cs b/src/Appender/FileAppender.cs index 65c4798..9ae07e4 100644 --- a/src/Appender/FileAppender.cs +++ b/src/Appender/FileAppender.cs @@ -145,7 +145,9 @@ namespace log4net.Appender private Stream m_realStream = null; private LockingModelBase m_lockingModel = null; +#if !NETSTANDARD1_3 // only used in unavailable Stream overrides private int m_readTotal = -1; +#endif private int m_lockLevel = 0; public LockingStream(LockingModelBase locking) @@ -160,6 +162,13 @@ namespace log4net.Appender #region Override Implementation of Stream +#if NETSTANDARD1_3 + protected override void Dispose(bool disposing) + { + m_lockingModel.CloseFile(); + base.Dispose(disposing); + } +#else // Methods public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { @@ -194,6 +203,8 @@ namespace log4net.Appender { //No-op, it has already been handled } +#endif + public override void Flush() { AssertLocked(); @@ -219,7 +230,11 @@ namespace log4net.Appender } void IDisposable.Dispose() { +#if NETSTANDARD1_3 + Dispose(true); +#else Close(); +#endif } public override void Write(byte[] buffer, int offset, int count) { @@ -708,7 +723,7 @@ namespace log4net.Appender /// - and . /// /// -#if NET_4_0 || MONO_4_0 +#if NET_4_0 || MONO_4_0 || NETSTANDARD1_3 [System.Security.SecuritySafeCritical] #endif public override void OpenFile(string filename, bool append, Encoding encoding) @@ -829,7 +844,7 @@ namespace log4net.Appender { if (m_mutex != null) { - m_mutex.Close(); + m_mutex.Dispose(); m_mutex = null; } else @@ -1431,7 +1446,11 @@ namespace log4net.Appender /// /// The encoding to use for the file stream. /// +#if NETSTANDARD1_3 + private Encoding m_encoding = Encoding.Unicode; +#else private Encoding m_encoding = Encoding.Default; +#endif /// /// The security context to use for privileged calls diff --git a/src/Appender/LocalSyslogAppender.cs b/src/Appender/LocalSyslogAppender.cs index e31b1ca..a21d7ed 100644 --- a/src/Appender/LocalSyslogAppender.cs +++ b/src/Appender/LocalSyslogAppender.cs @@ -337,7 +337,7 @@ namespace log4net.Appender /// must be called again. /// /// -#if NET_4_0 || MONO_4_0 +#if NET_4_0 || MONO_4_0 || NETSTANDARD1_3 [System.Security.SecuritySafeCritical] #endif public override void ActivateOptions() @@ -378,10 +378,12 @@ namespace log4net.Appender /// The format of the output will depend on the appender's layout. /// /// -#if NET_4_0 || MONO_4_0 +#if NET_4_0 || MONO_4_0 || NETSTANDARD1_3 [System.Security.SecuritySafeCritical] #endif +#if !NETSTANDARD1_3 [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] +#endif protected override void Append(LoggingEvent loggingEvent) { int priority = GeneratePriority(m_facility, GetSeverity(loggingEvent.Level)); @@ -400,7 +402,7 @@ namespace log4net.Appender /// Close the syslog when the appender is closed /// /// -#if NET_4_0 || MONO_4_0 +#if NET_4_0 || MONO_4_0 || NETSTANDARD1_3 [System.Security.SecuritySafeCritical] #endif protected override void OnClose() diff --git a/src/Appender/ManagedColoredConsoleAppender.cs b/src/Appender/ManagedColoredConsoleAppender.cs index a1a06ac..80b0fc4 100644 --- a/src/Appender/ManagedColoredConsoleAppender.cs +++ b/src/Appender/ManagedColoredConsoleAppender.cs @@ -134,8 +134,12 @@ namespace log4net.Appender set { string v = value.Trim(); - - if (string.Compare(ConsoleError, v, true, CultureInfo.InvariantCulture) == 0) + +#if NETSTANDARD1_3 + if (CultureInfo.InvariantCulture.CompareInfo.Compare(ConsoleError, v, CompareOptions.IgnoreCase) == 0) +#else + if (string.Compare(ConsoleError, v, true, CultureInfo.InvariantCulture) == 0) +#endif { m_writeToErrorStream = true; } diff --git a/src/Appender/NetSendAppender.cs b/src/Appender/NetSendAppender.cs index f7fa627..ae8b7a9 100644 --- a/src/Appender/NetSendAppender.cs +++ b/src/Appender/NetSendAppender.cs @@ -304,10 +304,12 @@ namespace log4net.Appender /// Sends the event using a network message. /// /// -#if NET_4_0 || MONO_4_0 +#if NET_4_0 || MONO_4_0 || NETSTANDARD1_3 [System.Security.SecuritySafeCritical] #endif +#if !NETSTANDARD1_3 [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] +#endif protected override void Append(LoggingEvent loggingEvent) { NativeError nativeError = null; diff --git a/src/Appender/OutputDebugStringAppender.cs b/src/Appender/OutputDebugStringAppender.cs index 2242afb..cd48689 100644 --- a/src/Appender/OutputDebugStringAppender.cs +++ b/src/Appender/OutputDebugStringAppender.cs @@ -75,13 +75,20 @@ namespace log4net.Appender /// Write the logging event to the output debug string API /// /// -#if NET_4_0 || MONO_4_0 +#if NET_4_0 || MONO_4_0 || NETSTANDARD1_3 [System.Security.SecuritySafeCritical] #elif !NETCF [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] #endif override protected void Append(LoggingEvent loggingEvent) { +#if NETSTANDARD1_3 + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + throw new System.PlatformNotSupportedException("OutputDebugString is only available on Windows"); + } +#endif + OutputDebugString(RenderLoggingEvent(loggingEvent)); } diff --git a/src/Appender/RemoteSyslogAppender.cs b/src/Appender/RemoteSyslogAppender.cs index 2f23875..b7a8c66 100644 --- a/src/Appender/RemoteSyslogAppender.cs +++ b/src/Appender/RemoteSyslogAppender.cs @@ -409,7 +409,11 @@ namespace log4net.Appender // Grab as a byte array buffer = this.Encoding.GetBytes(builder.ToString()); +#if NETSTANDARD1_3 + Client.SendAsync(buffer, buffer.Length, RemoteEndPoint).Wait(); +#else this.Client.Send(buffer, buffer.Length, this.RemoteEndPoint); +#endif } } catch (Exception e) diff --git a/src/Appender/TelnetAppender.cs b/src/Appender/TelnetAppender.cs index fc02801..4d768a2 100644 --- a/src/Appender/TelnetAppender.cs +++ b/src/Appender/TelnetAppender.cs @@ -25,7 +25,9 @@ using System.Net.Sockets; using System.Text; using System.IO; using System.Threading; - +#if NETSTANDARD1_3 +using System.Threading.Tasks; +#endif using log4net.Layout; using log4net.Core; using log4net.Util; @@ -336,8 +338,17 @@ namespace log4net.Appender m_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); m_serverSocket.Bind(new IPEndPoint(IPAddress.Any, port)); - m_serverSocket.Listen(5); + m_serverSocket.Listen(5); + AcceptConnection(); + } + + private void AcceptConnection() + { +#if NETSTANDARD1_3 + m_serverSocket.AcceptAsync().ContinueWith(OnConnect, TaskScheduler.Default); +#else m_serverSocket.BeginAccept(new AsyncCallback(OnConnect), null); +#endif } /// @@ -419,6 +430,10 @@ namespace log4net.Appender } } + +#if NETSTANDARD1_3 + private void OnConnect(Task acceptTask) +#else /// /// Callback used to accept a connection on the server socket /// @@ -430,12 +445,16 @@ namespace log4net.Appender /// /// private void OnConnect(IAsyncResult asyncResult) +#endif { try { +#if NETSTANDARD1_3 + Socket socket = acceptTask.GetAwaiter().GetResult(); +#else // Block until a client connects Socket socket = m_serverSocket.EndAccept(asyncResult); - +#endif LogLog.Debug(declaringType, "Accepting connection from ["+socket.RemoteEndPoint.ToString()+"]"); SocketClient client = new SocketClient(socket); @@ -465,7 +484,7 @@ namespace log4net.Appender { if (m_serverSocket != null) { - m_serverSocket.BeginAccept(new AsyncCallback(OnConnect), null); + AcceptConnection(); } } } diff --git a/src/Appender/UdpAppender.cs b/src/Appender/UdpAppender.cs index ce5342b..55770ff 100644 --- a/src/Appender/UdpAppender.cs +++ b/src/Appender/UdpAppender.cs @@ -403,7 +403,11 @@ namespace log4net.Appender try { Byte [] buffer = m_encoding.GetBytes(RenderLoggingEvent(loggingEvent).ToCharArray()); +#if NETSTANDARD1_3 + Client.SendAsync(buffer, buffer.Length, RemoteEndPoint).Wait(); +#else this.Client.Send(buffer, buffer.Length, this.RemoteEndPoint); +#endif } catch (Exception ex) { @@ -536,7 +540,11 @@ namespace log4net.Appender /// /// The encoding to use for the packet. /// +#if NETSTANDARD1_3 + private Encoding m_encoding = Encoding.Unicode; +#else private Encoding m_encoding = Encoding.Default; +#endif #endregion Private Instance Fields } diff --git a/src/AssemblyInfo.cs b/src/AssemblyInfo.cs index dd01f89..d957034 100644 --- a/src/AssemblyInfo.cs +++ b/src/AssemblyInfo.cs @@ -91,6 +91,8 @@ using System.Runtime.CompilerServices; [assembly: AssemblyTitle("Apache log4net for CLI Compatible Frameworks")] #elif (NET) [assembly: AssemblyTitle("Apache log4net for .NET Framework")] +#elif (NETSTANDARD1_3) +[assembly: AssemblyTitle("Apache log4net for .NET Core")] #elif (NETCF) [assembly: AssemblyTitle("Apache log4net for .NET Compact Framework")] #elif (MONO) diff --git a/src/Config/BasicConfigurator.cs b/src/Config/BasicConfigurator.cs index 8d617b4..1f89ad2 100644 --- a/src/Config/BasicConfigurator.cs +++ b/src/Config/BasicConfigurator.cs @@ -82,6 +82,7 @@ namespace log4net.Config #region Public Static Methods +#if !NETSTANDARD1_3 /// /// Initializes the log4net system with a default configuration. /// @@ -96,22 +97,8 @@ namespace log4net.Config /// static public ICollection Configure() { - return BasicConfigurator.Configure(LogManager.GetRepository(Assembly.GetCallingAssembly())); - } - - /// - /// 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. - /// - /// - static public ICollection Configure(IAppender appender) - { - return Configure(new IAppender[] { appender }); - } + return BasicConfigurator.Configure(LogManager.GetRepository(Assembly.GetCallingAssembly())); + } /// /// Initializes the log4net system using the specified appenders. @@ -138,6 +125,21 @@ namespace log4net.Config 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. + /// + /// + static public ICollection Configure(IAppender appender) + { + return Configure(new IAppender[] { appender }); + } +#endif // !NETSTANDARD1_3 + /// /// Initializes the with a default configuration. /// diff --git a/src/Config/PluginAttribute.cs b/src/Config/PluginAttribute.cs index 3533b25..eb91906 100644 --- a/src/Config/PluginAttribute.cs +++ b/src/Config/PluginAttribute.cs @@ -49,6 +49,7 @@ namespace log4net.Config { #region Public Instance Constructors +#if !NETSTANDARD1_3 // Excluded because GetCallingAssembly() is not available in CoreFX (https://github.com/dotnet/corefx/issues/2221). /// /// Initializes a new instance of the class /// with the specified type. @@ -66,6 +67,7 @@ namespace log4net.Config { m_typeName = typeName; } +#endif /// /// Initializes a new instance of the class @@ -140,12 +142,13 @@ namespace log4net.Config public IPlugin CreatePlugin() { Type pluginType = m_type; +#if !NETSTANDARD1_3 if (m_type == null) { // Get the plugin object type from the string type name pluginType = SystemInfo.GetTypeFromString(m_typeName, true, true); } - +#endif // Check that the type is a plugin if (!(typeof(IPlugin).IsAssignableFrom(pluginType))) { diff --git a/src/Config/XmlConfigurator.cs b/src/Config/XmlConfigurator.cs index 03bdf59..5b11d98 100644 --- a/src/Config/XmlConfigurator.cs +++ b/src/Config/XmlConfigurator.cs @@ -57,47 +57,6 @@ namespace log4net.Config #region Configure static methods #if !NETCF - /// - /// Automatically configures the log4net system based on the - /// application's configuration settings. - /// - /// - /// - /// Each application has a configuration file. This has the - /// same name as the application with '.config' appended. - /// This file is XML and calling this function prompts the - /// configurator to look in that file for a section called - /// log4net that contains the configuration data. - /// - /// - /// To use this method to configure log4net you must specify - /// the section - /// handler for the log4net configuration section. See the - /// for an example. - /// - /// - /// -#else - /// - /// Automatically configures the log4net system based on the - /// application's configuration settings. - /// - /// - /// - /// Each application has a configuration file. This has the - /// same name as the application with '.config' appended. - /// This file is XML and calling this function prompts the - /// configurator to look in that file for a section called - /// log4net that contains the configuration data. - /// - /// -#endif - static public ICollection Configure() - { - return Configure(LogManager.GetRepository(Assembly.GetCallingAssembly())); - } - -#if !NETCF /// /// Automatically configures the using settings /// stored in the application's configuration file. @@ -162,7 +121,7 @@ namespace log4net.Config LogLog.Debug(declaringType, "Application config file location unknown"); } -#if NETCF +#if NETCF || NETSTANDARD1_3 // No config file reading stuff. Just go straight for the file Configure(repository, new FileInfo(SystemInfo.ConfigurationFileLocation)); #else @@ -202,50 +161,66 @@ namespace log4net.Config #endif } +#if !NETSTANDARD1_3 // Excluded because GetCallingAssembly() is not available in CoreFX (https://github.com/dotnet/corefx/issues/2221). +#if !NETCF /// - /// Configures log4net using a log4net element + /// Automatically configures the log4net system based on the + /// application's configuration settings. /// /// /// - /// Loads the log4net configuration from the XML element - /// supplied as . + /// Each application has a configuration file. This has the + /// same name as the application with '.config' appended. + /// This file is XML and calling this function prompts the + /// configurator to look in that file for a section called + /// log4net that contains the configuration data. + /// + /// + /// To use this method to configure log4net you must specify + /// the section + /// handler for the log4net configuration section. See the + /// for an example. /// /// - /// The element to parse. - static public ICollection Configure(XmlElement element) - { - ArrayList configurationMessages = new ArrayList(); - - ILoggerRepository repository = LogManager.GetRepository(Assembly.GetCallingAssembly()); - - using (new LogLog.LogReceivedAdapter(configurationMessages)) - { - InternalConfigureFromXml(repository, element); - } - - repository.ConfigurationMessages = configurationMessages; - - return configurationMessages; - } + /// +#else + /// + /// Automatically configures the log4net system based on the + /// application's configuration settings. + /// + /// + /// + /// Each application has a configuration file. This has the + /// same name as the application with '.config' appended. + /// This file is XML and calling this function prompts the + /// configurator to look in that file for a section called + /// log4net that contains the configuration data. + /// + /// +#endif + static public ICollection Configure() + { + return Configure(LogManager.GetRepository(Assembly.GetCallingAssembly())); + } /// - /// Configures the using the specified XML - /// element. + /// Configures log4net using a log4net element /// /// + /// /// Loads the log4net configuration from the XML element /// supplied as . + /// /// - /// The repository to configure. /// The element to parse. - static public ICollection Configure(ILoggerRepository repository, XmlElement element) + static public ICollection Configure(XmlElement element) { ArrayList configurationMessages = new ArrayList(); + ILoggerRepository repository = LogManager.GetRepository(Assembly.GetCallingAssembly()); + using (new LogLog.LogReceivedAdapter(configurationMessages)) { - LogLog.Debug(declaringType, "configuring repository [" + repository.Name + "] using XML element"); - InternalConfigureFromXml(repository, element); } @@ -372,7 +347,6 @@ namespace log4net.Config ArrayList configurationMessages = new ArrayList(); ILoggerRepository repository = LogManager.GetRepository(Assembly.GetCallingAssembly()); - using (new LogLog.LogReceivedAdapter(configurationMessages)) { InternalConfigure(repository, configUri); @@ -402,7 +376,6 @@ namespace log4net.Config ArrayList configurationMessages = new ArrayList(); ILoggerRepository repository = LogManager.GetRepository(Assembly.GetCallingAssembly()); - using (new LogLog.LogReceivedAdapter(configurationMessages)) { InternalConfigure(repository, configStream); @@ -412,9 +385,35 @@ namespace log4net.Config return configurationMessages; } +#endif // !NETSTANDARD1_3 -#if !NETCF + /// + /// Configures the using the specified XML + /// element. + /// + /// + /// Loads the log4net configuration from the XML element + /// supplied as . + /// + /// The repository to configure. + /// The element to parse. + static public ICollection Configure(ILoggerRepository repository, XmlElement element) + { + ArrayList configurationMessages = new ArrayList(); + using (new LogLog.LogReceivedAdapter(configurationMessages)) + { + LogLog.Debug(declaringType, "configuring repository [" + repository.Name + "] using XML element"); + + InternalConfigureFromXml(repository, element); + } + + repository.ConfigurationMessages = configurationMessages; + + return configurationMessages; + } + +#if !NETCF /// /// Configures the using the specified configuration /// file. @@ -652,7 +651,11 @@ namespace log4net.Config #endif try { +#if NETSTANDARD1_3 + WebResponse response = configRequest.GetResponseAsync().GetAwaiter().GetResult(); +#else WebResponse response = configRequest.GetResponse(); +#endif if (response != null) { try @@ -725,12 +728,14 @@ namespace log4net.Config #if (NETCF) // Create a text reader for the file stream XmlTextReader xmlReader = new XmlTextReader(configStream); -#elif NET_2_0 +#elif NET_2_0 || NETSTANDARD1_3 // Allow the DTD to specify entity includes XmlReaderSettings settings = new XmlReaderSettings(); // .NET 4.0 warning CS0618: 'System.Xml.XmlReaderSettings.ProhibitDtd' // is obsolete: 'Use XmlReaderSettings.DtdProcessing property instead.' -#if !NET_4_0 && !MONO_4_0 +#if NETSTANDARD1_3 // TODO DtdProcessing.Parse not yet available (https://github.com/dotnet/corefx/issues/4376) + settings.DtdProcessing = DtdProcessing.Ignore; +#elif !NET_4_0 && !MONO_4_0 settings.ProhibitDtd = false; #else settings.DtdProcessing = DtdProcessing.Parse; @@ -786,7 +791,7 @@ namespace log4net.Config #region ConfigureAndWatch static methods #if (!NETCF && !SSCLI) - +#if !NETSTANDARD1_3 // Excluded because GetCallingAssembly() is not available in CoreFX (https://github.com/dotnet/corefx/issues/2221). /// /// Configures log4net using the file specified, monitors the file for changes /// and reloads the configuration if a change is detected. @@ -823,6 +828,7 @@ namespace log4net.Config return configurationMessages; } +#endif // !NETSTANDARD1_3 /// /// Configures the using the file specified, @@ -963,7 +969,7 @@ namespace log4net.Config /// Initializes a new instance of the class. /// /// -#if NET_4_0 || MONO_4_0 +#if NET_4_0 || MONO_4_0 || NETSTANDARD1_3 [System.Security.SecuritySafeCritical] #endif public ConfigureAndWatchHandler(ILoggerRepository repository, FileInfo configFile) @@ -1043,7 +1049,7 @@ namespace log4net.Config /// /// Release the handles held by the watcher and timer. /// -#if NET_4_0 || MONO_4_0 +#if NET_4_0 || MONO_4_0 || NETSTANDARD1_3 [System.Security.SecuritySafeCritical] #endif public void Dispose() diff --git a/src/Core/DefaultRepositorySelector.cs b/src/Core/DefaultRepositorySelector.cs index a92a979..970f296 100644 --- a/src/Core/DefaultRepositorySelector.cs +++ b/src/Core/DefaultRepositorySelector.cs @@ -23,7 +23,11 @@ using System; using System.Collections; +#if !NETSTANDARD1_3 using System.Configuration; +#else +using System.Linq; +#endif using System.IO; using System.Reflection; @@ -583,7 +587,11 @@ namespace log4net.Core try { // Look for the RepositoryAttribute on the assembly +#if NETSTANDARD1_3 + object[] repositoryAttributes = assembly.GetCustomAttributes(typeof(log4net.Config.RepositoryAttribute)).ToArray(); +#else object[] repositoryAttributes = Attribute.GetCustomAttributes(assembly, typeof(log4net.Config.RepositoryAttribute), false); +#endif if (repositoryAttributes == null || repositoryAttributes.Length == 0) { // This is not a problem, but its nice to know what is going on. @@ -655,7 +663,11 @@ namespace log4net.Core } // Look for the Configurator attributes (e.g. XmlConfiguratorAttribute) on the assembly +#if NETSTANDARD1_3 + object[] configAttributes = assembly.GetCustomAttributes(typeof(log4net.Config.ConfiguratorAttribute)).ToArray(); +#else object[] configAttributes = Attribute.GetCustomAttributes(assembly, typeof(log4net.Config.ConfiguratorAttribute), false); +#endif if (configAttributes != null && configAttributes.Length > 0) { // Sort the ConfiguratorAttributes in priority order @@ -705,7 +717,7 @@ namespace log4net.Core // Determine whether to watch the file or not based on an app setting value: bool watchRepositoryConfigFile = false; -#if NET_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0 +#if NET_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0 || NETSTANDARD1_3 Boolean.TryParse(SystemInfo.GetAppSetting("log4net.Config.Watch"), out watchRepositoryConfigFile); #else { @@ -803,7 +815,11 @@ namespace log4net.Core } // Look for the PluginAttribute on the assembly +#if NETSTANDARD1_3 + object[] configAttributes = assembly.GetCustomAttributes(typeof(log4net.Config.PluginAttribute)).ToArray(); +#else object[] configAttributes = Attribute.GetCustomAttributes(assembly, typeof(log4net.Config.PluginAttribute), false); +#endif if (configAttributes != null && configAttributes.Length > 0) { foreach(log4net.Plugin.IPluginFactory configAttr in configAttributes) @@ -843,7 +859,11 @@ namespace log4net.Core } // Look for the AliasRepositoryAttribute on the assembly +#if NETSTANDARD1_3 + object[] configAttributes = assembly.GetCustomAttributes(typeof(log4net.Config.AliasRepositoryAttribute)).ToArray(); +#else object[] configAttributes = Attribute.GetCustomAttributes(assembly, typeof(log4net.Config.AliasRepositoryAttribute), false); +#endif if (configAttributes != null && configAttributes.Length > 0) { foreach(log4net.Config.AliasRepositoryAttribute configAttr in configAttributes) diff --git a/src/Core/ExceptionEvaluator.cs b/src/Core/ExceptionEvaluator.cs index 1b462f0..967c37e 100644 --- a/src/Core/ExceptionEvaluator.cs +++ b/src/Core/ExceptionEvaluator.cs @@ -18,6 +18,9 @@ #endregion using System; +#if NETSTANDARD1_3 +using System.Reflection; +#endif namespace log4net.Core { diff --git a/src/Core/Level.cs b/src/Core/Level.cs index 40a6ad2..713918d 100644 --- a/src/Core/Level.cs +++ b/src/Core/Level.cs @@ -111,7 +111,11 @@ namespace log4net.Core } m_levelValue = level; +#if NETSTANDARD1_3 + m_levelName = levelName; +#else m_levelName = string.Intern(levelName); +#endif m_levelDisplayName = displayName; } diff --git a/src/Core/LevelCollection.cs b/src/Core/LevelCollection.cs index 1287ac0..d51bd0d 100644 --- a/src/Core/LevelCollection.cs +++ b/src/Core/LevelCollection.cs @@ -26,7 +26,10 @@ namespace log4net.Core /// A strongly-typed collection of objects. /// /// Nicko Cadell - public class LevelCollection : ICollection, IList, IEnumerable, ICloneable + public class LevelCollection : ICollection, IList, IEnumerable +#if !NETSTANDARD1_3 + , ICloneable +#endif { #region Interfaces @@ -205,10 +208,10 @@ namespace log4net.Core /// /// Gets a value indicating whether access to the collection is synchronized (thread-safe). /// - /// true if access to the ICollection is synchronized (thread-safe); otherwise, false. + /// false, because the backing type is an array, which is never thread-safe. public virtual bool IsSynchronized { - get { return m_array.IsSynchronized; } + get { return false; } } /// @@ -216,7 +219,7 @@ namespace log4net.Core /// public virtual object SyncRoot { - get { return m_array.SyncRoot; } + get { return m_array; } } #endregion diff --git a/src/Core/LocationInfo.cs b/src/Core/LocationInfo.cs index 8f96c4e..55fd8ad 100644 --- a/src/Core/LocationInfo.cs +++ b/src/Core/LocationInfo.cs @@ -83,7 +83,7 @@ namespace log4net.Core m_methodName = NA; m_fullInfo = NA; -#if !NETCF +#if !(NETCF || NETSTANDARD1_3) // StackTrace isn't fully implemented for NETSTANDARD1_3 https://github.com/dotnet/corefx/issues/1797 if (callerStackBoundaryDeclaringType != null) { try @@ -271,7 +271,7 @@ namespace log4net.Core get { return m_fullInfo; } } -#if !NETCF +#if !(NETCF || NETSTANDARD1_3) /// /// Gets the stack frames from the stack trace of the caller making the log request /// @@ -290,7 +290,7 @@ namespace log4net.Core private readonly string m_lineNumber; private readonly string m_methodName; private readonly string m_fullInfo; -#if !NETCF +#if !(NETCF || NETSTANDARD1_3) private readonly StackFrameItem[] m_stackFrames; #endif diff --git a/src/Core/LogException.cs b/src/Core/LogException.cs index 499979c..e7f243d 100644 --- a/src/Core/LogException.cs +++ b/src/Core/LogException.cs @@ -39,7 +39,11 @@ namespace log4net.Core #if !NETCF [Serializable] #endif +#if NETSTANDARD1_3 + public class LogException : Exception +#else public class LogException : ApplicationException +#endif { #region Public Instance Constructors @@ -88,7 +92,7 @@ namespace log4net.Core #region Protected Instance Constructors -#if !NETCF +#if !(NETCF || NETSTANDARD1_3) /// /// Serialization constructor /// diff --git a/src/Core/LoggerManager.cs b/src/Core/LoggerManager.cs index 9a3afed..8ffaad2 100644 --- a/src/Core/LoggerManager.cs +++ b/src/Core/LoggerManager.cs @@ -18,7 +18,11 @@ #endregion using System; +#if NETSTANDARD1_3 +using System.Runtime.InteropServices; +#else using System.Configuration; +#endif using System.Reflection; using log4net.Util; @@ -100,8 +104,8 @@ namespace log4net.Core // Set the default repository selector #if NETCF s_repositorySelector = new CompactRepositorySelector(typeof(log4net.Repository.Hierarchy.Hierarchy)); -#else - + return; +#elif !NETSTANDARD1_3 // Look for the RepositorySelector type specified in the AppSettings 'log4net.RepositorySelector' string appRepositorySelectorTypeName = SystemInfo.GetAppSetting("log4net.RepositorySelector"); if (appRepositorySelectorTypeName != null && appRepositorySelectorTypeName.Length > 0) @@ -140,13 +144,12 @@ namespace log4net.Core } } } - +#endif // Create the DefaultRepositorySelector if not configured above if (s_repositorySelector == null) { s_repositorySelector = new DefaultRepositorySelector(typeof(log4net.Repository.Hierarchy.Hierarchy)); } -#endif } /// @@ -163,7 +166,7 @@ namespace log4net.Core /// private static void RegisterAppDomainEvents() { -#if !NETCF +#if !(NETCF || NETSTANDARD1_3) // ProcessExit seems to be fired if we are part of the default domain AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnProcessExit); @@ -798,17 +801,21 @@ namespace log4net.Core { System.Text.StringBuilder sb = new System.Text.StringBuilder(); - // Grab the currently executing assembly +#if NETSTANDARD1_3 + Assembly myAssembly = typeof(LoggerManager).GetTypeInfo().Assembly; + sb.Append($"log4net assembly [{myAssembly.FullName}]. "); + //sb.Append($"Loaded from [{myAssembly.Location}]. "); // TODO Assembly.Location available in netstandard1.5 + sb.Append($"(.NET Framework [{RuntimeInformation.FrameworkDescription}] on {RuntimeInformation.OSDescription}"); +#else Assembly myAssembly = Assembly.GetExecutingAssembly(); - - // Build Up message 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("]"); #if (!SSCLI) sb.Append(" on ").Append(Environment.OSVersion.ToString()); #endif - sb.Append(")"); +#endif // NETSTANDARD1_3 + sb.Append(")"); return sb.ToString(); } diff --git a/src/Core/LoggingEvent.cs b/src/Core/LoggingEvent.cs index 787aa84..a4ed839 100644 --- a/src/Core/LoggingEvent.cs +++ b/src/Core/LoggingEvent.cs @@ -22,8 +22,10 @@ using System.Collections; using System.IO; #if (!NETCF) using System.Runtime.Serialization; +#if !NETSTANDARD1_3 using System.Security.Principal; #endif +#endif using log4net.Util; using log4net.Repository; @@ -426,7 +428,7 @@ namespace log4net.Core #region Protected Instance Constructors -#if !NETCF +#if !(NETCF || NETSTANDARD1_3) /// /// Serialization constructor @@ -745,7 +747,7 @@ namespace log4net.Core { if (m_data.ThreadName == null && this.m_cacheUpdatable) { -#if NETCF +#if NETCF || NETSTANDARD1_3 // Get thread ID only m_data.ThreadName = SystemInfo.CurrentThreadId.ToString(System.Globalization.NumberFormatInfo.InvariantInfo); #else @@ -828,7 +830,7 @@ namespace log4net.Core { if (m_data.UserName == null && this.m_cacheUpdatable) { -#if (NETCF || SSCLI) +#if (NETCF || SSCLI || NETSTANDARD1_3) // NETSTANDARD1_3 TODO requires platform-specific code // On compact framework there's no notion of current Windows user m_data.UserName = SystemInfo.NotAvailableText; #else @@ -876,7 +878,7 @@ namespace log4net.Core { if (m_data.Identity == null && this.m_cacheUpdatable) { -#if (NETCF || SSCLI) +#if (NETCF || SSCLI || NETSTANDARD1_3) // On compact framework there's no notion of current thread principals m_data.Identity = SystemInfo.NotAvailableText; #else @@ -1022,7 +1024,7 @@ namespace log4net.Core /// is to be used outside that method. /// /// -#if NET_4_0 || MONO_4_0 +#if NET_4_0 || MONO_4_0 || NETSTANDARD1_3 [System.Security.SecurityCritical] #else [System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.Demand, SerializationFormatter=true)] @@ -1320,7 +1322,7 @@ namespace log4net.Core { m_compositeProperties.Add(m_eventProperties); } -#if !NETCF +#if !(NETCF || NETSTANDARD1_3) PropertiesDictionary logicalThreadProperties = LogicalThreadContext.Properties.GetProperties(false); if (logicalThreadProperties != null) { diff --git a/src/Filter/StringMatchFilter.cs b/src/Filter/StringMatchFilter.cs index 00a3626..38fa49d 100644 --- a/src/Filter/StringMatchFilter.cs +++ b/src/Filter/StringMatchFilter.cs @@ -95,7 +95,11 @@ namespace log4net.Filter { if (m_stringRegexToMatch != null) { +#if NETSTANDARD1_3 + m_regexToMatch = new Regex(m_stringRegexToMatch); +#else m_regexToMatch = new Regex(m_stringRegexToMatch, RegexOptions.Compiled); +#endif } } diff --git a/src/Layout/Pattern/DatePatternConverter.cs b/src/Layout/Pattern/DatePatternConverter.cs index 91a4caa..498ddd4 100644 --- a/src/Layout/Pattern/DatePatternConverter.cs +++ b/src/Layout/Pattern/DatePatternConverter.cs @@ -18,6 +18,7 @@ #endregion using System; +using System.Globalization; using System.Text; using System.IO; @@ -119,20 +120,34 @@ namespace log4net.Layout.Pattern { dateFormatStr = AbsoluteTimeDateFormatter.Iso8601TimeDateFormat; } - - if (string.Compare(dateFormatStr, AbsoluteTimeDateFormatter.Iso8601TimeDateFormat, true, System.Globalization.CultureInfo.InvariantCulture) == 0) +#if NETSTANDARD1_3 + if (CultureInfo.InvariantCulture.CompareInfo.Compare(dateFormatStr, AbsoluteTimeDateFormatter.Iso8601TimeDateFormat, CompareOptions.IgnoreCase) == 0) { m_dateFormatter = new Iso8601DateFormatter(); } - else if (string.Compare(dateFormatStr, AbsoluteTimeDateFormatter.AbsoluteTimeDateFormat, true, System.Globalization.CultureInfo.InvariantCulture) == 0) + else if (CultureInfo.InvariantCulture.CompareInfo.Compare(dateFormatStr, AbsoluteTimeDateFormatter.AbsoluteTimeDateFormat, CompareOptions.IgnoreCase) == 0) { m_dateFormatter = new AbsoluteTimeDateFormatter(); } - else if (string.Compare(dateFormatStr, AbsoluteTimeDateFormatter.DateAndTimeDateFormat, true, System.Globalization.CultureInfo.InvariantCulture) == 0) + else if (CultureInfo.InvariantCulture.CompareInfo.Compare(dateFormatStr, AbsoluteTimeDateFormatter.DateAndTimeDateFormat, CompareOptions.IgnoreCase) == 0) { m_dateFormatter = new DateTimeDateFormatter(); } - else +#else + if (string.Compare(dateFormatStr, AbsoluteTimeDateFormatter.Iso8601TimeDateFormat, true, CultureInfo.InvariantCulture) == 0) + { + m_dateFormatter = new Iso8601DateFormatter(); + } + else if (string.Compare(dateFormatStr, AbsoluteTimeDateFormatter.AbsoluteTimeDateFormat, true, CultureInfo.InvariantCulture) == 0) + { + m_dateFormatter = new AbsoluteTimeDateFormatter(); + } + else if (string.Compare(dateFormatStr, AbsoluteTimeDateFormatter.DateAndTimeDateFormat, true, CultureInfo.InvariantCulture) == 0) + { + m_dateFormatter = new DateTimeDateFormatter(); + } +#endif + else { try { diff --git a/src/Layout/Pattern/ExceptionPatternConverter.cs b/src/Layout/Pattern/ExceptionPatternConverter.cs index f522d87..06d3928 100644 --- a/src/Layout/Pattern/ExceptionPatternConverter.cs +++ b/src/Layout/Pattern/ExceptionPatternConverter.cs @@ -106,9 +106,11 @@ namespace log4net.Layout.Pattern case "stacktrace": WriteObject(writer, loggingEvent.Repository, loggingEvent.ExceptionObject.StackTrace); break; +#if !NETSTANDARD1_3 case "targetsite": WriteObject(writer, loggingEvent.Repository, loggingEvent.ExceptionObject.TargetSite); break; +#endif case "helplink": WriteObject(writer, loggingEvent.Repository, loggingEvent.ExceptionObject.HelpLink); break; diff --git a/src/Layout/PatternLayout.cs b/src/Layout/PatternLayout.cs index 9e15921..31a5644 100644 --- a/src/Layout/PatternLayout.cs +++ b/src/Layout/PatternLayout.cs @@ -20,6 +20,9 @@ using System; using System.Collections; using System.IO; +#if NETSTANDARD1_3 +using System.Reflection; +#endif using log4net.Core; using log4net.Layout.Pattern; @@ -861,7 +864,7 @@ namespace log4net.Layout // .NET Compact Framework 1.0 has no support for ASP.NET // SSCLI 1.0 has no support for ASP.NET -#if !NETCF && !SSCLI && !CLIENT_PROFILE +#if !NETCF && !SSCLI && !CLIENT_PROFILE && !NETSTANDARD1_3 s_globalRulesRegistry.Add("aspnet-cache", typeof(AspNetCachePatternConverter)); s_globalRulesRegistry.Add("aspnet-context", typeof(AspNetContextPatternConverter)); s_globalRulesRegistry.Add("aspnet-request", typeof(AspNetRequestPatternConverter)); @@ -905,7 +908,7 @@ namespace log4net.Layout s_globalRulesRegistry.Add("r", typeof(RelativeTimePatternConverter)); s_globalRulesRegistry.Add("timestamp", typeof(RelativeTimePatternConverter)); -#if !NETCF +#if !(NETCF || NETSTANDARD1_3) s_globalRulesRegistry.Add("stacktrace", typeof(StackTracePatternConverter)); s_globalRulesRegistry.Add("stacktracedetail", typeof(StackTraceDetailPatternConverter)); #endif diff --git a/src/Layout/RawLayoutConverter.cs b/src/Layout/RawLayoutConverter.cs index d287d7d..7ccfe77 100644 --- a/src/Layout/RawLayoutConverter.cs +++ b/src/Layout/RawLayoutConverter.cs @@ -18,6 +18,9 @@ #endregion using System; +#if NETSTANDARD1_3 +using System.Reflection; +#endif using log4net; using log4net.Core; diff --git a/src/Layout/XmlLayout.cs b/src/Layout/XmlLayout.cs index 6d8e432..34f9750 100644 --- a/src/Layout/XmlLayout.cs +++ b/src/Layout/XmlLayout.cs @@ -220,7 +220,7 @@ namespace log4net.Layout writer.WriteStartElement(m_elmEvent); writer.WriteAttributeString(ATTR_LOGGER, loggingEvent.LoggerName); -#if NET_2_0 || NETCF_2_0 || MONO_2_0 +#if NET_2_0 || NETCF_2_0 || MONO_2_0 || NETSTANDARD1_3 writer.WriteAttributeString(ATTR_TIMESTAMP, XmlConvert.ToString(loggingEvent.TimeStamp, XmlDateTimeSerializationMode.Local)); #else writer.WriteAttributeString(ATTR_TIMESTAMP, XmlConvert.ToString(loggingEvent.TimeStamp)); diff --git a/src/Layout/XmlLayoutBase.cs b/src/Layout/XmlLayoutBase.cs index 2ec0e8c..9b51653 100644 --- a/src/Layout/XmlLayoutBase.cs +++ b/src/Layout/XmlLayoutBase.cs @@ -196,11 +196,18 @@ namespace log4net.Layout { throw new ArgumentNullException("loggingEvent"); } - +#if NETSTANDARD1_3 + var settings = new XmlWriterSettings + { + Indent = false, + OmitXmlDeclaration = true + }; + var xmlWriter = XmlWriter.Create(new ProtectCloseTextWriter(writer), settings); +#else XmlTextWriter xmlWriter = new XmlTextWriter(new ProtectCloseTextWriter(writer)); xmlWriter.Formatting = Formatting.None; xmlWriter.Namespaces = false; - +#endif // Write the event to the writer FormatXml(xmlWriter, loggingEvent); diff --git a/src/LogManager.cs b/src/LogManager.cs index 1e024e7..7ec8d0c 100644 --- a/src/LogManager.cs +++ b/src/LogManager.cs @@ -73,6 +73,7 @@ namespace log4net #region Type Specific Manager Methods +#if !NETSTANDARD1_3 // Excluded because GetCallingAssembly() is not available in CoreFX (https://github.com/dotnet/corefx/issues/2221). /// Returns the named logger if it exists. /// /// Returns the named logger if it exists. @@ -89,24 +90,61 @@ namespace log4net { return Exists(Assembly.GetCallingAssembly(), name); } - + + /// Get the currently defined loggers. /// - /// Returns the named logger if it exists. + /// Returns all the currently defined loggers in the default repository. + /// + /// + /// The root logger is not included in the returned array. + /// + /// All the defined loggers. + public static ILog[] GetCurrentLoggers() + { + return GetCurrentLoggers(Assembly.GetCallingAssembly()); + } + + /// Get or create a logger. + /// + /// Retrieves or creates a named logger. /// /// /// - /// If the named logger exists (in the specified repository) then it - /// returns a reference to the logger, otherwise it returns - /// null. + /// Retrieves a logger named as the + /// parameter. If the named logger already exists, then the + /// existing instance will be returned. Otherwise, a new instance is + /// created. + /// + /// By default, loggers do not have a set level but inherit + /// it from the hierarchy. This is one of the central features of + /// log4net. /// /// - /// The repository to lookup in. - /// The fully qualified logger name to look for. - /// - /// The logger found, or null if the logger doesn't exist in the specified - /// repository. - /// - public static ILog Exists(string repository, string name) + /// The name of the logger to retrieve. + /// The logger with the name specified. + public static ILog GetLogger(string name) + { + return GetLogger(Assembly.GetCallingAssembly(), name); + } +#endif // !NETSTANDARD1_3 + + /// + /// Returns the named logger if it exists. + /// + /// + /// + /// If the named logger exists (in the specified repository) then it + /// returns a reference to the logger, otherwise it returns + /// null. + /// + /// + /// The repository to lookup in. + /// The fully qualified logger name to look for. + /// + /// The logger found, or null if the logger doesn't exist in the specified + /// repository. + /// + public static ILog Exists(string repository, string name) { return WrapLogger(LoggerManager.Exists(repository, name)); } @@ -132,19 +170,6 @@ namespace log4net return WrapLogger(LoggerManager.Exists(repositoryAssembly, name)); } - /// Get the currently defined loggers. - /// - /// Returns all the currently defined loggers in the default repository. - /// - /// - /// The root logger is not included in the returned array. - /// - /// All the defined loggers. - public static ILog[] GetCurrentLoggers() - { - return GetCurrentLoggers(Assembly.GetCallingAssembly()); - } - /// /// Returns all the currently defined loggers in the specified repository. /// @@ -171,29 +196,6 @@ namespace log4net return WrapLoggers(LoggerManager.GetCurrentLoggers(repositoryAssembly)); } - /// Get or create a logger. - /// - /// Retrieves or creates a named logger. - /// - /// - /// - /// Retrieves a logger named as the - /// parameter. If the named logger already exists, then the - /// existing instance will be returned. Otherwise, a new instance is - /// created. - /// - /// By default, loggers do not have a set level but inherit - /// it from the hierarchy. This is one of the central features of - /// log4net. - /// - /// - /// The name of the logger to retrieve. - /// The logger with the name specified. - public static ILog GetLogger(string name) - { - return GetLogger(Assembly.GetCallingAssembly(), name); - } - /// /// Retrieves or creates a named logger. /// @@ -252,7 +254,11 @@ namespace log4net /// The logger with the name specified. public static ILog GetLogger(Type type) { +#if NETSTANDARD1_3 + return GetLogger(type.GetTypeInfo().Assembly, type.FullName); +#else return GetLogger(Assembly.GetCallingAssembly(), type.FullName); +#endif } /// @@ -311,6 +317,7 @@ namespace log4net LoggerManager.Shutdown(); } +#if !NETSTANDARD1_3 /// Shutdown a logger repository. /// /// Shuts down the default repository. @@ -335,6 +342,7 @@ namespace log4net ShutdownRepository(Assembly.GetCallingAssembly()); } +#endif /// /// Shuts down the repository for the repository specified. /// @@ -387,6 +395,7 @@ namespace log4net LoggerManager.ShutdownRepository(repositoryAssembly); } +#if !NETSTANDARD1_3 /// Reset the configuration of a repository /// /// Resets all values contained in this repository instance to their defaults. @@ -405,6 +414,7 @@ namespace log4net { ResetConfiguration(Assembly.GetCallingAssembly()); } +#endif /// /// Resets all values contained in this repository instance to their defaults. @@ -444,6 +454,7 @@ namespace log4net LoggerManager.ResetConfiguration(repositoryAssembly); } +#if !NETSTANDARD1_3 /// Get the logger repository. /// /// Returns the default instance. @@ -460,6 +471,7 @@ namespace log4net { return GetRepository(Assembly.GetCallingAssembly()); } +#endif /// /// Returns the default instance. @@ -495,6 +507,7 @@ namespace log4net return GetRepository(repositoryAssembly); } +#if !NETSTANDARD1_3 /// Get a logger repository. /// /// Returns the default instance. @@ -510,6 +523,7 @@ namespace log4net { return GetRepository(Assembly.GetCallingAssembly()); } +#endif /// /// Returns the default instance. @@ -543,6 +557,7 @@ namespace log4net return LoggerManager.GetRepository(repositoryAssembly); } +#if !NETSTANDARD1_3 /// Create a domain /// /// Creates a repository with the specified repository type. @@ -586,6 +601,7 @@ namespace log4net { return CreateRepository(Assembly.GetCallingAssembly(), repositoryType); } +#endif /// /// Creates a repository with the specified name. diff --git a/src/ObjectRenderer/RendererMap.cs b/src/ObjectRenderer/RendererMap.cs index 122a6c1..7f4db96 100644 --- a/src/ObjectRenderer/RendererMap.cs +++ b/src/ObjectRenderer/RendererMap.cs @@ -19,6 +19,10 @@ using System; using System.IO; +#if NETSTANDARD1_3 +using System.Reflection; +#endif + using log4net.Util; namespace log4net.ObjectRenderer @@ -216,7 +220,11 @@ namespace log4net.ObjectRenderer if (result == null) { +#if NETSTANDARD1_3 + for (Type cur = type; cur != null; cur = cur.GetTypeInfo().BaseType) +#else for(Type cur = type; cur != null; cur = cur.BaseType) +#endif { // Search the type's interfaces result = SearchTypeAndInterfaces(cur); diff --git a/src/Plugin/PluginCollection.cs b/src/Plugin/PluginCollection.cs index d068f55..7e7d4e2 100644 --- a/src/Plugin/PluginCollection.cs +++ b/src/Plugin/PluginCollection.cs @@ -26,7 +26,10 @@ namespace log4net.Plugin /// A strongly-typed collection of objects. /// /// Nicko Cadell - public class PluginCollection : ICollection, IList, IEnumerable, ICloneable + public class PluginCollection : ICollection, IList, IEnumerable +#if !NETSTANDARD1_3 + , ICloneable +#endif { #region Interfaces @@ -209,10 +212,10 @@ namespace log4net.Plugin /// /// Gets a value indicating whether access to the collection is synchronized (thread-safe). /// - /// true if access to the ICollection is synchronized (thread-safe); otherwise, false. + /// false, because the backing type is an array, which is never thread-safe. public virtual bool IsSynchronized { - get { return m_array.IsSynchronized; } + get { return false; } } /// @@ -223,7 +226,7 @@ namespace log4net.Plugin /// public virtual object SyncRoot { - get { return m_array.SyncRoot; } + get { return m_array; } } #endregion diff --git a/src/Repository/Hierarchy/Logger.cs b/src/Repository/Hierarchy/Logger.cs index 5c29653..34735a7 100644 --- a/src/Repository/Hierarchy/Logger.cs +++ b/src/Repository/Hierarchy/Logger.cs @@ -73,7 +73,7 @@ namespace log4net.Repository.Hierarchy /// protected Logger(string name) { -#if NETCF +#if NETCF || NETSTANDARD1_3 // NETCF: String.Intern causes Native Exception m_name = name; #else @@ -432,7 +432,7 @@ namespace log4net.Repository.Hierarchy { log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); } -#if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0 +#if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0 && !NETSTANDARD1_3 catch { log4net.Util.LogLog.Error(declaringType, "Exception while logging"); @@ -469,7 +469,7 @@ namespace log4net.Repository.Hierarchy { log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); } -#if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0 +#if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0 && !NETSTANDARD1_3 catch { log4net.Util.LogLog.Error(declaringType, "Exception while logging"); @@ -509,7 +509,7 @@ namespace log4net.Repository.Hierarchy { log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex); } -#if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0 +#if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0 && !NETSTANDARD1_3 catch { log4net.Util.LogLog.Error(declaringType, "Exception while logging"); @@ -606,7 +606,7 @@ namespace log4net.Repository.Hierarchy { LogLog.Debug(declaringType, " Current AppDomain context information: "); LogLog.Debug(declaringType, " BaseDirectory : " + SystemInfo.ApplicationBaseDirectory); -#if !NETCF +#if !(NETCF || NETSTANDARD1_3) LogLog.Debug(declaringType, " FriendlyName : " + AppDomain.CurrentDomain.FriendlyName); LogLog.Debug(declaringType, " DynamicDirectory: " + AppDomain.CurrentDomain.DynamicDirectory); #endif diff --git a/src/Repository/Hierarchy/LoggerKey.cs b/src/Repository/Hierarchy/LoggerKey.cs index 1ea9004..ccc566b 100644 --- a/src/Repository/Hierarchy/LoggerKey.cs +++ b/src/Repository/Hierarchy/LoggerKey.cs @@ -64,7 +64,7 @@ namespace log4net.Repository.Hierarchy /// The name of the logger. internal LoggerKey(string name) { -#if NETCF +#if NETCF || NETSTANDARD1_3 // NETCF: String.Intern causes Native Exception m_name = name; #else @@ -115,7 +115,7 @@ namespace log4net.Repository.Hierarchy LoggerKey objKey = obj as LoggerKey; if (objKey != null) { -#if NETCF +#if NETCF || NETSTANDARD1_3 return ( m_name == objKey.m_name ); #else // Compare reference types rather than string's overloaded == diff --git a/src/Repository/Hierarchy/XmlHierarchyConfigurator.cs b/src/Repository/Hierarchy/XmlHierarchyConfigurator.cs index cc17d12..a9ff3d0 100644 --- a/src/Repository/Hierarchy/XmlHierarchyConfigurator.cs +++ b/src/Repository/Hierarchy/XmlHierarchyConfigurator.cs @@ -300,7 +300,11 @@ namespace log4net.Repository.Hierarchy LogLog.Debug(declaringType, "Loading Appender [" + appenderName + "] type: [" + typeName + "]"); try { +#if NETSTANDARD1_3 + IAppender appender = (IAppender)Activator.CreateInstance(SystemInfo.GetTypeFromString(this.GetType().GetTypeInfo().Assembly, typeName, true, true)); +#else IAppender appender = (IAppender)Activator.CreateInstance(SystemInfo.GetTypeFromString(typeName, true, true)); +#endif appender.Name = appenderName; foreach (XmlNode currentNode in appenderElement.ChildNodes) @@ -486,7 +490,11 @@ namespace log4net.Repository.Hierarchy { try { +#if NETSTANDARD1_3 + m_hierarchy.RendererMap.Put(SystemInfo.GetTypeFromString(this.GetType().GetTypeInfo().Assembly, renderedClassName, true, true), renderer); +#else m_hierarchy.RendererMap.Put(SystemInfo.GetTypeFromString(renderedClassName, true, true), renderer); +#endif } catch(Exception e) { @@ -630,7 +638,7 @@ namespace log4net.Repository.Hierarchy if(propertyValue != null) { -#if !NETCF +#if !(NETCF || NETSTANDARD1_3) // NETSTANDARD1_3: System.Runtime.InteropServices.RuntimeInformation not available on desktop 4.6 try { // Expand environment variables in the string. @@ -658,7 +666,11 @@ namespace log4net.Repository.Hierarchy // Read the explicit subtype try { +#if NETSTANDARD1_3 + Type subType = SystemInfo.GetTypeFromString(this.GetType().GetTypeInfo().Assembly, subTypeString, true, true); +#else Type subType = SystemInfo.GetTypeFromString(subTypeString, true, true); +#endif LogLog.Debug(declaringType, "Parameter ["+name+"] specified subtype ["+subType.FullName+"]"); @@ -713,7 +725,11 @@ namespace log4net.Repository.Hierarchy try { // Pass to the property +#if NETSTANDARD1_3 // TODO BindingFlags is available for netstandard1.5 + propInfo.SetValue(target, convertedValue, null); +#else propInfo.SetValue(target, convertedValue, BindingFlags.SetProperty, null, null, CultureInfo.InvariantCulture); +#endif } catch(TargetInvocationException targetInvocationEx) { @@ -728,7 +744,11 @@ namespace log4net.Repository.Hierarchy try { // Pass to the property +#if NETSTANDARD1_3 // TODO BindingFlags is available for netstandard1.5 + methInfo.Invoke(target, new[] { convertedValue }); +#else methInfo.Invoke(target, BindingFlags.InvokeMethod, null, new object[] {convertedValue}, CultureInfo.InvariantCulture); +#endif } catch(TargetInvocationException targetInvocationEx) { @@ -780,7 +800,11 @@ namespace log4net.Repository.Hierarchy try { // Pass to the property +#if NETSTANDARD1_3 // TODO BindingFlags is available for netstandard1.5 + propInfo.SetValue(target, createdObject, null); +#else propInfo.SetValue(target, createdObject, BindingFlags.SetProperty, null, null, CultureInfo.InvariantCulture); +#endif } catch(TargetInvocationException targetInvocationEx) { @@ -795,7 +819,11 @@ namespace log4net.Repository.Hierarchy try { // Pass to the property +#if NETSTANDARD1_3 // TODO BindingFlags is available for netstandard1.5 + methInfo.Invoke(target, new[] { createdObject }); +#else methInfo.Invoke(target, BindingFlags.InvokeMethod, null, new object[] {createdObject}, CultureInfo.InvariantCulture); +#endif } catch(TargetInvocationException targetInvocationEx) { @@ -831,7 +859,12 @@ namespace log4net.Repository.Hierarchy /// true if the type is creatable using a default constructor, false otherwise private static bool IsTypeConstructible(Type type) { +#if NETSTANDARD1_3 + TypeInfo typeInfo = type.GetTypeInfo(); + if (typeInfo.IsClass && !typeInfo.IsAbstract) +#else if (type.IsClass && !type.IsAbstract) +#endif { ConstructorInfo defaultConstructor = type.GetConstructor(new Type[0]); if (defaultConstructor != null && !defaultConstructor.IsAbstract && !defaultConstructor.IsPrivate) @@ -866,8 +899,13 @@ namespace log4net.Repository.Hierarchy { if (!methInfo.IsStatic) { +#if NETSTANDARD1_3 + if (CultureInfo.InvariantCulture.CompareInfo.Compare(methInfo.Name, requiredMethodNameA, CompareOptions.IgnoreCase) == 0 || + CultureInfo.InvariantCulture.CompareInfo.Compare(methInfo.Name, requiredMethodNameB, CompareOptions.IgnoreCase) == 0) +#else if (string.Compare(methInfo.Name, requiredMethodNameA, true, System.Globalization.CultureInfo.InvariantCulture) == 0 || string.Compare(methInfo.Name, requiredMethodNameB, true, System.Globalization.CultureInfo.InvariantCulture) == 0) +#endif { // Found matching method name @@ -955,7 +993,11 @@ namespace log4net.Repository.Hierarchy // Read the explicit object type try { +#if NETSTANDARD1_3 + objectType = SystemInfo.GetTypeFromString(this.GetType().GetTypeInfo().Assembly, objectTypeString, true, true); +#else objectType = SystemInfo.GetTypeFromString(objectTypeString, true, true); +#endif } catch(Exception ex) { @@ -1027,7 +1069,7 @@ namespace log4net.Repository.Hierarchy #endregion Protected Instance Methods -#if !NETCF +#if !(NETCF || NETSTANDARD1_3) // NETSTANDARD1_3: System.Runtime.InteropServices.RuntimeInformation not available on desktop 4.6 private bool HasCaseInsensitiveEnvironment { get diff --git a/src/Util/ILogExtensions.cs b/src/Util/ILogExtensions.cs index f8c0ebb..0d82d9e 100644 --- a/src/Util/ILogExtensions.cs +++ b/src/Util/ILogExtensions.cs @@ -17,7 +17,7 @@ // #endregion -#if NET_3_5 || NET_4_0 || MONO_3_5 || MONO_4_0 +#if NET_3_5 || NET_4_0 || MONO_3_5 || MONO_4_0 || NETSTANDARD1_3 using System; diff --git a/src/Util/LogLog.cs b/src/Util/LogLog.cs index 4d6b1dd..64bdf1a 100644 --- a/src/Util/LogLog.cs +++ b/src/Util/LogLog.cs @@ -19,7 +19,9 @@ using System; using System.Collections; +#if !NETSTANDARD1_3 using System.Configuration; +#endif using System.Diagnostics; namespace log4net.Util diff --git a/src/Util/NativeError.cs b/src/Util/NativeError.cs index 5e0ac6e..1aeab0b 100644 --- a/src/Util/NativeError.cs +++ b/src/Util/NativeError.cs @@ -114,7 +114,7 @@ namespace log4net.Util /// native Win32 FormatMessage function. /// /// -#if NET_4_0 || MONO_4_0 +#if NET_4_0 || MONO_4_0 || NETSTANDARD1_3 [System.Security.SecuritySafeCritical] #elif !NETCF [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode=true)] @@ -157,7 +157,7 @@ namespace log4net.Util /// using the native FormatMessage function. /// /// -#if NET_4_0 || MONO_4_0 +#if NET_4_0 || MONO_4_0 || NETSTANDARD1_3 [System.Security.SecuritySafeCritical] #elif !NETCF [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)] diff --git a/src/Util/OptionConverter.cs b/src/Util/OptionConverter.cs index 616cf1b..cc791dc 100644 --- a/src/Util/OptionConverter.cs +++ b/src/Util/OptionConverter.cs @@ -286,7 +286,11 @@ namespace log4net.Util } else { +#if NETSTANDARD1_3 + if (target.GetTypeInfo().IsEnum) +#else if (target.IsEnum) +#endif { // Target type is an enum. @@ -303,7 +307,11 @@ namespace log4net.Util if (meth != null) { // Call the Parse method +#if NETSTANDARD1_3 + return meth.Invoke(target, new[] { txt }); +#else return meth.Invoke(null, BindingFlags.InvokeMethod, null, new object[] {txt}, CultureInfo.InvariantCulture); +#endif } else { @@ -475,7 +483,11 @@ namespace log4net.Util { try { +#if NETSTANDARD1_3 + Type classObj = SystemInfo.GetTypeFromString(superClass.GetTypeInfo().Assembly, className, true, true); +#else Type classObj = SystemInfo.GetTypeFromString(className, true, true); +#endif if (!superClass.IsAssignableFrom(classObj)) { LogLog.Error(declaringType, "OptionConverter: A [" + className + "] object is not assignable to a [" + superClass.FullName + "] variable."); diff --git a/src/Util/PatternParser.cs b/src/Util/PatternParser.cs index 863f557..f947897 100644 --- a/src/Util/PatternParser.cs +++ b/src/Util/PatternParser.cs @@ -232,7 +232,11 @@ namespace log4net.Util { formattingInfo.Min = 0; } +#if NETSTANDARD1_3 + formattingInfo.Min = (formattingInfo.Min * 10) + int.Parse(pattern[offset].ToString(), System.Globalization.NumberFormatInfo.InvariantInfo); +#else formattingInfo.Min = (formattingInfo.Min * 10) + int.Parse(pattern[offset].ToString(CultureInfo.InvariantCulture), System.Globalization.NumberFormatInfo.InvariantInfo); +#endif offset++; } // Look for the separator between min and max @@ -252,7 +256,11 @@ namespace log4net.Util { formattingInfo.Max = 0; } +#if NETSTANDARD1_3 + formattingInfo.Max = (formattingInfo.Max * 10) + int.Parse(pattern[offset].ToString(), System.Globalization.NumberFormatInfo.InvariantInfo); +#else formattingInfo.Max = (formattingInfo.Max * 10) + int.Parse(pattern[offset].ToString(CultureInfo.InvariantCulture), System.Globalization.NumberFormatInfo.InvariantInfo); +#endif offset++; } @@ -263,7 +271,11 @@ namespace log4net.Util { if (matches[m].Length <= remainingStringLength) { +#if NETSTANDARD1_3 + if (CultureInfo.InvariantCulture.CompareInfo.Compare(pattern, offset, matches[m].Length, matches[m], 0, matches[m].Length) == 0) +#else if (String.Compare(pattern, offset, matches[m], 0, matches[m].Length, false, System.Globalization.CultureInfo.InvariantCulture) == 0) +#endif { // Found match offset = offset + matches[m].Length; diff --git a/src/Util/PatternString.cs b/src/Util/PatternString.cs index 73f5a5f..8348c1e 100644 --- a/src/Util/PatternString.cs +++ b/src/Util/PatternString.cs @@ -20,6 +20,9 @@ using System; using System.Collections; using System.IO; +#if NETSTANDARD1_3 +using System.Reflection; +#endif using log4net.Util; using log4net.Util.PatternStringConverters; @@ -288,7 +291,9 @@ namespace log4net.Util s_globalRulesRegistry.Add("date", typeof(DatePatternConverter)); #if !NETCF s_globalRulesRegistry.Add("env", typeof(EnvironmentPatternConverter)); - s_globalRulesRegistry.Add("envFolderPath", typeof(EnvironmentFolderPathPatternConverter)); +#if !NETSTANDARD1_3 // EnvironmentFolderPathPatternConverter not yet supported + s_globalRulesRegistry.Add("envFolderPath", typeof(EnvironmentFolderPathPatternConverter)); +#endif #endif s_globalRulesRegistry.Add("identity", typeof(IdentityPatternConverter)); s_globalRulesRegistry.Add("literal", typeof(LiteralPatternConverter)); diff --git a/src/Util/PatternStringConverters/DatePatternConverter.cs b/src/Util/PatternStringConverters/DatePatternConverter.cs index 88045df..fea1183 100644 --- a/src/Util/PatternStringConverters/DatePatternConverter.cs +++ b/src/Util/PatternStringConverters/DatePatternConverter.cs @@ -18,6 +18,7 @@ #endregion using System; +using System.Globalization; using System.Text; using System.IO; @@ -119,20 +120,34 @@ namespace log4net.Util.PatternStringConverters { dateFormatStr = AbsoluteTimeDateFormatter.Iso8601TimeDateFormat; } - - if (string.Compare(dateFormatStr, AbsoluteTimeDateFormatter.Iso8601TimeDateFormat, true, System.Globalization.CultureInfo.InvariantCulture) == 0) +#if NETSTANDARD1_3 + if (CultureInfo.InvariantCulture.CompareInfo.Compare(dateFormatStr, AbsoluteTimeDateFormatter.Iso8601TimeDateFormat, CompareOptions.IgnoreCase) == 0) { m_dateFormatter = new Iso8601DateFormatter(); } - else if (string.Compare(dateFormatStr, AbsoluteTimeDateFormatter.AbsoluteTimeDateFormat, true, System.Globalization.CultureInfo.InvariantCulture) == 0) + else if (CultureInfo.InvariantCulture.CompareInfo.Compare(dateFormatStr, AbsoluteTimeDateFormatter.AbsoluteTimeDateFormat, CompareOptions.IgnoreCase) == 0) { m_dateFormatter = new AbsoluteTimeDateFormatter(); } - else if (string.Compare(dateFormatStr, AbsoluteTimeDateFormatter.DateAndTimeDateFormat, true, System.Globalization.CultureInfo.InvariantCulture) == 0) + else if (CultureInfo.InvariantCulture.CompareInfo.Compare(dateFormatStr, AbsoluteTimeDateFormatter.DateAndTimeDateFormat, CompareOptions.IgnoreCase) == 0) { m_dateFormatter = new DateTimeDateFormatter(); } - else +#else + if (string.Compare(dateFormatStr, AbsoluteTimeDateFormatter.Iso8601TimeDateFormat, true, CultureInfo.InvariantCulture) == 0) + { + m_dateFormatter = new Iso8601DateFormatter(); + } + else if (string.Compare(dateFormatStr, AbsoluteTimeDateFormatter.AbsoluteTimeDateFormat, true, CultureInfo.InvariantCulture) == 0) + { + m_dateFormatter = new AbsoluteTimeDateFormatter(); + } + else if (string.Compare(dateFormatStr, AbsoluteTimeDateFormatter.DateAndTimeDateFormat, true, CultureInfo.InvariantCulture) == 0) + { + m_dateFormatter = new DateTimeDateFormatter(); + } +#endif + else { try { diff --git a/src/Util/PatternStringConverters/IdentityPatternConverter.cs b/src/Util/PatternStringConverters/IdentityPatternConverter.cs index 5f83c76..d92a292 100644 --- a/src/Util/PatternStringConverters/IdentityPatternConverter.cs +++ b/src/Util/PatternStringConverters/IdentityPatternConverter.cs @@ -48,7 +48,7 @@ namespace log4net.Util.PatternStringConverters /// override protected void Convert(TextWriter writer, object state) { -#if (NETCF || SSCLI) +#if (NETCF || SSCLI || NETSTANDARD1_3) // On compact framework there's no notion of current thread principals writer.Write( SystemInfo.NotAvailableText ); #else diff --git a/src/Util/PatternStringConverters/NewLinePatternConverter.cs b/src/Util/PatternStringConverters/NewLinePatternConverter.cs index c5b4e7a..8e36496 100644 --- a/src/Util/PatternStringConverters/NewLinePatternConverter.cs +++ b/src/Util/PatternStringConverters/NewLinePatternConverter.cs @@ -17,6 +17,9 @@ // #endregion +#if NETSTANDARD1_3 +using System.Globalization; +#endif using System; using System.Text; using System.IO; @@ -72,6 +75,16 @@ namespace log4net.Util.PatternStringConverters /// public void ActivateOptions() { +#if NETSTANDARD1_3 + if (CultureInfo.InvariantCulture.CompareInfo.Compare(Option, "DOS", CompareOptions.IgnoreCase) == 0) + { + Option = "\r\n"; + } + else if (CultureInfo.InvariantCulture.CompareInfo.Compare(Option, "UNIX", CompareOptions.IgnoreCase) == 0) + { + Option = "\n"; + } +#else if (string.Compare(Option, "DOS", true, System.Globalization.CultureInfo.InvariantCulture) == 0) { Option = "\r\n"; @@ -80,6 +93,7 @@ namespace log4net.Util.PatternStringConverters { Option = "\n"; } +#endif else { Option = SystemInfo.NewLine; diff --git a/src/Util/PatternStringConverters/ProcessIdPatternConverter.cs b/src/Util/PatternStringConverters/ProcessIdPatternConverter.cs index e47ee9e..2d6a5a1 100644 --- a/src/Util/PatternStringConverters/ProcessIdPatternConverter.cs +++ b/src/Util/PatternStringConverters/ProcessIdPatternConverter.cs @@ -46,7 +46,7 @@ namespace log4net.Util.PatternStringConverters /// Write the current process ID to the output . /// /// -#if NET_4_0 || MONO_4_0 +#if NET_4_0 || MONO_4_0 || NETSTANDARD1_3 [System.Security.SecuritySafeCritical] #endif override protected void Convert(TextWriter writer, object state) diff --git a/src/Util/PatternStringConverters/PropertyPatternConverter.cs b/src/Util/PatternStringConverters/PropertyPatternConverter.cs index 3124b31..9c2051e 100644 --- a/src/Util/PatternStringConverters/PropertyPatternConverter.cs +++ b/src/Util/PatternStringConverters/PropertyPatternConverter.cs @@ -68,7 +68,7 @@ namespace log4net.Util.PatternStringConverters { CompositeProperties compositeProperties = new CompositeProperties(); -#if !NETCF +#if !(NETCF || NETSTANDARD1_3) PropertiesDictionary logicalThreadProperties = LogicalThreadContext.Properties.GetProperties(false); if (logicalThreadProperties != null) { diff --git a/src/Util/PatternStringConverters/UserNamePatternConverter.cs b/src/Util/PatternStringConverters/UserNamePatternConverter.cs index 921ee24..0f8dffb 100644 --- a/src/Util/PatternStringConverters/UserNamePatternConverter.cs +++ b/src/Util/PatternStringConverters/UserNamePatternConverter.cs @@ -48,7 +48,7 @@ namespace log4net.Util.PatternStringConverters /// override protected void Convert(TextWriter writer, object state) { -#if (NETCF || SSCLI) +#if (NETCF || SSCLI || NETSTANDARD1_3) // On compact framework there's no notion of current Windows user writer.Write( SystemInfo.NotAvailableText ); #else diff --git a/src/Util/PropertiesDictionary.cs b/src/Util/PropertiesDictionary.cs index be511d5..d2e48d5 100644 --- a/src/Util/PropertiesDictionary.cs +++ b/src/Util/PropertiesDictionary.cs @@ -75,7 +75,7 @@ namespace log4net.Util #region Private Instance Constructors -#if !NETCF +#if !(NETCF || NETSTANDARD1_3) /// /// Initializes a new instance of the class /// with serialized data. diff --git a/src/Util/ReadOnlyPropertiesDictionary.cs b/src/Util/ReadOnlyPropertiesDictionary.cs index be7796a..fba6c1a 100644 --- a/src/Util/ReadOnlyPropertiesDictionary.cs +++ b/src/Util/ReadOnlyPropertiesDictionary.cs @@ -19,6 +19,7 @@ using System; using System.Collections; +using System.Reflection; #if !NETCF using System.Runtime.Serialization; using System.Xml; @@ -91,7 +92,7 @@ namespace log4net.Util #region Private Instance Constructors -#if !NETCF +#if !(NETCF || NETSTANDARD1_3) /// /// Deserialization constructor /// @@ -203,7 +204,7 @@ namespace log4net.Util /// Serializes this object into the provided. /// /// -#if NET_4_0 || MONO_4_0 +#if NET_4_0 || MONO_4_0 || NETSTANDARD1_3 [System.Security.SecurityCritical] #else [System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.Demand, SerializationFormatter=true)] @@ -215,8 +216,13 @@ namespace log4net.Util string entryKey = entry.Key as string; object entryValue = entry.Value; - // If value is serializable then we add it to the list - if (entryKey != null && entryValue != null && entryValue.GetType().IsSerializable) + // If value is serializable then we add it to the list +#if NETSTANDARD1_3 + bool isSerializable = entryValue.GetType().GetTypeInfo().IsSerializable; +#else + bool isSerializable = entryValue.GetType().IsSerializable; +#endif + if (entryKey != null && entryValue != null && isSerializable) { // Store the keys as an Xml encoded local name as it may contain colons (':') // which are NOT escaped by the Xml Serialization framework. diff --git a/src/Util/SystemInfo.cs b/src/Util/SystemInfo.cs index 8e04483..035fcc1 100644 --- a/src/Util/SystemInfo.cs +++ b/src/Util/SystemInfo.cs @@ -18,7 +18,9 @@ #endregion using System; +#if !NETSTANDARD1_3 using System.Configuration; +#endif using System.Reflection; using System.Text; using System.IO; @@ -143,7 +145,9 @@ namespace log4net.Util get { #if NETCF - return System.IO.Path.GetDirectoryName(SystemInfo.EntryAssemblyLocation) + System.IO.Path.DirectorySeparatorChar; +- return System.IO.Path.GetDirectoryName(SystemInfo.EntryAssemblyLocation) + System.IO.Path.DirectorySeparatorChar; +#elif NETSTANDARD1_3 + return Directory.GetCurrentDirectory(); #else return AppDomain.CurrentDomain.BaseDirectory; #endif @@ -168,7 +172,7 @@ namespace log4net.Util { get { -#if NETCF +#if NETCF || NETSTANDARD1_3 return SystemInfo.EntryAssemblyLocation+".config"; #else return System.AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; @@ -191,6 +195,8 @@ namespace log4net.Util { #if NETCF return SystemInfo.NativeEntryAssemblyLocation; +#elif NETSTANDARD1_3 // TODO GetEntryAssembly is available for netstandard1.5 + return AppContext.BaseDirectory; #else return System.Reflection.Assembly.GetEntryAssembly().Location; #endif @@ -225,7 +231,7 @@ namespace log4net.Util { #if NETCF_1_0 return System.Threading.Thread.CurrentThread.GetHashCode(); -#elif NET_2_0 || NETCF_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0 +#elif NET_2_0 || NETCF_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0 || NETSTANDARD1_3 return System.Threading.Thread.CurrentThread.ManagedThreadId; #else return AppDomain.GetCurrentThreadId(); @@ -283,7 +289,9 @@ namespace log4net.Util { try { -#if (!SSCLI && !NETCF) +#if NETSTANDARD1_3 + s_hostName = Environment.GetEnvironmentVariable("COMPUTERNAME"); +#elif (!SSCLI && !NETCF) s_hostName = Environment.MachineName; #endif } @@ -331,7 +339,7 @@ namespace log4net.Util { try { -#if !NETCF +#if !(NETCF || NETSTANDARD1_3) s_appFriendlyName = AppDomain.CurrentDomain.FriendlyName; #endif } @@ -448,6 +456,8 @@ namespace log4net.Util { #if NETCF return "Not supported on Microsoft .NET Compact Framework"; +#elif NETSTANDARD1_3 // TODO Assembly.Location available in netstandard1.5 + return "Not supported on .NET Core"; #else if (myAssembly.GlobalAssemblyCache) { @@ -518,7 +528,12 @@ namespace log4net.Util /// public static string AssemblyQualifiedName(Type type) { - return type.FullName + ", " + type.Assembly.FullName; + return type.FullName + ", " +#if NETSTANDARD1_3 + + type.GetTypeInfo().Assembly.FullName; +#else + + type.Assembly.FullName; +#endif } /// @@ -570,7 +585,7 @@ namespace log4net.Util /// public static string AssemblyFileName(Assembly myAssembly) { -#if NETCF +#if NETCF || NETSTANDARD1_3 // TODO Assembly.Location is in netstandard1.5 System.Reflection // This is not very good because it assumes that only // the entry assembly can be an EXE. In fact multiple // EXEs can be loaded in to a process. @@ -615,9 +630,14 @@ namespace log4net.Util /// public static Type GetTypeFromString(Type relativeType, string typeName, bool throwOnError, bool ignoreCase) { +#if NETSTANDARD1_3 + return GetTypeFromString(relativeType.GetTypeInfo().Assembly, typeName, throwOnError, ignoreCase); +#else return GetTypeFromString(relativeType.Assembly, typeName, throwOnError, ignoreCase); +#endif } +#if !NETSTANDARD1_3 /// /// Loads the type specified in the type string. /// @@ -641,6 +661,7 @@ namespace log4net.Util { return GetTypeFromString(Assembly.GetCallingAssembly(), typeName, throwOnError, ignoreCase); } +#endif /// /// Loads the type specified in the type string. @@ -668,7 +689,9 @@ namespace log4net.Util if(typeName.IndexOf(',') == -1) { //LogLog.Debug(declaringType, "SystemInfo: Loading type ["+typeName+"] from assembly ["+relativeAssembly.FullName+"]"); -#if NETCF +#if NETSTANDARD1_3 + return relativeAssembly.GetType(typeName, throwOnError, ignoreCase); +#elif NETCF return relativeAssembly.GetType(typeName, throwOnError); #else // Attempt to lookup the type from the relativeAssembly @@ -948,7 +971,7 @@ namespace log4net.Util { try { -#if NETCF +#if NETCF || NETSTANDARD1_3 // Configuration APIs are not suported under the Compact Framework #elif NET_2_0 return ConfigurationManager.AppSettings[key]; diff --git a/src/Util/SystemStringFormat.cs b/src/Util/SystemStringFormat.cs index 4b57cc3..a852f39 100644 --- a/src/Util/SystemStringFormat.cs +++ b/src/Util/SystemStringFormat.cs @@ -109,7 +109,7 @@ namespace log4net.Util log4net.Util.LogLog.Warn(declaringType, "Exception while rendering format ["+format+"]", ex); return StringFormatError(ex, format, args); } -#if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0 +#if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0 && !NETSTANDARD1_3 catch { log4net.Util.LogLog.Warn(declaringType, "Exception while rendering format ["+format+"]"); @@ -148,7 +148,7 @@ namespace log4net.Util log4net.Util.LogLog.Error(declaringType, "INTERNAL ERROR during StringFormat error handling", ex); return "Exception during StringFormat. See Internal Log."; } -#if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0 +#if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0 && !NETSTANDARD1_3 catch { log4net.Util.LogLog.Error(declaringType, "INTERNAL ERROR during StringFormat error handling"); @@ -210,7 +210,7 @@ namespace log4net.Util { buffer.Append(""); } -#if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0 +#if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0 && !NETSTANDARD1_3 catch { buffer.Append(""); diff --git a/src/Util/TextWriterAdapter.cs b/src/Util/TextWriterAdapter.cs index 6738020..b68eae8 100644 --- a/src/Util/TextWriterAdapter.cs +++ b/src/Util/TextWriterAdapter.cs @@ -149,10 +149,17 @@ namespace log4net.Util /// /// /// +#if NETSTANDARD1_3 + virtual public void Close() + { + m_writer.Dispose(); + } +#else override public void Close() { m_writer.Close(); } +#endif /// /// Dispose this writer diff --git a/src/Util/TypeConverters/ConversionNotSupportedException.cs b/src/Util/TypeConverters/ConversionNotSupportedException.cs index b677aaf..86ae9fc 100644 --- a/src/Util/TypeConverters/ConversionNotSupportedException.cs +++ b/src/Util/TypeConverters/ConversionNotSupportedException.cs @@ -18,7 +18,7 @@ #endregion using System; -#if !NETCF +#if !(NETCF || NETSTANDARD1_3) using System.Runtime.Serialization; #endif @@ -39,7 +39,11 @@ namespace log4net.Util.TypeConverters #if !NETCF [Serializable] #endif +#if NETSTANDARD1_3 + public class ConversionNotSupportedException : Exception +#else public class ConversionNotSupportedException : ApplicationException +#endif { #region Public Instance Constructors @@ -88,7 +92,7 @@ namespace log4net.Util.TypeConverters #region Protected Instance Constructors -#if !NETCF +#if !(NETCF || NETSTANDARD1_3) /// /// Serialization constructor /// diff --git a/src/Util/TypeConverters/ConverterRegistry.cs b/src/Util/TypeConverters/ConverterRegistry.cs index 7727176..0ddfb12 100644 --- a/src/Util/TypeConverters/ConverterRegistry.cs +++ b/src/Util/TypeConverters/ConverterRegistry.cs @@ -19,6 +19,9 @@ using System; using System.Globalization; +#if NETSTANDARD1_3 +using System.Linq; +#endif using System.Reflection; using System.Collections; diff --git a/src/Util/TypeConverters/IPAddressConverter.cs b/src/Util/TypeConverters/IPAddressConverter.cs index 1683306..d9cbf32 100644 --- a/src/Util/TypeConverters/IPAddressConverter.cs +++ b/src/Util/TypeConverters/IPAddressConverter.cs @@ -116,7 +116,11 @@ namespace log4net.Util.TypeConverters } // Try to resolve via DNS. This is a blocking call. +#if NETSTANDARD1_3 + IPHostEntry host = Dns.GetHostEntryAsync(str).GetAwaiter().GetResult(); +#else IPHostEntry host = Dns.GetHostByName(str); +#endif if (host != null && host.AddressList != null && host.AddressList.Length > 0 && diff --git a/src/Util/TypeConverters/PatternStringConverter.cs b/src/Util/TypeConverters/PatternStringConverter.cs index 2c79552..723cc25 100644 --- a/src/Util/TypeConverters/PatternStringConverter.cs +++ b/src/Util/TypeConverters/PatternStringConverter.cs @@ -18,6 +18,9 @@ #endregion using System; +#if NETSTANDARD1_3 +using System.Reflection; +#endif using System.Text; using log4net.Util; diff --git a/src/Util/TypeConverters/TypeConverter.cs b/src/Util/TypeConverters/TypeConverter.cs index 8fc8150..3a6d6a9 100644 --- a/src/Util/TypeConverters/TypeConverter.cs +++ b/src/Util/TypeConverters/TypeConverter.cs @@ -19,6 +19,9 @@ using System; using System.Text; +#if NETSTANDARD1_3 +using System.Reflection; +#endif namespace log4net.Util.TypeConverters { @@ -77,7 +80,11 @@ namespace log4net.Util.TypeConverters string str = source as string; if (str != null) { +#if NETSTANDARD1_3 // TODO can we use ComponentModel here? + return SystemInfo.GetTypeFromString(GetType().GetTypeInfo().Assembly, str, true, true); +#else return SystemInfo.GetTypeFromString(str, true, true); +#endif } throw ConversionNotSupportedException.Create(typeof(Type), source); } diff --git a/tests/src/Appender/RollingFileAppenderTest.cs b/tests/src/Appender/RollingFileAppenderTest.cs index bcbae6e..0192b11 100644 --- a/tests/src/Appender/RollingFileAppenderTest.cs +++ b/tests/src/Appender/RollingFileAppenderTest.cs @@ -51,9 +51,10 @@ namespace log4net.Tests.Appender private int _MaxSizeRollBackups = 3; private CountingAppender _caRoot; private Logger _root; +#if !NETSTANDARD1_3 private CultureInfo _currentCulture; private CultureInfo _currentUICulture; - +#endif private class SilentErrorHandler : IErrorHandler { private StringBuilder m_buffer = new StringBuilder(); @@ -98,9 +99,9 @@ namespace log4net.Tests.Appender private static void ResetAndDeleteTestFiles() { // Regular users should not use the clear method lightly! - LogManager.GetRepository().ResetConfiguration(); - LogManager.GetRepository().Shutdown(); - ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Clear(); + Utils.GetRepository().ResetConfiguration(); + Utils.GetRepository().Shutdown(); + ((Repository.Hierarchy.Hierarchy)Utils.GetRepository()).Clear(); DeleteTestFiles(); } @@ -115,10 +116,12 @@ namespace log4net.Tests.Appender ResetAndDeleteTestFiles(); InitializeVariables(); +#if !NETSTANDARD1_3 // set correct thread culture _currentCulture = System.Threading.Thread.CurrentThread.CurrentCulture; _currentUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture; System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.InvariantCulture; +#endif } /// @@ -128,10 +131,12 @@ namespace log4net.Tests.Appender public void TearDown() { ResetAndDeleteTestFiles(); - + +#if !NETSTANDARD1_3 // restore previous culture System.Threading.Thread.CurrentThread.CurrentCulture = _currentCulture; System.Threading.Thread.CurrentThread.CurrentUICulture = _currentUICulture; +#endif } /// @@ -1107,7 +1112,7 @@ namespace log4net.Tests.Appender /// private void ConfigureRootAppender() { - _root = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; + _root = ((Repository.Hierarchy.Hierarchy)Utils.GetRepository()).Root; _root.Level = Level.Debug; _caRoot = new CountingAppender(); _root.AddAppender(_caRoot); @@ -1454,7 +1459,11 @@ namespace log4net.Tests.Appender private static void AssertFileEquals(string filename, string contents) { +#if NETSTANDARD1_3 + StreamReader sr = new StreamReader(new FileStream(filename, FileMode.Open)); +#else StreamReader sr = new StreamReader(filename); +#endif string logcont = sr.ReadToEnd(); sr.Close(); @@ -1709,7 +1718,6 @@ namespace log4net.Tests.Appender public void TestInterProcessLockRoll() { String filename = "test.log"; - bool locked; SilentErrorHandler sh = new SilentErrorHandler(); ILogger log = CreateLogger(filename, new FileAppender.InterProcessLock(), sh, 1, 2); diff --git a/tests/src/Appender/SmtpPickupDirAppenderTest.cs b/tests/src/Appender/SmtpPickupDirAppenderTest.cs index 9389430..a2e8f8c 100644 --- a/tests/src/Appender/SmtpPickupDirAppenderTest.cs +++ b/tests/src/Appender/SmtpPickupDirAppenderTest.cs @@ -84,9 +84,9 @@ namespace log4net.Tests.Appender private void ResetLogger() { // Regular users should not use the clear method lightly! - LogManager.GetRepository().ResetConfiguration(); - LogManager.GetRepository().Shutdown(); - ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Clear(); + Utils.GetRepository().ResetConfiguration(); + Utils.GetRepository().Shutdown(); + ((Repository.Hierarchy.Hierarchy)Utils.GetRepository()).Clear(); } /// diff --git a/tests/src/Appender/TraceAppenderTest.cs b/tests/src/Appender/TraceAppenderTest.cs index 306ac16..21e8fbd 100644 --- a/tests/src/Appender/TraceAppenderTest.cs +++ b/tests/src/Appender/TraceAppenderTest.cs @@ -55,6 +55,7 @@ namespace log4net.Tests.Appender categoryTraceListener.Category); } +#if !NETSTANDARD1_3 // "LocationInfo can't get method names on NETSTANDARD1_3 due to unavailable stack frame APIs" [Test] public void MethodNameCategoryTest() { @@ -80,6 +81,7 @@ namespace log4net.Tests.Appender System.Reflection.MethodInfo.GetCurrentMethod().Name, categoryTraceListener.Category); } +#endif } public class CategoryTraceListener : TraceListener diff --git a/tests/src/Core/FixingTest.cs b/tests/src/Core/FixingTest.cs index 5415f02..badf963 100644 --- a/tests/src/Core/FixingTest.cs +++ b/tests/src/Core/FixingTest.cs @@ -33,7 +33,11 @@ namespace log4net.Tests.Core { const string TEST_REPOSITORY = "Test Repository"; +#if NETSTANDARD1_3 + [OneTimeSetUp] +#else [TestFixtureSetUp] +#endif public void CreateRepository() { bool exists = false; @@ -139,7 +143,9 @@ namespace log4net.Tests.Core Assert.AreEqual("System.Exception: This is the exception", loggingEvent.GetExceptionString(), "Exception is incorrect"); Assert.AreEqual(null, loggingEventData.Identity, "Identity is incorrect"); Assert.AreEqual(Level.Warn, loggingEventData.Level, "Level is incorrect"); +#if !NETSTANDARD1_3 // NETSTANDARD1_3: LocationInfo can't get method names Assert.AreEqual("get_LocationInformation", loggingEvent.LocationInformation.MethodName, "Location Info is incorrect"); +#endif Assert.AreEqual("log4net.Tests.Core.FixingTest", loggingEventData.LoggerName, "LoggerName is incorrect"); Assert.AreEqual(LogManager.GetRepository(TEST_REPOSITORY), loggingEvent.Repository, "Repository is incorrect"); Assert.AreEqual(Thread.CurrentThread.Name, loggingEventData.ThreadName, "ThreadName is incorrect"); diff --git a/tests/src/Core/StringFormatTest.cs b/tests/src/Core/StringFormatTest.cs index e7b0d93..16c7b5a 100644 --- a/tests/src/Core/StringFormatTest.cs +++ b/tests/src/Core/StringFormatTest.cs @@ -40,6 +40,7 @@ namespace log4net.Tests.Core [TestFixture] public class StringFormatTest { +#if !NETSTANDARD1_3 private CultureInfo _currentCulture; private CultureInfo _currentUICulture; @@ -59,6 +60,7 @@ namespace log4net.Tests.Core System.Threading.Thread.CurrentThread.CurrentCulture = _currentCulture; System.Threading.Thread.CurrentThread.CurrentUICulture = _currentUICulture; } +#endif [Test] public void TestFormatString() diff --git a/tests/src/Hierarchy/Hierarchy.cs b/tests/src/Hierarchy/Hierarchy.cs index 8578566..3755d7b 100644 --- a/tests/src/Hierarchy/Hierarchy.cs +++ b/tests/src/Hierarchy/Hierarchy.cs @@ -67,7 +67,8 @@ namespace log4net.Tests.Hierarchy CountingAppender beta = new CountingAppender(); Repository.Hierarchy.Hierarchy hierarchy = - (Repository.Hierarchy.Hierarchy)LogManager.GetRepository(); + (Repository.Hierarchy.Hierarchy)Utils.GetRepository(); + hierarchy.Root.AddAppender(alpha); hierarchy.Root.AddAppender(beta); hierarchy.Configured = true; @@ -85,7 +86,11 @@ namespace log4net.Tests.Hierarchy CountingAppender alpha = new CountingAppender(); CountingAppender beta = new CountingAppender(); +#if NETSTANDARD1_3 + BasicConfigurator.Configure(Utils.GetRepository(), alpha, beta); +#else BasicConfigurator.Configure(alpha, beta); +#endif ILog log = LogManager.GetLogger(GetType()); log.Debug("Hello World"); diff --git a/tests/src/Hierarchy/Logger.cs b/tests/src/Hierarchy/Logger.cs index 7913554..776dbd6 100644 --- a/tests/src/Hierarchy/Logger.cs +++ b/tests/src/Hierarchy/Logger.cs @@ -25,6 +25,10 @@ using log4net.Tests.Appender; using NUnit.Framework; +#if NETSTANDARD1_3 +using System.Reflection; +#endif + namespace log4net.Tests.Hierarchy { /// @@ -57,9 +61,9 @@ namespace log4net.Tests.Hierarchy public void TearDown() { // Regular users should not use the clear method lightly! - LogManager.GetRepository().ResetConfiguration(); - LogManager.GetRepository().Shutdown(); - ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Clear(); + Utils.GetRepository().ResetConfiguration(); + Utils.GetRepository().Shutdown(); + ((Repository.Hierarchy.Hierarchy)Utils.GetRepository()).Clear(); } /// @@ -68,7 +72,7 @@ namespace log4net.Tests.Hierarchy [Test] public void TestAppender1() { - log = (Logger)LogManager.GetLogger("test").Logger; + log = (Logger)Utils.GetLogger("test").Logger; CountingAppender a1 = new CountingAppender(); a1.Name = "testAppender1"; log.AddAppender(a1); @@ -91,7 +95,7 @@ namespace log4net.Tests.Hierarchy CountingAppender a2 = new CountingAppender(); a2.Name = "testAppender2.2"; - log = (Logger)LogManager.GetLogger("test").Logger; + log = (Logger)Utils.GetLogger("test").Logger; log.AddAppender(a1); log.AddAppender(a2); @@ -119,8 +123,8 @@ namespace log4net.Tests.Hierarchy [Test] public void TestAdditivity1() { - Logger a = (Logger)LogManager.GetLogger("a").Logger; - Logger ab = (Logger)LogManager.GetLogger("a.b").Logger; + Logger a = (Logger)Utils.GetLogger("a").Logger; + Logger ab = (Logger)Utils.GetLogger("a.b").Logger; CountingAppender ca = new CountingAppender(); a.AddAppender(ca); @@ -143,10 +147,10 @@ namespace log4net.Tests.Hierarchy [Test] public void TestAdditivity2() { - Logger a = (Logger)LogManager.GetLogger("a").Logger; - Logger ab = (Logger)LogManager.GetLogger("a.b").Logger; - Logger abc = (Logger)LogManager.GetLogger("a.b.c").Logger; - Logger x = (Logger)LogManager.GetLogger("x").Logger; + Logger a = (Logger)Utils.GetLogger("a").Logger; + Logger ab = (Logger)Utils.GetLogger("a.b").Logger; + Logger abc = (Logger)Utils.GetLogger("a.b.c").Logger; + Logger x = (Logger)Utils.GetLogger("x").Logger; CountingAppender ca1 = new CountingAppender(); CountingAppender ca2 = new CountingAppender(); @@ -177,10 +181,10 @@ namespace log4net.Tests.Hierarchy [Test] public void TestAdditivity3() { - Logger root = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; - Logger a = (Logger)LogManager.GetLogger("a").Logger; - Logger ab = (Logger)LogManager.GetLogger("a.b").Logger; - Logger abc = (Logger)LogManager.GetLogger("a.b.c").Logger; + Logger root = ((Repository.Hierarchy.Hierarchy)Utils.GetRepository()).Root; + Logger a = (Logger)Utils.GetLogger("a").Logger; + Logger ab = (Logger)Utils.GetLogger("a.b").Logger; + Logger abc = (Logger)Utils.GetLogger("a.b.c").Logger; CountingAppender caRoot = new CountingAppender(); CountingAppender caA = new CountingAppender(); @@ -220,10 +224,10 @@ namespace log4net.Tests.Hierarchy public void TestDisable1() { CountingAppender caRoot = new CountingAppender(); - Logger root = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; + Logger root = ((Repository.Hierarchy.Hierarchy)Utils.GetRepository()).Root; root.AddAppender(caRoot); - Repository.Hierarchy.Hierarchy h = ((Repository.Hierarchy.Hierarchy)LogManager.GetRepository()); + Repository.Hierarchy.Hierarchy h = ((Repository.Hierarchy.Hierarchy)Utils.GetRepository()); h.Threshold = Level.Info; h.Configured = true; @@ -271,11 +275,20 @@ namespace log4net.Tests.Hierarchy [Test] public void TestExists() { - object a = LogManager.GetLogger("a"); - object a_b = LogManager.GetLogger("a.b"); - object a_b_c = LogManager.GetLogger("a.b.c"); + object a = Utils.GetLogger("a"); + object a_b = Utils.GetLogger("a.b"); + object a_b_c = Utils.GetLogger("a.b.c"); object t; +#if NETSTANDARD1_3 + Assert.IsNull(LogManager.Exists(GetType().GetTypeInfo().Assembly, "xx")); + t = LogManager.Exists(GetType().GetTypeInfo().Assembly, "a"); + Assert.AreSame(a, t); + t = LogManager.Exists(GetType().GetTypeInfo().Assembly, "a.b"); + Assert.AreSame(a_b, t); + t = LogManager.Exists(GetType().GetTypeInfo().Assembly, "a.b.c"); + Assert.AreSame(a_b_c, t); +#else t = LogManager.Exists("xx"); Assert.IsNull(t); t = LogManager.Exists("a"); @@ -284,6 +297,7 @@ namespace log4net.Tests.Hierarchy Assert.AreSame(a_b, t); t = LogManager.Exists("a.b.c"); Assert.AreSame(a_b_c, t); +#endif } /// diff --git a/tests/src/Hierarchy/XmlHierarchyConfiguratorTest.cs b/tests/src/Hierarchy/XmlHierarchyConfiguratorTest.cs index 8bd1bab..05f1586 100644 --- a/tests/src/Hierarchy/XmlHierarchyConfiguratorTest.cs +++ b/tests/src/Hierarchy/XmlHierarchyConfiguratorTest.cs @@ -45,6 +45,7 @@ namespace log4net.Tests.Hierarchy } } +#if !NETSTANDARD1_3 // TODO write replacement test [Test][Platform(Include="Win")] public void EnvironmentOnWindowsIsCaseInsensitive() { @@ -58,6 +59,7 @@ namespace log4net.Tests.Hierarchy SetTestPropWithPath(); Assert.AreEqual("Path=", TestProp); } +#endif private void SetTestPropWithPath() { diff --git a/tests/src/Layout/PatternLayoutTest.cs b/tests/src/Layout/PatternLayoutTest.cs index c8ee77c..49ced68 100644 --- a/tests/src/Layout/PatternLayoutTest.cs +++ b/tests/src/Layout/PatternLayoutTest.cs @@ -42,6 +42,7 @@ namespace log4net.Tests.Layout [TestFixture] public class PatternLayoutTest { +#if !NETSTANDARD1_3 private CultureInfo _currentCulture; private CultureInfo _currentUICulture; @@ -62,6 +63,7 @@ namespace log4net.Tests.Layout System.Threading.Thread.CurrentThread.CurrentCulture = _currentCulture; System.Threading.Thread.CurrentThread.CurrentUICulture = _currentUICulture; } +#endif protected virtual PatternLayout NewPatternLayout() { return new PatternLayout(); @@ -99,7 +101,11 @@ namespace log4net.Tests.Layout stringAppender.Reset(); } +#if NETSTANDARD1_3 + [Test, Ignore("System.Diagnostics.StackTrace isn't fully implemented on NETSTANDARD1_3")] +#else [Test] +#endif public void TestStackTracePattern() { StringAppender stringAppender = new StringAppender(); diff --git a/tests/src/Layout/XmlLayoutTest.cs b/tests/src/Layout/XmlLayoutTest.cs index 937c8a7..f6a8711 100644 --- a/tests/src/Layout/XmlLayoutTest.cs +++ b/tests/src/Layout/XmlLayoutTest.cs @@ -36,6 +36,7 @@ namespace log4net.Tests.Layout [TestFixture] public class XmlLayoutTest { +#if !NETSTANDARD1_3 private CultureInfo _currentCulture; private CultureInfo _currentUICulture; @@ -55,6 +56,7 @@ namespace log4net.Tests.Layout System.Threading.Thread.CurrentThread.CurrentCulture = _currentCulture; System.Threading.Thread.CurrentThread.CurrentUICulture = _currentUICulture; } +#endif /// /// Build a basic object with some default values. @@ -81,7 +83,7 @@ namespace log4net.Tests.Layout private static string CreateEventNode(string message) { return String.Format("{1}" + Environment.NewLine, -#if NET_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0 +#if NET_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0 || NETSTANDARD1_3 XmlConvert.ToString(DateTime.Today, XmlDateTimeSerializationMode.Local), #else XmlConvert.ToString(DateTime.Today), @@ -92,7 +94,7 @@ namespace log4net.Tests.Layout private static string CreateEventNode(string key, string value) { return String.Format("Test message" + Environment.NewLine, -#if NET_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0 +#if NET_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0 || NETSTANDARD1_3 XmlConvert.ToString(DateTime.Today, XmlDateTimeSerializationMode.Local), #else XmlConvert.ToString(DateTime.Today), @@ -303,7 +305,7 @@ namespace log4net.Tests.Layout Assert.AreEqual(expected, stringAppender.GetString()); } -#if NET_4_0 || MONO_4_0 +#if NET_4_0 || MONO_4_0 || NETSTANDARD1_3 [Test] public void BracketsInStackTracesKeepLogWellFormed() { XmlLayout layout = new XmlLayout(); @@ -347,8 +349,13 @@ namespace log4net.Tests.Layout bar(42); var log = stringAppender.GetString(); +#if NETSTANDARD1_3 + var startOfExceptionText = log.IndexOf("", StringComparison.Ordinal) + 11; + var endOfExceptionText = log.IndexOf("", StringComparison.Ordinal); +#else var startOfExceptionText = log.IndexOf("", StringComparison.InvariantCulture) + 11; var endOfExceptionText = log.IndexOf("", StringComparison.InvariantCulture); +#endif var sub = log.Substring(startOfExceptionText, endOfExceptionText - startOfExceptionText); if (sub.StartsWith(" /// It's "does not throw not supported exception" NOT /// "returns 'Dynamic Assembly' string for dynamic assemblies" by purpose. @@ -65,7 +65,11 @@ namespace log4net.Tests.Util public static string TestAssemblyLocationInfoMethod() { +#if NETSTANDARD1_3 + return SystemInfo.AssemblyLocationInfo(typeof(SystemInfoTest).GetTypeInfo().Assembly); +#else return SystemInfo.AssemblyLocationInfo(Assembly.GetCallingAssembly()); +#endif } #endif @@ -74,57 +78,62 @@ namespace log4net.Tests.Util { Type t; - t = SystemInfo.GetTypeFromString("log4net.Tests.Util.SystemInfoTest,log4net.Tests", false, false); + t = GetTypeFromString("log4net.Tests.Util.SystemInfoTest,log4net.Tests", false, false); Assert.AreSame(typeof(SystemInfoTest), t, "Test explicit case sensitive type load"); - t = SystemInfo.GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST,log4net.Tests", false, true); + t = GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST,log4net.Tests", false, true); Assert.AreSame(typeof(SystemInfoTest), t, "Test explicit case in-sensitive type load caps"); - t = SystemInfo.GetTypeFromString("log4net.tests.util.systeminfotest,log4net.Tests", false, true); + t = GetTypeFromString("log4net.tests.util.systeminfotest,log4net.Tests", false, true); Assert.AreSame(typeof(SystemInfoTest), t, "Test explicit case in-sensitive type load lower"); } - [Test][Platform(Include="Win")] +#if !NETSTANDARD1_3 + [Test][Platform(Include="Win")] public void TestGetTypeFromStringCaseInsensitiveOnAssemblyName() { Type t; - t = SystemInfo.GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST,LOG4NET.TESTS", false, true); + t = GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST,LOG4NET.TESTS", false, true); Assert.AreSame(typeof(SystemInfoTest), t, "Test explicit case in-sensitive type load caps"); - t = SystemInfo.GetTypeFromString("log4net.tests.util.systeminfotest,log4net.tests", false, true); + t = GetTypeFromString("log4net.tests.util.systeminfotest,log4net.tests", false, true); Assert.AreSame(typeof(SystemInfoTest), t, "Test explicit case in-sensitive type load lower"); } +#endif [Test] public void TestGetTypeFromStringRelative() { Type t; - t = SystemInfo.GetTypeFromString("log4net.Tests.Util.SystemInfoTest", false, false); + t = GetTypeFromString("log4net.Tests.Util.SystemInfoTest", false, false); Assert.AreSame(typeof(SystemInfoTest), t, "Test explicit case sensitive type load"); - t = SystemInfo.GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST", false, true); + t = GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST", false, true); Assert.AreSame(typeof(SystemInfoTest), t, "Test explicit case in-sensitive type load caps"); - t = SystemInfo.GetTypeFromString("log4net.tests.util.systeminfotest", false, true); + t = GetTypeFromString("log4net.tests.util.systeminfotest", false, true); Assert.AreSame(typeof(SystemInfoTest), t, "Test explicit case in-sensitive type load lower"); } +#if NETSTANDARD1_3 + [Ignore("This test relies on enumerating loaded assemblies, which is presently impossible in CoreFX (https://github.com/dotnet/corefx/issues/1784).")] +#endif [Test] public void TestGetTypeFromStringSearch() { Type t; - t = SystemInfo.GetTypeFromString("log4net.Util.SystemInfo", false, false); + t = GetTypeFromString("log4net.Util.SystemInfo", false, false); Assert.AreSame(typeof(SystemInfo), t, string.Format("Test explicit case sensitive type load found {0} rather than {1}", t.AssemblyQualifiedName, typeof(SystemInfo).AssemblyQualifiedName)); - t = SystemInfo.GetTypeFromString("LOG4NET.UTIL.SYSTEMINFO", false, true); + t = GetTypeFromString("LOG4NET.UTIL.SYSTEMINFO", false, true); Assert.AreSame(typeof(SystemInfo), t, "Test explicit case in-sensitive type load caps"); - t = SystemInfo.GetTypeFromString("log4net.util.systeminfo", false, true); + t = GetTypeFromString("log4net.util.systeminfo", false, true); Assert.AreSame(typeof(SystemInfo), t, "Test explicit case in-sensitive type load lower"); } @@ -133,10 +142,10 @@ namespace log4net.Tests.Util { Type t; - t = SystemInfo.GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST,LOG4NET.TESTS", false, false); + t = GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST,LOG4NET.TESTS", false, false); Assert.AreSame(null, t, "Test explicit case sensitive fails type load"); - t = SystemInfo.GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST,LOG4NET.TESTS", true, false); + t = GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST,LOG4NET.TESTS", true, false); } [Test, ExpectedException(typeof(TypeLoadException))] @@ -144,10 +153,22 @@ namespace log4net.Tests.Util { Type t; - t = SystemInfo.GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST", false, false); + t = GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST", false, false); Assert.AreSame(null, t, "Test explicit case sensitive fails type load"); - t = SystemInfo.GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST", true, false); + t = GetTypeFromString("LOG4NET.TESTS.UTIL.SYSTEMINFOTEST", true, false); + } + + // Wraps SystemInfo.GetTypeFromString because the method relies on GetCallingAssembly, which is + // unavailable in CoreFX. As a workaround, only overloads which explicitly take a Type or Assembly + // are exposed for NETSTANDARD1_3. + private Type GetTypeFromString(string typeName, bool throwOnError, bool ignoreCase) + { +#if NETSTANDARD1_3 + return SystemInfo.GetTypeFromString(GetType().GetTypeInfo().Assembly, typeName, throwOnError, ignoreCase); +#else + return SystemInfo.GetTypeFromString(typeName, throwOnError, ignoreCase); +#endif } } } diff --git a/tests/src/Utils.cs b/tests/src/Utils.cs index 4e98283..5cbfb9c 100644 --- a/tests/src/Utils.cs +++ b/tests/src/Utils.cs @@ -17,6 +17,7 @@ // #endregion +using log4net.Repository; using System; using System.Reflection; @@ -43,12 +44,20 @@ namespace log4net.Tests public static object InvokeMethod(object target, string name, params object[] args) { +#if NETSTANDARD1_3 + return target.GetType().GetTypeInfo().GetDeclaredMethod(name).Invoke(target, args); +#else return target.GetType().GetMethod(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance, null, GetTypesArray(args), null).Invoke(target, args); +#endif } public static object InvokeMethod(Type target, string name, params object[] args) { +#if NETSTANDARD1_3 + return target.GetTypeInfo().GetDeclaredMethod(name).Invoke(null, args); +#else return target.GetMethod(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, null, GetTypesArray(args), null).Invoke(null, args); +#endif } public static object GetField(object target, string name) @@ -105,7 +114,28 @@ namespace log4net.Tests internal static void RemovePropertyFromAllContexts() { GlobalContext.Properties.Remove(PROPERTY_KEY); ThreadContext.Properties.Remove(PROPERTY_KEY); +#if !(NETCF || NETSTANDARD1_3) LogicalThreadContext.Properties.Remove(PROPERTY_KEY); +#endif } - } + + // Wrappers because repository/logger retrieval APIs require an Assembly argument on NETSTANDARD1_3 + internal static ILog GetLogger(string name) + { +#if NETSTANDARD1_3 + return LogManager.GetLogger(typeof(Utils).GetTypeInfo().Assembly, name); +#else + return LogManager.GetLogger(name); +#endif + } + + internal static ILoggerRepository GetRepository() + { +#if NETSTANDARD1_3 + return LogManager.GetRepository(typeof(Utils).GetTypeInfo().Assembly); +#else + return LogManager.GetRepository(); +#endif + } + } } \ No newline at end of file -- 2.7.4.windows.1