Skip to content

Commit

Permalink
Codes changes for nullable reference types.
Browse files Browse the repository at this point in the history
  • Loading branch information
LittleGitPhoenix committed Nov 23, 2021
1 parent 73a3ba8 commit 118c08a
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,15 @@ public class FileInfoConverter : JsonConverter<FileInfo>
/// <inheritdoc />
public override FileInfo Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var value = reader.GetString();
try
{
return new FileInfo(reader.GetString());
if (value is null) throw new NotSupportedException();
return new FileInfo(value);
}
catch (Exception)
{
throw new JsonException($"Cannot convert the value '{(reader.GetString() ?? "[NULL]")}' of type {reader.TokenType} into a {nameof(FileInfo)}.");
throw new JsonException($"Cannot convert the value '{value ?? "[NULL]"}' of type {reader.TokenType} into a {nameof(FileInfo)}.");
}
}

Expand All @@ -79,13 +81,15 @@ public class DirectoryInfoConverter : JsonConverter<DirectoryInfo>
/// <inheritdoc />
public override DirectoryInfo Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var value = reader.GetString();
try
{
return new DirectoryInfo(reader.GetString());
if (value is null) throw new NotSupportedException();
return new DirectoryInfo(value);
}
catch (Exception)
{
throw new JsonException($"Cannot convert the value '{(reader.GetString() ?? "[NULL]")}' of type {reader.TokenType} into a {nameof(DirectoryInfo)}.");
throw new JsonException($"Cannot convert the value '{value ?? "[NULL]"}' of type {reader.TokenType} into a {nameof(DirectoryInfo)}.");
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/Settings.Json.Net/CustomJsonConverters/RegexConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ public class RegexConverter : JsonConverter<Regex>
/// <inheritdoc />
public override Regex Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return new Regex(reader.GetString(), RegexOptions.IgnoreCase | RegexOptions.Compiled);
var value = reader.GetString() ?? ".*";
return new Regex(value, RegexOptions.IgnoreCase | RegexOptions.Compiled);
}

