UPD
If the whole question is how to generate a log file name, can it be easier to do this way? In the configuration, we set the valid with tz. .NET format for date:
{ "logFilePattern" : "yyyy.MM.dd.log" }
Then in the code we bite it and get the file name:
const string extension = ".log"; var datePattern = logFilePattern.Remove(logFilePattern.IndexOf(extension), extension.Length); DateTime date = DateTime.UtcNow; var logFileName = date.ToString(datePattern) + extension;
About the task in general
A naive implementation can simply consist in replacing a value:
string stringPattern = "Name = {name}"; string name = "Fred"; string formatted = stringPattern.Replace($"{{nameof(name)}}", name);
There are two drawbacks:
- non-universal code (I would like to have a separate method, such as
FormatString(pattern, value1, value2, ...)
) - the possible escaping of curly brackets is not taken into account (the string
"{{name}}"
not a pattern, but the replacement will be made) - in the presence of several values we will produce extra lines
A method of the form FormatString(pattern, value1, value2, ...)
, as far as I understand, is unrealistic, since there is no way in the called method to find out the names of the parameters with which it was called. Therefore, you can dwell on, for example, the dictionary:
public static string FormatString(string pattern, IDictionary<string, object> values)
Escaping can be processed with a regular expression, but given that there can be several parameters, this can also be an unnecessarily heavy operation. Therefore, the implementation in general depends on the desired degree of optimization, ideally, it is necessary to manually pass the char[]
/ List<char>
and change it on the fly.
At night looking like this:
public static string FormatString(string pattern, IDictionary<string, object> values) { var buffer = pattern.ToList(); int replaceStartIndex = -1; int replaceEndIndex = -1; int index = 0; while (index < buffer.Count) { var character = buffer[index]; if (character == '{') { if (replaceStartIndex == -1) { replaceStartIndex = index; } else { replaceStartIndex = -1; } } else if (character == '}') { if (replaceEndIndex == -1) { replaceEndIndex = index; } else { replaceEndIndex = -1; } } if (replaceStartIndex > -1 && replaceEndIndex > -1) { var key = new string(buffer.Skip(replaceStartIndex + 1).Take(replaceEndIndex - replaceStartIndex - 1).ToArray()); var value = values[key]; var stringValue = value?.ToString(); buffer.RemoveRange(replaceStartIndex, replaceEndIndex - replaceStartIndex + 1); if (stringValue != null) { buffer.InsertRange(replaceStartIndex, stringValue.ToCharArray()); index = replaceStartIndex + stringValue.Length; } else { index = replaceStartIndex; } replaceStartIndex = -1; replaceEndIndex = -1; } else { index++; } } return string.Join("", buffer); }
Check:
static void Main(string[] args) { string stringPattern = "Name = {name}, Age = {age}, Null = {nullString}, Escape = {{escape}}"; string name = "Fred"; int age = 42; string nullString = null; string escape = "You shouldn't see this"; var values = new Dictionary<string, object>() { [nameof(name)] = name, [nameof(age)] = age, [nameof(nullString)] = nullString, [nameof(escape)] = escape }; string formatted = FormatString(stringPattern, values); Console.WriteLine(formatted); }
Conclusion:
Name = Fred, Age = 42, Null =, Escape = {{escape}}