Last active
May 29, 2019 00:42
-
-
Save pmunin/5cb1d6e388bb1efd2e2479383e3cafa4 to your computer and use it in GitHub Desktop.
FormattableStringExtensions C#
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Reflection; | |
using System.Runtime.CompilerServices; | |
namespace FormattableStrings | |
{ | |
public static class FormattableStringExtensions | |
{ | |
class Formattable : IFormattable | |
{ | |
public Formattable(Func<(string format, IFormatProvider provider, Formattable formattable), string> toStringFunc) | |
{ | |
this.ToStringFunc = toStringFunc; | |
} | |
public Func<(string format, IFormatProvider provider, Formattable formattable), string> ToStringFunc; | |
public string ToString(string format, IFormatProvider formatProvider) | |
{ | |
return ToStringFunc((format, formatProvider, this)); | |
} | |
} | |
/// <summary> | |
/// Converts formattable string to regular string, allowing to substitute its formattable parameters with any other value | |
/// for example FormatArgs($"Value A:{1}, B:{2}", arg=>(int)arg.value+1) will return Value A:2, B:3 | |
/// </summary> | |
/// <param name="str"></param> | |
/// <param name="getParamValue"></param> | |
/// <returns></returns> | |
public static string FormatArgs(this FormattableString str, Func<(object value, int index, string format, IFormatProvider formatProvider), object> getParamValue) | |
{ | |
var args = str.GetArguments().Select((val, i) => | |
new Formattable(p=> { | |
var r = getParamValue((val, i, p.format, p.provider)); | |
if (r is string s) return s; | |
if (r is IFormattable f) return f.ToString(p.format, p.provider); | |
return r.ToString(); | |
}) | |
).ToArray(); | |
return string.Format(str.Format, args: args); | |
} | |
public static FormattableString ReformatArgs(this FormattableString str, Func<(object value, int index, string format, IFormatProvider formatProvider), object> getParamValue) | |
{ | |
var args = str.GetArguments().Select((val, i) => | |
new Formattable(p => { | |
var r = getParamValue((val, i, p.format, p.provider)); | |
if (r is string s) return s; | |
if (r is IFormattable f) return f.ToString(p.format, p.provider); | |
return r.ToString(); | |
}) | |
).ToArray(); | |
return FormattableStringFactory.Create(str.Format, arguments: args); | |
} | |
/// <summary> | |
/// Generates string allowing to substitute each parameter, extracting properties from it. | |
/// E.g.: FormatArgsByProperties($"My object: {new {Prop1=123}}", arg=>{var kvp = arg.properties.First(); return kvp.Key"="+kvp.Value.value.ToString()}) will return "My object: Prop1=123" | |
/// </summary> | |
/// <param name="str"></param> | |
/// <param name="getValue"></param> | |
/// <returns></returns> | |
public static string FormatArgsByProperties(this FormattableString str, | |
Func<(Dictionary<string, (PropertyInfo property, object value)> properties, int index), object> getValue) | |
{ | |
return str.FormatArgs(arg => | |
{ | |
var props = arg.value?.GetType()?.GetProperties(); | |
var dict = props?.ToDictionary(p => p.Name, p => (property: p, value: p.GetValue(arg))); | |
return getValue((dict, arg.index)); | |
}); | |
} | |
public static string FormatArgsByFirstProperty(this FormattableString str, | |
Func<(PropertyInfo property, object value, int index), object> getValue) | |
{ | |
return str.FormatArgs(arg => | |
{ | |
var prop = arg.value?.GetType()?.GetProperties()?.FirstOrDefault(); | |
return getValue((prop, prop?.GetValue(arg.value), arg.index)); | |
}); | |
} | |
public static FormattableString AppendFormattable(this FormattableString str, FormattableString str2) | |
{ | |
var arg2Start = str.GetArguments().Length; | |
var fmt2 = str2.FormatArgs(arg => | |
{ | |
var res = $"{arg.index+arg2Start}" + (arg.format != null ? $":{arg.format}" : ""); | |
res = "{" + res + "}"; | |
return res; | |
}); | |
return FormattableStringFactory.Create(str.Format + fmt2, arguments: str.GetArguments().Concat(str2.GetArguments()).ToArray()); | |
} | |
public static FormattableString AppendFormattable(this string str, FormattableString str2) | |
{ | |
var fmt = str + str2.Format; | |
var args = str2.GetArguments(); | |
return System.Runtime.CompilerServices.FormattableStringFactory.Create(fmt, args); | |
} | |
public static FormattableString AsFormattable(this string str) | |
{ | |
return FormattableStringFactory.Create(str); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment