-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathConfigLoader.cs
More file actions
91 lines (81 loc) · 2.6 KB
/
Copy pathConfigLoader.cs
File metadata and controls
91 lines (81 loc) · 2.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
using System.Text.Json;
using CodeContext.Configuration;
using CodeContext.Interfaces;
namespace CodeContext.Services;
/// <summary>
/// Functional configuration loader with separated I/O and parsing logic.
/// </summary>
public class ConfigLoader
{
private const string ConfigFileName = "config.json";
private readonly IConsoleWriter _console;
public ConfigLoader(IConsoleWriter console)
{
_console = console;
}
/// <summary>
/// Loads configuration from config.json if it exists, otherwise returns default configuration.
/// I/O operation with functional error handling.
/// </summary>
public AppConfig Load() =>
ReadConfigFile(ConfigFileName)
.Match(
onSuccess: ParseConfig,
onError: HandleParseError);
/// <summary>
/// I/O operation: reads config file or returns empty JSON.
/// </summary>
private static Result<string> ReadConfigFile(string fileName)
{
try
{
var json = File.Exists(fileName) ? File.ReadAllText(fileName) : "{}";
return new Result<string>.Success(json);
}
catch (Exception ex)
{
return new Result<string>.Error(ex.Message);
}
}
/// <summary>
/// Pure function: parses JSON string into AppConfig.
/// </summary>
private AppConfig ParseConfig(string json)
{
try
{
return JsonSerializer.Deserialize<AppConfig>(json) ?? new AppConfig();
}
catch (JsonException ex)
{
_console.WriteLine($"⚠️ Warning: Invalid config.json format ({ex.Message}). Using defaults.");
return new AppConfig();
}
}
/// <summary>
/// Error handler: returns default config and logs error.
/// </summary>
private AppConfig HandleParseError(string error)
{
_console.WriteLine($"⚠️ Warning: Could not read config.json ({error}). Using defaults.");
return new AppConfig();
}
/// <summary>
/// Simple Result type for functional error handling.
/// </summary>
private abstract record Result<T>
{
private Result() { }
public sealed record Success(T Value) : Result<T>;
public sealed record Error(string Message) : Result<T>;
public TResult Match<TResult>(
Func<T, TResult> onSuccess,
Func<string, TResult> onError) =>
this switch
{
Success s => onSuccess(s.Value),
Error e => onError(e.Message),
_ => throw new InvalidOperationException()
};
}
}