Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion source/Core/CreativeCoders.Core/ObjectExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using JetBrains.Annotations;

Expand Down Expand Up @@ -66,7 +69,7 @@ public static async ValueTask TryDisposeAsync(this object instance)
throw new MissingMemberException(instance.GetType().Name, propertyName);
}

return (T?) propInfo.GetValue(instance);
return (T?)propInfo.GetValue(instance);
}

public static void SetPropertyValue<T>(this object instance, string propertyName, T? value)
Expand All @@ -80,4 +83,19 @@ public static void SetPropertyValue<T>(this object instance, string propertyName

propInfo.SetValue(instance, value);
}

public static Dictionary<string, object?> ToDictionary(this object obj)
{
Ensure.NotNull(obj);

return obj
.GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Select(propertyInfo => ReadProperty(obj, propertyInfo))
.ToDictionary(x => x.PropertyName, x => x.PropertyValue);
}

private static (string PropertyName, object? PropertyValue) ReadProperty(object obj,
PropertyInfo propertyInfo)
=> (propertyInfo.Name, propertyInfo.GetValue(obj));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;

namespace CreativeCoders.Core.Placeholders;

#nullable enable

public class PlaceholderReplacer(
string placeholderPrefix,
string placeholderSuffix,
IDictionary<string, object?> placeholders)
{
private readonly string _placeholderPrefix = Ensure.IsNotNullOrWhitespace(placeholderPrefix);

private readonly string _placeholderSuffix = Ensure.IsNotNullOrWhitespace(placeholderSuffix);

private readonly IDictionary<string, object?> _placeholders = Ensure.NotNull(placeholders);

public string Replace(string text, bool allowNull = false)
{
if (_placeholders.Count == 0)
{
return text;
}

return _placeholders
.Aggregate(text,
(current, placeholder) =>
current.Replace($"{_placeholderPrefix}{placeholder.Key}{_placeholderSuffix}",
placeholder.Value.ToStringSafe(allowNull ? "null" : string.Empty)));
}

public IEnumerable<string> Replace(IEnumerable<string> lines, bool allowNull = false)
{
return _placeholders.Count == 0
? lines
: lines.Select(x => Replace(x, allowNull));
}
}
44 changes: 44 additions & 0 deletions source/Core/CreativeCoders.Core/Text/EnumerableStringExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using CreativeCoders.Core.Placeholders;

namespace CreativeCoders.Core.Text;

#nullable enable

public static class EnumerableStringExtensions
{
public static Dictionary<string, string> ToDictionary(this IEnumerable<string> items, string separator,
bool ignoreInvalidEntries = true)
{
Ensure.NotNull(items);
Ensure.NotNull(separator);

return items
.Select(x => x.SplitIntoKeyValue(separator))
.Where(x =>
{
if (x == null && !ignoreInvalidEntries)
{
throw new ArgumentException("Invalid key/value entry found");
}

return x != null;
})
.ToDictionary(x => x.Key, x => x.Value);
}

[ExcludeFromCodeCoverage]
public static IEnumerable<string> ReplacePlaceholders(this IEnumerable<string> items,
string placeholderPrefix, string placeholderSuffix,
IDictionary<string, object?> placeholders)
{
Ensure.NotNull(items);

var replacer = new PlaceholderReplacer(placeholderPrefix, placeholderSuffix, placeholders);

return replacer.Replace(items);
}
}
9 changes: 9 additions & 0 deletions source/Core/CreativeCoders.Core/Text/KeyAndValue.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#nullable enable
namespace CreativeCoders.Core.Text;

public class KeyAndValue(string key, string value)
{
public string Key { get; } = Ensure.NotNull(key);

public string Value { get; } = Ensure.NotNull(value);
}
23 changes: 23 additions & 0 deletions source/Core/CreativeCoders.Core/Text/StringExtension.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.CompilerServices;
Expand Down Expand Up @@ -190,4 +191,26 @@ private static string SeparatedToPascalCase(this string? text, char separator)
return parts.Aggregate(string.Empty,
(current, part) => current + char.ToUpperInvariant(part[0]) + part[1..].ToLowerInvariant());
}

public static KeyAndValue? SplitIntoKeyValue(this string? text, string separator)
{
Ensure.NotNull(separator);

if (string.IsNullOrEmpty(text))
{
return null;
}

var separatorIndex = text.IndexOf(separator, StringComparison.Ordinal);

if (separatorIndex == -1)
{
return null;
}

var key = text[..separatorIndex];
var value = text[(separatorIndex + 1)..];

return new KeyAndValue(key, value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,65 @@ public interface IProcessExecutor<T>
{
T? Execute();

T? Execute(string[] args);

T? Execute(IDictionary<string, object?> placeholderVars);

Task<T?> ExecuteAsync();

Task<T?> ExecuteAsync(string[] args);

Task<T?> ExecuteAsync(IDictionary<string, object?> placeholderVars);

ProcessExecutionResult<T?> ExecuteEx();

ProcessExecutionResult<T?> ExecuteEx(string[] args);

ProcessExecutionResult<T?> ExecuteEx(IDictionary<string, object?> placeholderVars);

Task<ProcessExecutionResult<T?>> ExecuteExAsync();

Task<ProcessExecutionResult<T?>> ExecuteExAsync(string[] args);

Task<ProcessExecutionResult<T?>> ExecuteExAsync(IDictionary<string, object?> placeholderVars);
}

[PublicAPI]
public interface IProcessExecutor
{
void Execute();

void Execute(string[] args);

void Execute(IDictionary<string, object?> placeholderVars);

Task ExecuteAsync();

Task ExecuteAsync(string[] args);

Task ExecuteAsync(IDictionary<string, object?> placeholderVars);

IProcess ExecuteEx();

IProcess ExecuteEx(string[] args);

IProcess ExecuteEx(IDictionary<string, object?> placeholderVars);

Task<IProcess> ExecuteExAsync();

Task<IProcess> ExecuteExAsync(string[] args);

Task<IProcess> ExecuteExAsync(IDictionary<string, object?> placeholderVars);

int ExecuteAndReturnExitCode();

int ExecuteAndReturnExitCode(string[] args);

int ExecuteAndReturnExitCode(IDictionary<string, object?> placeholderVars);

Task<int> ExecuteAndReturnExitCodeAsync();

Task<int> ExecuteAndReturnExitCodeAsync(string[] args);

Task<int> ExecuteAndReturnExitCodeAsync(IDictionary<string, object?> placeholderVars);
}
Loading
Loading