From e81439ae1b5661cad1b099c361d8230a7bda56e9 Mon Sep 17 00:00:00 2001 From: Thibaud DESODT Date: Tue, 21 Nov 2017 17:51:04 +0100 Subject: [PATCH] Extend the class::static handling to also support public static fields --- .../KeyValuePairs/SettingValueConversions.cs | 18 +++++++++++++++--- .../Settings/KeyValuePairSettingsTests.cs | 2 +- .../Settings/SettingValueConversionsTests.cs | 12 +++++++++--- .../Support/StaticAccessorClasses.cs | 12 +++++++++++- 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/Serilog/Settings/KeyValuePairs/SettingValueConversions.cs b/src/Serilog/Settings/KeyValuePairs/SettingValueConversions.cs index f1069af67..230f1943c 100644 --- a/src/Serilog/Settings/KeyValuePairs/SettingValueConversions.cs +++ b/src/Serilog/Settings/KeyValuePairs/SettingValueConversions.cs @@ -44,11 +44,23 @@ public static object ConvertToType(string value, Type toType) .Where(x => x.GetMethod.IsPublic) .FirstOrDefault(x => x.GetMethod.IsStatic); - if (publicStaticPropertyInfo == null) + if (publicStaticPropertyInfo != null) { - throw new InvalidOperationException($"Could not find public static property `{memberName}` on type `{accessorTypeName}`"); + return publicStaticPropertyInfo.GetValue(null); // static property, no instance to pass } - return publicStaticPropertyInfo.GetValue(null); // static property, no instance to pass + + // no property ? look for a field + var publicStaticFieldInfo = accessorType.GetTypeInfo().DeclaredFields + .Where(x => x.Name == memberName) + .Where(x => x.IsPublic) + .FirstOrDefault(x => x.IsStatic); + + if (publicStaticFieldInfo != null) + { + return publicStaticFieldInfo.GetValue(null); // static field, no instance to pass + } + + throw new InvalidOperationException($"Could not find a public static property or field with name `{memberName}` on type `{accessorTypeName}`"); } var toTypeInfo = toType.GetTypeInfo(); diff --git a/test/Serilog.Tests/Settings/KeyValuePairSettingsTests.cs b/test/Serilog.Tests/Settings/KeyValuePairSettingsTests.cs index fcceea943..52502daa9 100644 --- a/test/Serilog.Tests/Settings/KeyValuePairSettingsTests.cs +++ b/test/Serilog.Tests/Settings/KeyValuePairSettingsTests.cs @@ -325,7 +325,7 @@ public void LoggingLevelSwitchCanBeUsedForMinimumLevelOverrides() var systemLogger = log.ForContext(Constants.SourceContextPropertyName, "System.Bar"); log.Write(Some.InformationEvent()); - Assert.False(evt is null, "Minimul level is Debug. It should log Information messages"); + Assert.False(evt is null, "Minimum level is Debug. It should log Information messages"); evt = null; // ReSharper disable HeuristicUnreachableCode diff --git a/test/Serilog.Tests/Settings/SettingValueConversionsTests.cs b/test/Serilog.Tests/Settings/SettingValueConversionsTests.cs index c03273ff6..c0a33a474 100644 --- a/test/Serilog.Tests/Settings/SettingValueConversionsTests.cs +++ b/test/Serilog.Tests/Settings/SettingValueConversionsTests.cs @@ -125,6 +125,8 @@ public void TryParseStaticMemberAccessorReturnsExpectedResults(string input, str [Theory] [InlineData("Serilog.Tests.Support.ClassWithStaticAccessors::StringProperty, Serilog.Tests", typeof(string), "StringProperty")] [InlineData("Serilog.Tests.Support.ClassWithStaticAccessors::IntProperty, Serilog.Tests", typeof(int), 42)] + [InlineData("Serilog.Tests.Support.ClassWithStaticAccessors::StringField, Serilog.Tests", typeof(string), "StringField")] + [InlineData("Serilog.Tests.Support.ClassWithStaticAccessors::IntField, Serilog.Tests", typeof(int), 666)] public void StaticMembersAccessorsCanBeUsedForSImpleTypes(string input, Type targetType, object expectedValue) { var actual = SettingValueConversions.ConvertToType(input, targetType); @@ -136,6 +138,8 @@ public void StaticMembersAccessorsCanBeUsedForSImpleTypes(string input, Type tar [Theory] [InlineData("Serilog.Tests.Support.ClassWithStaticAccessors::InterfaceProperty, Serilog.Tests", typeof(IAmAnInterface))] [InlineData("Serilog.Tests.Support.ClassWithStaticAccessors::AbstractProperty, Serilog.Tests", typeof(AnAbstractClass))] + [InlineData("Serilog.Tests.Support.ClassWithStaticAccessors::InterfaceField, Serilog.Tests", typeof(IAmAnInterface))] + [InlineData("Serilog.Tests.Support.ClassWithStaticAccessors::AbstractField, Serilog.Tests", typeof(AnAbstractClass))] public void StaticMembersAccessorsCanBeUsedForReferenceTypes(string input, Type targetType) { var actual = SettingValueConversions.ConvertToType(input, targetType); @@ -164,17 +168,19 @@ public void StaticAccessorOnUnknownTypeThrowsTypeLoadException(string input, Typ [InlineData("Serilog.Tests.Support.ClassWithStaticAccessors::UnknownMember, Serilog.Tests", typeof(string))] // static property exists but it's private [InlineData("Serilog.Tests.Support.ClassWithStaticAccessors::PrivateStringProperty, Serilog.Tests", typeof(string))] - // public member exists but it's a field - [InlineData("Serilog.Tests.Support.ClassWithStaticAccessors::StringField, Serilog.Tests", typeof(string))] + // static field exists but it's private + [InlineData("Serilog.Tests.Support.ClassWithStaticAccessors::PrivateStringField, Serilog.Tests", typeof(string))] // public property exists but it's not static [InlineData("Serilog.Tests.Support.ClassWithStaticAccessors::InstanceStringProperty, Serilog.Tests", typeof(string))] + // public field exists but it's not static + [InlineData("Serilog.Tests.Support.ClassWithStaticAccessors::InstanceStringField, Serilog.Tests", typeof(string))] public void StaticAccessorWithInvalidMemberThrowsInvalidOperationException(string input, Type targetType) { var exception = Assert.Throws(() => SettingValueConversions.ConvertToType(input, targetType) ); - Assert.Contains("Could not find public static property ", exception.Message); + Assert.Contains("Could not find a public static property or field ", exception.Message); Assert.Contains("on type `Serilog.Tests.Support.ClassWithStaticAccessors, Serilog.Tests`", exception.Message); } } diff --git a/test/Serilog.Tests/Support/StaticAccessorClasses.cs b/test/Serilog.Tests/Support/StaticAccessorClasses.cs index e5f788c40..057886dca 100644 --- a/test/Serilog.Tests/Support/StaticAccessorClasses.cs +++ b/test/Serilog.Tests/Support/StaticAccessorClasses.cs @@ -27,9 +27,19 @@ public class ClassWithStaticAccessors public static int IntProperty => 42; public static IAmAnInterface InterfaceProperty => ConcreteImpl.Instance; public static AnAbstractClass AbstractProperty => ConcreteImpl.Instance; + + public static string StringField = nameof(StringField); + public static int IntField = 666; + public static IAmAnInterface InterfaceField = ConcreteImpl.Instance; + public static AnAbstractClass AbstractField = ConcreteImpl.Instance; + // ReSharper disable once UnusedMember.Local static string PrivateStringProperty => nameof(PrivateStringProperty); +#pragma warning disable 169 + static string PrivateStringField = nameof(PrivateStringField); +#pragma warning restore 169 public string InstanceStringProperty => nameof(InstanceStringProperty); - public static string StringField = nameof(StringField); + public string InstanceStringField = nameof(InstanceStringField); + } }