Search code examples
c#.netstring-interpolation

c# - dynamic string interpolation


I'm trying to format some string dynamically with available variables in a specific context/scope.

This strings would have parts with things like {{parameter1}}, {{parameter2}} and these variables would exist in the scope where I'll try to reformat the string. The variable names should match.

I looked for something like a dynamically string interpolation approach, or how to use FormattableStringFactory, but I found nothing that really gives me what I need.

var parameter1 = DateTime.Now.ToString();
var parameter2 = "Hello world!";
var retrievedString = "{{parameter2}} Today we're {{parameter1}}";
var result = MagicMethod(retrievedString, parameter1, parameter2);
// or, var result = MagicMethod(retrievedString, new { parameter1, parameter2 });

Is there an existing solution or should I (in MagicMethod) replace these parts in the retrievedString with matching members of the anonymous object given as parameter (using reflection or something like that)?

EDIT:

Finally, I created an extension method to handle this:

internal static string SpecialFormat(this string input, object parameters) {
  var type = parameters.GetType();
  System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex( "\\{(.*?)\\}" );
  var sb = new System.Text.StringBuilder();
  var pos = 0;

  foreach (System.Text.RegularExpressions.Match toReplace in regex.Matches( input )) {
    var capture = toReplace.Groups[ 0 ];
    var paramName = toReplace.Groups[ toReplace.Groups.Count - 1 ].Value;
    var property = type.GetProperty( paramName );
    if (property == null) continue;
    sb.Append( input.Substring( pos, capture.Index - pos) );
    sb.Append( property.GetValue( parameters, null ) );
    pos = capture.Index + capture.Length;
  }

  if (input.Length > pos + 1) sb.Append( input.Substring( pos ) );

  return sb.ToString();
}

and I call it like this:

var parameter1 = DateTime.Now.ToString();
var parameter2 = "Hello world!";
var retrievedString = "{parameter2} Today we're {parameter1}";
var result = retrievedString.SpecialFormat( new { parameter1, parameter2 } );

Now, I don't use double braces anymore.


Solution

  • You can use reflection coupled with an anonymous type to do this:

    public string StringFormat(string input, object parameters)
    {
        var properties = parameters.GetType().GetProperties();
        var result = input;
    
        foreach (var property in properties)
        {
            result = result.Replace(
                $"{{{{{property.Name}}}}}", //This is assuming your param names are in format "{{abc}}"
                property.GetValue(parameters).ToString());
        }
    
        return result;
    }
    

    And call it like this:

    var result = StringFormat(retrievedString, new { parameter1, parameter2 });