Add ReplacePlaceholders for SQL-style string interpolation
Introduce ReplacePlaceholders to PlaceholderExtensions, enabling replacement of {#...#COLUMN_NAME} placeholders in strings with property values from provided objects. Uses a generated regex for matching and converts values to SQL-compatible literals. Throws PlaceholderResolutionException if a column cannot be resolved. Refactored class to partial to support regex generation.
This commit is contained in:
@@ -1,10 +1,51 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using ReC.Application.Common.Exceptions;
|
||||
|
||||
namespace ReC.Application.Common.Behaviors.InvokeAction;
|
||||
|
||||
public static class PlaceholderExtensions
|
||||
public static partial class PlaceholderExtensions
|
||||
{
|
||||
[GeneratedRegex(@"\{#[^#]+#[^}]+\}")]
|
||||
private static partial Regex PlaceholderRegex();
|
||||
|
||||
/// <summary>
|
||||
/// Replaces placeholders in the format <c>{#ANY_STRING#COLUMN_NAME}</c> with the corresponding
|
||||
/// property value resolved via <see cref="GetValueByColumnName{T}"/> from the provided objects.
|
||||
/// Values are converted to SQL-compatible string representations.
|
||||
/// </summary>
|
||||
/// <exception cref="PlaceholderResolutionException">
|
||||
/// Thrown when a placeholder's column name cannot be resolved from any of the provided objects.
|
||||
/// </exception>
|
||||
public static string ReplacePlaceholders(this string str, params object[] objects)
|
||||
{
|
||||
return PlaceholderRegex().Replace(str, match =>
|
||||
{
|
||||
var placeholder = match.Value;
|
||||
var inner = placeholder[2..^1]; // remove {# and }
|
||||
var lastHash = inner.LastIndexOf('#');
|
||||
var columnName = inner[(lastHash + 1)..];
|
||||
|
||||
foreach (var obj in objects)
|
||||
{
|
||||
var value = obj.GetValueByColumnName(columnName);
|
||||
if (value is not null)
|
||||
return ToSqlLiteral(value);
|
||||
}
|
||||
|
||||
throw new PlaceholderResolutionException(placeholder, columnName, str);
|
||||
});
|
||||
}
|
||||
|
||||
private static string ToSqlLiteral(object value) => value switch
|
||||
{
|
||||
bool b => b ? "TRUE" : "FALSE",
|
||||
DateTime dt => dt.ToString("yyyy-MM-dd HH:mm:ss"),
|
||||
DateTimeOffset dto => dto.ToString("yyyy-MM-dd HH:mm:ss zzz"),
|
||||
_ => value.ToString() ?? string.Empty
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of a property by its column name defined in <see cref="ColumnAttribute"/>.
|
||||
/// Returns <c>null</c> if no property with the given column name exists.
|
||||
|
||||
Reference in New Issue
Block a user