/// <inheritdoc />
Expand Down
89 changes: 44 additions & 45 deletions src/Settings.Json.Net/JsonSettingsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,9 @@


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Dynamic;
using System.IO;
using System.Linq;
using System.Net.Http.Headers;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Phoenix.Functionality.Settings.Cache;
Expand Down Expand Up @@ -87,7 +79,7 @@ public JsonSettingsManager(ISettingsCache cache) : this(null, cache) { }
/// </summary>
/// <param name="baseDirectory"> The directory where all setting files reside. </param>
/// <param name="cache"> An <see cref="ISettingsCache"/> used for caching all loaded settings instances. If this is <c>Null</c> then <see cref="NoSettingsCache"/> will be used. </param>
public JsonSettingsManager(DirectoryInfo baseDirectory, ISettingsCache cache)
public JsonSettingsManager(DirectoryInfo? baseDirectory, ISettingsCache? cache)
{
// Save parameters.
_baseDirectory = baseDirectory ?? new DirectoryInfo(Path.Combine(Directory.GetCurrentDirectory(), ".settings"));
Expand Down Expand Up @@ -167,7 +159,16 @@ public static IDirectoryJsonSettingsManagerBuilder Construct()
{
// YES: Deserialize it.
origin = SettingsOrigin.File;
settings = JsonSettingsManager.Deserialize<TSettings>(settingsFile);
var deserializedSettings = JsonSettingsManager.Deserialize<TSettings>(settingsFile);
if (deserializedSettings is null)
{
origin = SettingsOrigin.Default;
settings = JsonSettingsManager.GetDefaultInstance<TSettings>();
}
else
{
settings = deserializedSettings;
}
}

// Update the cache if needed.
Expand All @@ -182,17 +183,15 @@ public static IDirectoryJsonSettingsManagerBuilder Construct()
/// </summary>
/// <param name="settingsFile"> The settings file to deserialize. </param>
/// <returns> The deserialized settings object. </returns>
private static TSettings Deserialize<TSettings>(FileInfo settingsFile) where TSettings : class, ISettings, new()
private static TSettings? Deserialize<TSettings>(FileInfo settingsFile) where TSettings : class, ISettings, new()
{
if (settingsFile == null) throw new ArgumentNullException(nameof(settingsFile));
if (!settingsFile.Exists) throw new ArgumentException($"The settings file '{settingsFile.FullName}' does not exist.", nameof(settingsFile));

using (var stream = settingsFile.Open(FileMode.Open, FileAccess.Read))
{
// Directly deserialize the file into an instance of TSettings.
//? What about error handling for (partially) invalid json?
return JsonSerializer.DeserializeAsync<TSettings>(stream, JsonOptions.Instance, CancellationToken.None).Result;
}

// Directly deserialize the file into an instance of TSettings.
//? What about error handling for (partially) invalid json?
using var stream = settingsFile.Open(FileMode.Open, FileAccess.Read);
return JsonSerializer.DeserializeAsync<TSettings>(stream, JsonOptions.Instance, CancellationToken.None).Result;
}

/// <summary>
Expand All @@ -203,39 +202,41 @@ public static IDirectoryJsonSettingsManagerBuilder Construct()
/// <returns> <c>True</c> if they match, otherwise <c>False</c>. </returns>
public static async Task<bool> ShouldSettingsFileBeUpdatedAsync(FileInfo settingsFile, object settings)
{
var targetJsonDocument = JsonDocument.Parse(await JsonSettingsManager.SerializeAsync(settings));
var targetData = await JsonSettingsManager.ConvertJsonDocumentToData(targetJsonDocument);
var targetJsonDocument = JsonDocument.Parse(await JsonSettingsManager.SerializeAsync(settings).ConfigureAwait(false));
var targetData = await JsonSettingsManager.ConvertJsonDocumentToData(targetJsonDocument).ConfigureAwait(false);

#if NETSTANDARD2_0 || NETSTANDARD1_6 || NETSTANDARD1_5 || NETSTANDARD1_4 || NETSTANDARD1_3 || NETSTANDARD1_2 || NETSTANDARD1_1 || NETSTANDARD1_0
var actualJsonDocument = JsonDocument.Parse(File.ReadAllText(settingsFile.FullName));
#else
var actualJsonDocument = JsonDocument.Parse(await File.ReadAllTextAsync(settingsFile.FullName));
var actualJsonDocument = JsonDocument.Parse(await File.ReadAllTextAsync(settingsFile.FullName).ConfigureAwait(false));
#endif
var actualData = await JsonSettingsManager.ConvertJsonDocumentToData(actualJsonDocument);
var actualData = await JsonSettingsManager.ConvertJsonDocumentToData(actualJsonDocument).ConfigureAwait(false);

var areEqual = targetData.SequenceEqual(actualData);
return !areEqual;
}

private static async Task<byte[]> ConvertJsonDocumentToData(JsonDocument document)
{
using (var stream = new MemoryStream())
#if NETSTANDARD2_0 || NETSTANDARD1_6 || NETSTANDARD1_5 || NETSTANDARD1_4 || NETSTANDARD1_3 || NETSTANDARD1_2 || NETSTANDARD1_1 || NETSTANDARD1_0
using var stream = new MemoryStream();
#else
await using var stream = new MemoryStream();
#endif
await using (var writer = new Utf8JsonWriter(stream))
{
using (var writer = new Utf8JsonWriter(stream))
{
document.RootElement.WriteTo(writer);
//document.RootElement.WriteValue(writer); //.Net Core 3.0
await writer.FlushAsync();
}

stream.Seek(0, SeekOrigin.Begin);
return stream.ToArray();
document.RootElement.WriteTo(writer);
//document.RootElement.WriteValue(writer); //.Net Core 3.0
await writer.FlushAsync().ConfigureAwait(false);
}

stream.Seek(0, SeekOrigin.Begin);
return stream.ToArray();
}

#endregion
#endregion

#region Save
#region Save

/// <inheritdoc />
public void Save<TSettings>(TSettings settings, bool createBackup = default) where TSettings : ISettings
Expand Down Expand Up @@ -273,13 +274,11 @@ private static void Save(string jsonString, FileInfo settingsFile)
}

