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.ComponentModel.DataAnnotations.Schema;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using ReC.Application.Common.Exceptions;
|
||||||
|
|
||||||
namespace ReC.Application.Common.Behaviors.InvokeAction;
|
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>
|
/// <summary>
|
||||||
/// Gets the value of a property by its column name defined in <see cref="ColumnAttribute"/>.
|
/// 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.
|
/// Returns <c>null</c> if no property with the given column name exists.
|
||||||
|
|||||||
Reference in New Issue
Block a user