Skip to content

Commit

Permalink
AddFile support handler with context
Browse files Browse the repository at this point in the history
  • Loading branch information
thohng committed May 14, 2024
1 parent 828f809 commit 23151ef
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 43 deletions.
111 changes: 69 additions & 42 deletions src/NetLah.Extensions.Configuration/AddFileConfigurationSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class AddFileConfigurationSource : IConfigurationSource
{
private readonly AddFileConfigurationSourceOptionsBuilder _options;
private readonly AddFileOptions _defaultOptions;
private readonly IEnumerable<Action<AddFileContext>> _handlers;
private string? _lastAddFileState;
private IConfigurationRoot? _lastConfiguration;

Expand All @@ -25,6 +26,7 @@ public AddFileConfigurationSource(AddFileConfigurationSourceOptionsBuilder optio
}
_defaultOptions = new AddFileOptions { Optional = true, ReloadOnChange = true };
options.TryAddProvider(".json", JsonConfigurationExtensions.AddJsonFile);
_handlers = new[] { DefaultAddFileByProvider }.Concat(_options.Handlers);
}

public IConfigurationProvider Build(IConfigurationBuilder builder)
Expand Down Expand Up @@ -62,47 +64,78 @@ public IConfigurationProvider Build(IConfigurationBuilder builder)

foreach (var item in configurationSection.GetChildren())
{
var context = new AddFileContext
{
Configuration = item,
ConfigurationBuilder = configurationBuilder,
Logger = logger,
SupportedExtensions = supportedExtensions,
IsProcessed = false,
};

var processed = false;

if (item.Value is { } value1)
{
var extensionOrType = Path.GetExtension(value1);
AddFile(extensionOrType, new AddFileSource
var extensionOrProvider = Path.GetExtension(value1);
context.Provider = extensionOrProvider;
context.Source = new AddFileSource
{
LoggingLevel = _defaultOptions.LoggingLevel,
Optional = _defaultOptions.Optional,
ReloadOnChange = _defaultOptions.ReloadOnChange,
Path = value1,
});
OriginalPath = value1,
};
}
else if (item.Value == null && item["Provider"] is { } typeValue1 &&
("Settings".Equals(typeValue1, StringComparison.OrdinalIgnoreCase) || "DefaultSettings".Equals(typeValue1, StringComparison.OrdinalIgnoreCase)))
{
// Settings and type already processed
processed = true;
}
else
{
var provider = item["Provider"];
var path = item["Path"];
var extensionOrProvider = provider ?? Path.GetExtension(path);
if (extensionOrProvider != null)
var addFileSource = new AddFileSource
{
var addFileSource = new AddFileSource
{
LoggingLevel = _defaultOptions.LoggingLevel,
Optional = _defaultOptions.Optional,
ReloadOnChange = _defaultOptions.ReloadOnChange
};
item.Bind(addFileSource);
addFileSource.OriginalPath = path;
AddFile(extensionOrProvider, addFileSource);
}
else
LoggingLevel = _defaultOptions.LoggingLevel,
Optional = _defaultOptions.Optional,
ReloadOnChange = _defaultOptions.ReloadOnChange
};
item.Bind(addFileSource);
addFileSource.OriginalPath = addFileSource.Path;
context.Provider = extensionOrProvider;
context.Source = addFileSource;
}

if (!processed)
{
foreach (var handler in _handlers)
{
if (_defaultOptions.IsEnableLogging())
handler(context);
if (context.IsProcessed)
{
logger.LogError("AddFile unknown entry {@entry}", FormatConfigurationSection(item));
processed = true;
break;
}
}
}

if (!processed)
{
if (_defaultOptions.IsEnableLogging())
{
logger.LogError("AddFile unknown entry {@entry}", FormatConfigurationSection(item));
}

if (_defaultOptions.ThrowIfNotSupport ?? _options.ThrowIfNotSupport ?? false)
{
throw new Exception($"AddFile is not supported file extension/provider {context.Provider}, only support {context.SupportedExtensions} with file {context.Source.Path}");
}
}
}

#if NET7_0_OR_GREATER
Expand All @@ -124,31 +157,6 @@ public IConfigurationProvider Build(IConfigurationBuilder builder)
}
}

void AddFile(string extensionOrType, AddFileSource source)
{
if (_options.ConfigureAddFiles.TryGetValue(extensionOrType, out var configureAddFile))
{
if (configureAddFile.ResolveAbsolute)
{
source.Path = Path.GetFullPath(source.Path);
}
logger.Log(source.GetLogLevel(), "Add configuration file {filePath}", source.Path);
configureAddFile.ConfigureAction(configurationBuilder, source);
}
else
{
if (source.IsEnableLogging())
{
logger.LogError("AddFile is not supported file extension/provider {extension}, only support {supportedExtensions} with {sourceFile}", extensionOrType, supportedExtensions, source.Path);
}

if (_defaultOptions.ThrowIfNotSupport ?? _options.ThrowIfNotSupport ?? false)
{
throw new Exception($"AddFile is not supported file extension/provider {extensionOrType}, only support {supportedExtensions} with file {source.Path}");
}
}
}

#if NETSTANDARD
configuration = configurationBuilder.Build();
#else
Expand All @@ -169,4 +177,23 @@ void AddFile(string extensionOrType, AddFileSource source)
ShouldDisposeConfiguration = false,
});
}

private void DefaultAddFileByProvider(AddFileContext context)
{
var source = context.Source;
if (context.Provider is { } provider
&& !string.IsNullOrWhiteSpace(provider)
&& source.OriginalPath is { } path
&& !string.IsNullOrWhiteSpace(path)
&& _options.ConfigureAddFiles.TryGetValue(provider, out var configureAddFile))
{
context.IsProcessed = true;
if (configureAddFile.ResolveAbsolute)
{
source.Path = path = Path.GetFullPath(path);
}
context.Logger.Log(source.GetLogLevel(), "Add configuration file {filePath}", path);
configureAddFile.ConfigureAction(context.ConfigurationBuilder, source);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ namespace NetLah.Extensions.Configuration;
public interface IConfigureAddFiles
{
IDictionary<string, ConfigureAddFileOptions> ConfigureAddFiles { get; }

List<Action<AddFileContext>> Handlers { get; }
}

public class ConfigureAddFileOptions
Expand All @@ -20,6 +22,8 @@ public class AddFileConfigurationSourceOptions : IConfigureAddFiles
{
public IDictionary<string, ConfigureAddFileOptions> ConfigureAddFiles { get; } = new Dictionary<string, ConfigureAddFileOptions>(StringComparer.OrdinalIgnoreCase);

public List<Action<AddFileContext>> Handlers { get; } = new List<Action<AddFileContext>>();

public string SectionKey { get; set; } = string.Empty;

public bool? ThrowIfNotSupport { get; set; }
Expand Down
22 changes: 21 additions & 1 deletion src/NetLah.Extensions.Configuration/AddFileSource.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
namespace NetLah.Extensions.Configuration;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

namespace NetLah.Extensions.Configuration;

public class AddFileSource : AddFileOptionsBase
{
public string Path { get; set; } = null!;

public string? OriginalPath { get; set; } = null;
}

public class AddFileContext
{
public IConfigurationSection Configuration { get; set; } = null!;

public IConfigurationBuilder ConfigurationBuilder { get; set; } = null!;

public ILogger Logger { get; set; } = null!;

public string SupportedExtensions { get; set; } = null!;

public string? Provider { get; set; }

public AddFileSource Source { get; set; } = null!;

public bool IsProcessed { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ namespace NetLah.Extensions.Configuration;

public static class ConfigureAddFilesExtensions
{
public static TConfigureAddFiles AddHandler<TConfigureAddFiles>(this TConfigureAddFiles configureAddFiles, Action<AddFileContext> handler)
where TConfigureAddFiles : IConfigureAddFiles
{
configureAddFiles.Handlers.Add(handler);
return configureAddFiles;
}

public static TConfigureAddFiles AddProvider<TConfigureAddFiles>(this TConfigureAddFiles configureAddFiles, string fileExtension, AddFileDelegate addFile, bool resolveAbsolute = false)
where TConfigureAddFiles : IConfigureAddFiles
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1382,4 +1382,55 @@ public void AddFileConfigurationProduction_KeyPerFile()
Assert.Equal("Key-Per-File/mainValue line0", configuration["MainKey"]);
Assert.Equal("KeyPerFileSection__Add-File-Source.txt", configuration["KeyPerFileSection:Add-File-Source"]);
}

[Fact]
public void AddFileConfigurationProduction_KeyPerFile_Handler()
{
var configuration = ConfigurationBuilderBuilder.Create(
new string[] {
"/AddFile:0:Provider=Key-per_file",
"/AddFile:0:Path=Key-Per-File"
})
.WithAddFileConfiguration(options =>
{
#if NET5_0_OR_GREATER
options.AddHandler(ctx =>
{
if (ctx.Configuration["Provider"] == "Key-per_file")
{
ctx.ConfigurationBuilder.AddKeyPerFile(Path.GetFullPath(ctx.Source.Path), ctx.Source.Optional, ctx.Source.ReloadOnChange);
ctx.IsProcessed = true;
}
});
#else
options.AddHandler(ctx =>
{
if (ctx.Configuration["Provider"] == "Key-per_file")
{
ctx.ConfigurationBuilder.AddKeyPerFile(Path.GetFullPath(ctx.Source.Path), ctx.Source.Optional);
ctx.IsProcessed = true;
}
});
#endif
}, throwIfNotSupport: true)
.BuildConfigurationRoot();

AssertProviders(configuration, new[] {
"JsonConfigurationProvider",
"JsonConfigurationProvider",
"ChainedConfigurationProvider",
"EnvironmentVariablesConfigurationProvider",
"CommandLineConfigurationProvider",
}, new[] {
"appsettings.json",
"appsettings.Production.json",
null,
null,
null,
});

Assert.Equal("EnvironmentProductionValue1", configuration["EnvironmentKey"]);
Assert.Equal("Key-Per-File/mainValue line0", configuration["MainKey"]);
Assert.Equal("KeyPerFileSection__Add-File-Source.txt", configuration["KeyPerFileSection:Add-File-Source"]);
}
}

0 comments on commit 23151ef

Please sign in to comment.