// Check if the directory of the file exists. Trying to create a file, whose directory is also not existing, will throw an exception.
if (!settingsFile.Directory.Exists) settingsFile.Directory.Create();
if (!settingsFile.Directory!.Exists) settingsFile.Directory.Create();

using (var fileStream = settingsFile.Open(FileMode.Create))
{
var jsonData = System.Text.Encoding.UTF8.GetBytes(jsonString);
fileStream.Write(jsonData, offset: 0, count: jsonData.Length);
}
using var fileStream = settingsFile.Open(FileMode.Create);
var jsonData = System.Text.Encoding.UTF8.GetBytes(jsonString);
fileStream.Write(jsonData, offset: 0, count: jsonData.Length);
}

/// <summary>
Expand All @@ -303,17 +302,17 @@ private static void CreateBackup(FileInfo settingsFile)
if (settingsFile.Exists)
{
// Create a backup of the current file.
var backupFolder = Path.Combine(settingsFile.DirectoryName, ".backup");
var backupFolder = Path.Combine(settingsFile.DirectoryName!, ".backup");
var backupFile = $"{Path.GetFileNameWithoutExtension(settingsFile.Name)}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}{settingsFile.Extension}";

Directory.CreateDirectory(backupFolder);
settingsFile.CopyTo(Path.Combine(backupFolder, backupFile), overwrite: true);
}
}

#endregion
#endregion

#region Helper
#region Helper

/// <summary>
/// Creates a default settings instance.
Expand Down Expand Up @@ -346,8 +345,8 @@ private static FileInfo GetSettingsFile(string settingsName, DirectoryInfo setti
return new FileInfo(Path.Combine(settingsDirectory.FullName, fileName));
}

#endregion
#endregion

#endregion
#endregion
}
}
4 changes: 2 additions & 2 deletions src/Settings.Json.Net/JsonSettingsManagerBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ public class JsonSettingsManagerBuilder

#region Fields

private DirectoryInfo _settingsDirectory;
private DirectoryInfo? _settingsDirectory;

private ISettingsCache _cache;
private ISettingsCache? _cache;

#endregion

Expand Down
2 changes: 1 addition & 1 deletion src/Settings.Json.Net/Settings.Json.Net.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<Nullable>enable</Nullable>
<AssemblyName>Phoenix.Functionality.Settings.Json.Net</AssemblyName>
<RootNamespace>Phoenix.Functionality.Settings.Json.Net</RootNamespace>
<Version>2.0.0</Version>
<Version>2.1.0</Version>
<Authors>Felix Leistner</Authors>
<Company>Little Phoenix</Company>
<Copyright>2021</Copyright>
Expand Down
13 changes: 12 additions & 1 deletion src/Settings.Json.Net/⬙/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
___

## 2.1.0 (2021-23-11)

### Changed

- If the value of a **RegEx** setting property is **null**, then the pattern **.\*** (anything) will be used.
- The project now fully uses [nullable reference types](https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references).

### Fixed

- A possible deadlock scenario when updating a settings file based on a changed class layout has been addressed.
___

## 2.0.0 (2021-11-01)

### Added
Expand All @@ -19,7 +31,6 @@ ___

:large_blue_circle: Phoenix.Functionality.Settings ~~1.1.0~~**2.0.0**
:large_blue_circle: System.Text.Json ~~4.7.0~~**5.0.2**

___

## 1.1.0 (2020-02-09)
Expand Down

0 comments on commit 118c08a

Please sign in to comment.