Skip to content

Commit

Permalink
SettingValueConversions.ConvertToType() value cant be null (serilog#1721
Browse files Browse the repository at this point in the history
)

* SettingValueConversions.ConvertToType() value cant be null

* Update KeyValuePairSettings.cs

* Update SettingValueConversionsTests.cs
  • Loading branch information
SimonCropp authored and Twinki14 committed Dec 30, 2023
1 parent 2b40ecb commit 3760984
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 33 deletions.
7 changes: 4 additions & 3 deletions src/Serilog/Settings/KeyValuePairs/KeyValuePairSettings.cs
Expand Up @@ -190,15 +190,16 @@ select new
throw new FormatException($"\"{switchName}\" is not a valid name for a Level Switch declaration. Level switch must be declared with a '$' sign, like \"level-switch:$switchName\"");
}
LoggingLevelSwitch newSwitch;
if (string.IsNullOrEmpty(switchInitialLevel))
if (switchInitialLevel == String.Empty)
{
newSwitch = new();
}
else
{
var initialLevel = (LogEventLevel)SettingValueConversions.ConvertToType(switchInitialLevel, typeof(LogEventLevel));
var initialLevel = (LogEventLevel) Enum.Parse(typeof(LogEventLevel), switchInitialLevel);
newSwitch = new(initialLevel);
}

namedSwitches.Add(switchName, newSwitch);
}
return namedSwitches;
Expand All @@ -220,7 +221,7 @@ static object ConvertOrLookupByName(string valueOrSwitchName, Type type, IReadOn
{
return LookUpSwitchByName(valueOrSwitchName, declaredSwitches);
}
return SettingValueConversions.ConvertToType(valueOrSwitchName, type);
return SettingValueConversions.ConvertToType(valueOrSwitchName, type)!;
}

static void ApplyDirectives(List<IGrouping<string, ConfigurationMethodCall>> directives, IList<MethodInfo> configurationMethods, object loggerConfigMethod, IReadOnlyDictionary<string, LoggingLevelSwitch> declaredSwitches)
Expand Down
22 changes: 9 additions & 13 deletions src/Serilog/Settings/KeyValuePairs/SettingValueConversions.cs
Expand Up @@ -12,8 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#nullable enable
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
Expand All @@ -31,15 +33,15 @@ class SettingValueConversions
{
{ typeof(Uri), s => new Uri(s) },
{ typeof(TimeSpan), s => TimeSpan.Parse(s) },
{ typeof(Type), s => Type.GetType(s, throwOnError: true) },
{ typeof(Type), s => Type.GetType(s, throwOnError: true)! },
};

