Skip to content

Commit

Permalink
Merge pull request #285 from Lombiq/issue/OFFI-101
Browse files Browse the repository at this point in the history
OFFI-101: New configuration extension medhods
  • Loading branch information
wAsnk authored Sep 24, 2024
2 parents 050e2af + 3df8434 commit 3146a79
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,23 @@ public static IConfigurationSection AddValueIfKeyNotExists(
configurationSection[key] ??= value;
return configurationSection;
}

/// <summary>
/// Creates a new instance of <typeparamref name="T"/> and binds it the provided configuration.
/// </summary>
/// <param name="configuration">The base configuration.</param>
/// <param name="sectionKey">
/// If <see langword="null"/> or empty, then <paramref name="configuration"/> is used, otherwise the section with
/// this key inside it.
/// </param>
public static (T Options, IConfiguration ConfigurationSection) BindNew<T>(
this IConfiguration configuration,
string sectionKey = null)
where T : new()
{
var options = new T();
var section = string.IsNullOrEmpty(sectionKey) ? configuration : configuration.GetSection(sectionKey);
section.Bind(options);
return (options, section);
}
}
23 changes: 22 additions & 1 deletion Lombiq.HelpfulLibraries.Cli/Extensions/CommandExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#nullable enable

using CliWrap.Builders;
using CliWrap.EventStream;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

Expand All @@ -14,7 +18,7 @@ public static class CommandExtensions
/// </summary>
public static async Task ExecuteDotNetApplicationAsync(
this Command command,
Action<StandardErrorCommandEvent> stdErrHandler = default,
Action<StandardErrorCommandEvent>? stdErrHandler = default,
CancellationToken cancellationToken = default)
{
await using var enumerator = command.ListenAsync(cancellationToken).GetAsyncEnumerator(cancellationToken);
Expand Down Expand Up @@ -45,4 +49,21 @@ public static async Task<Command> WithArgumentsAsync(this Command command, Func<

return command.WithArguments(builder.Build());
}

/// <summary>
/// Same as <see cref="Command.WithEnvironmentVariables(IReadOnlyDictionary{string,string?})"/>, but the values can
/// be any type. If a value is <see cref="IConvertible"/>, like all C# primitive types then <see
/// cref="NumberExtensions.ToTechnicalString(IConvertible)"/> is called, otherwise <see cref="object.ToString"/>.
/// </summary>
public static Command WithEnvironmentVariables(this Command command, IEnumerable<KeyValuePair<string?, object?>> variables) =>
command.WithEnvironmentVariables(variables
.Where(pair => pair is { Key: { } })
.ToDictionary(
pair => pair.Key!,
pair => pair.Value switch
{
string text => text,
IConvertible convertible => convertible.ToTechnicalString(),
_ => pair.Value?.ToString(),
}));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System.Threading.Tasks;

namespace System.Net.Http;

public static class HttpResponseExtensions
{
public static async Task ThrowIfNotSuccessAsync(
this HttpResponseMessage response,
string errorMessage,
HttpContent requestBody = null)
{
if (!response.IsSuccessStatusCode)
{
var requestContent = requestBody == null ? "<NULL>" : await requestBody.ReadAsStringAsync();
throw new InvalidOperationException(string.Join(
separator: '\n',
errorMessage,
$"Response: {response}",
$"Response Content: {await response.Content.ReadAsStringAsync()}",
$"Request Content: {requestContent}"));
}
}
}
8 changes: 8 additions & 0 deletions Lombiq.HelpfulLibraries.Common/Extensions/NumberExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#nullable enable

using System.Globalization;

namespace System;
Expand Down Expand Up @@ -58,6 +60,12 @@ public static class NumberExtensions
/// <param name="number">The number to stringify.</param>
public static string ToTechnicalString(this decimal number) => number.ToString(CultureInfo.InvariantCulture);

/// <summary>
/// Returns culture-invariant <see cref="string"/> created from the specified <see cref="IConvertible"/>.
/// </summary>
/// <param name="number">The number to stringify.</param>
public static string? ToTechnicalString(this IConvertible? number) => number?.ToString(CultureInfo.InvariantCulture);

/// <summary>
/// Returns the result if the <paramref name="number"/> can be parsed to <see cref="int"/>. Returns -1 if the parse
/// failed.
Expand Down
21 changes: 21 additions & 0 deletions Lombiq.HelpfulLibraries.Common/Extensions/TaskExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace System.Threading.Tasks;

public static class TaskExtensions
{
/// <summary>
/// A shortcut for <see cref="MulticastDelegateExtensions.InvokeAsync{TDelegate}"/> when the delegate is a <see
/// cref="Task"/> returning <see cref="Func{TIn, TResult}"/>.
/// </summary>
public static Task InvokeFuncAsync<TIn>(this Func<TIn, Task> @delegate, TIn argument) =>
@delegate.InvokeAsync<Func<TIn, Task>>(func => func(argument));

/// <summary>
/// Converts a <see cref="Task{TResult}"/> that returns an <see cref="IDisposable"/> instance into <see
/// cref="Task"/> by disposing and discarding its result.
/// </summary>
public static Task DisposeResultAsync<T>(this Task<T> task)
where T : IDisposable =>
task.ContinueWith(
finishedTask => finishedTask.Result?.Dispose(),
TaskScheduler.Current);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,6 @@ public static IServiceCollection BindAndConfigureSection<T>(
this IServiceCollection services,
IShellConfiguration shellConfiguration,
string sectionName)
where T : class, new()
{
var options = new T();
var configSection = shellConfiguration.GetSection(sectionName);
configSection.Bind(options);
services.Configure<T>(configSection);

return services;
}
where T : class, new() =>
services.Configure<T>(shellConfiguration.BindNew<T>(sectionName).ConfigurationSection);
}

0 comments on commit 3146a79

Please sign in to comment.