I'd like to create an EscapingFormatProvider
that automatically HTML-escapes formatted strings before returning them, unless the format argument starts with a !:
string.Format(new EscapingFormatProvider(), "<div>{0}</div>", "<script src='foo'></script>");
// => <div><script src='foo'></script></div>
string.Format(new EscapingFormatProvider(), "<div>{0:!}</div>", "<script src='foo'></script>");
// => <div><script src='foo'></script></div>
I'd like it to pass the format argument, less the ! if there was one, to the default formatter. The only trouble is, I have no idea how to get at the default formatter. None of the examples I've found address the issue of delegation to the default formatter.
EDIT: This is what I came up with:
private class EscapingFormatProvider : IFormatProvider, ICustomFormatter
{
public object GetFormat(Type formatType) { return this; }
private string DefaultFormat(string format, object arg)
{
return string.Format("{0:" + format + "}", arg);
}
public string Format(string format, object arg, IFormatProvider formatProvider)
{
return (format.First() == '!')
? HttpUtility.HtmlEncode(DefaultFormat(format.Substring(1), arg))
: DefaultFormat(format, arg);
}
}
It's a bit indirect, but I suppose it works.
If I'm understanding you correctly, all you should need to do to use the default format provider is call the overload of string.Format that doesn't take an IFormatProvider! Or do you mean something else by "default formatter", or are you worried about localization?
The correct solution is to re-implement what the default formatter does, which is the following:
var formattable = arg as IFormattable;
return formattable == null
? arg.ToString()
: formattable.ToString(format, formatProvider);
On top of this, your format provider should only return itself if ICustomFormatter
is the type asked for.
Therefore, in your case, your format provider should look like this:
class EscapingFormatProvider : IFormatProvider, ICustomFormatter
{
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter))
return this;
return null;
}
public string Format(string format, object arg, IFormatProvider formatProvider)
{
var escape = false;
if (format.StartsWith("!"))
{
escape = true;
format = format.Substring(1);
}
var formattable = arg as IFormattable;
var formatted = formattable == null
? arg.ToString()
: formattable.ToString(format, formatProvider);
return escape ? HttpUtility.HtmlEncode(formatted) : formatted;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With