public static object ConvertToType(string value, Type toType)
public static object? ConvertToType(string value, Type toType)
{
var toTypeInfo = toType.GetTypeInfo();
if (toTypeInfo.IsGenericType && toType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
if (string.IsNullOrEmpty(value))
if (value == String.Empty)
return null;

// unwrap Nullable<> type since we're not handling null situations
Expand All @@ -64,13 +66,13 @@ public static object ConvertToType(string value, Type toType)
// like "Namespace.TypeName::StaticProperty, AssemblyName"
if (TryParseStaticMemberAccessor(value, out var accessorTypeName, out var memberName))
{
var accessorType = Type.GetType(accessorTypeName, throwOnError: true);
var accessorType = Type.GetType(accessorTypeName, throwOnError: true)!;
// is there a public static property with that name ?
var publicStaticPropertyInfo = accessorType.GetTypeInfo().DeclaredProperties
.Where(x => x.Name == memberName)
.Where(x => x.GetMethod != null)
.Where(x => x.GetMethod.IsPublic)
.FirstOrDefault(x => x.GetMethod.IsStatic);
.Where(x => x.GetMethod!.IsPublic)
.FirstOrDefault(x => x.GetMethod!.IsStatic);

if (publicStaticPropertyInfo != null)
{
Expand Down Expand Up @@ -134,14 +136,8 @@ public static object ConvertToType(string value, Type toType)
return Convert.ChangeType(value, toType);
}

internal static bool TryParseStaticMemberAccessor(string input, out string accessorTypeName, out string memberName)
internal static bool TryParseStaticMemberAccessor(string input, [NotNullWhen(true)] out string? accessorTypeName, [NotNullWhen(true)] out string? memberName)
{
if (input == null)
{
accessorTypeName = null;
memberName = null;
return false;
}
if (StaticMemberAccessorRegex.IsMatch(input))
{
var match = StaticMemberAccessorRegex.Match(input);
Expand Down
25 changes: 8 additions & 17 deletions test/Serilog.Tests/Settings/SettingValueConversionsTests.cs
Expand Up @@ -17,13 +17,6 @@ public void ConvertibleValuesConvertToTIfTargetIsNullable()
Assert.True(result == 3);
}

[Fact]
public void NullValuesConvertToNullIfTargetIsNullable()
{
var result = (int?)SettingValueConversions.ConvertToType(null, typeof(int?));
Assert.True(result == null);
}

[Fact]
public void EmptyStringValuesConvertToNullIfTargetIsNullable()
{
Expand All @@ -41,14 +34,14 @@ public void ValuesConvertToNullableTimeSpan()
[Fact]
public void ValuesConvertToEnumMembers()
{
var result = (LogEventLevel)SettingValueConversions.ConvertToType("Information", typeof(LogEventLevel));
var result = (LogEventLevel)SettingValueConversions.ConvertToType("Information", typeof(LogEventLevel))!;
Assert.Equal(LogEventLevel.Information, result);
}

[Fact]
public void ValuesConvertToStringArray()
{
var result = (string[])SettingValueConversions.ConvertToType("key1=value1,key2=value2", typeof(string[]));
var result = (string[])SettingValueConversions.ConvertToType("key1=value1,key2=value2", typeof(string[]))!;
Assert.Equal(2, result.Length);
Assert.Equal("key1=value1", result[0]);
Assert.Equal("key2=value2", result[1]);
Expand All @@ -57,14 +50,14 @@ public void ValuesConvertToStringArray()
[Fact]
public void ValuesConvertToStringArrayEmpty()
{
var result = (string[])SettingValueConversions.ConvertToType("", typeof(string[]));
var result = (string[])SettingValueConversions.ConvertToType("", typeof(string[]))!;
Assert.Empty(result);
}

[Fact]
public void ValuesConvertToIntArray()
{
var result = (int[])SettingValueConversions.ConvertToType("1,2", typeof(int[]));
var result = (int[])SettingValueConversions.ConvertToType("1,2", typeof(int[]))!;
Assert.Equal(2, result.Length);
Assert.Equal(1, result[0]);
Assert.Equal(2, result[1]);
Expand All @@ -73,22 +66,22 @@ public void ValuesConvertToIntArray()
[Fact]
public void ValuesConvertToIntArrayEmpty()
{
var result = (int[])SettingValueConversions.ConvertToType("", typeof(int[]));
var result = (int[])SettingValueConversions.ConvertToType("", typeof(int[]))!;
Assert.Empty(result);
}

[Fact]
public void ValuesConvertToTypeFromQualifiedName()
{
var result = (Type)SettingValueConversions.ConvertToType("System.Version", typeof(Type));
var result = (Type)SettingValueConversions.ConvertToType("System.Version", typeof(Type))!;
Assert.Equal(typeof(Version), result);
}

[Fact]
public void ValuesConvertToTypeFromAssemblyQualifiedName()
{
var assemblyQualifiedName = typeof(Version).AssemblyQualifiedName;
var result = (Type)SettingValueConversions.ConvertToType(assemblyQualifiedName, typeof(Type));
var assemblyQualifiedName = typeof(Version).AssemblyQualifiedName!;
var result = (Type)SettingValueConversions.ConvertToType(assemblyQualifiedName, typeof(Type))!;
Assert.Equal(typeof(Version), result);
}

Expand Down Expand Up @@ -147,8 +140,6 @@ public void TimeSpanValuesCanBeParsed(string input, int expDays, int expHours, i
null, null)]
[InlineData("ThereIsNoMemberHere::",
null, null)]
[InlineData(null,
null, null)]
[InlineData(" ",
null, null)]
// a full-qualified type name should not be considered a static member accessor
Expand Down

0 comments on commit 3760984

Please sign in to comment.