Search code examples
c#stringstring-formattingiformatprovideriformattable

Custom string formatter in C#


String formatting in C#;

Can I use it? Yes.

Can I implement custom formatting? No.

I need to write something where I can pass a set of custom formatting options to string.Format, which will have some effect on the particular item.

at the moment I have something like this:

string.Format("{0}", item);

but I want to be able to do things with that item:

string.Format("{0:lcase}", item); // lowercases the item
string.Format("{0:ucase}", item); // uppercases the item
string.Format("{0:nospace}", item); // removes spaces

I know I can do things like .ToUpper(), .ToLower() etc. but I need to do it with string formatting.

I've been looking into things like IFormatProvider and IFormattable but I don't really know if they are the things I should be using, or, how to implement them.

Can anyone explain how I can solve this problem?

Rationale (just in case you want to know...)

I have a small program, where I can enter a comma delimited set of values, and a template. The items are passed into string.Format, along with the template which creates an output. I want to provide template formatting options, so that the user can control how they want items to be output.


Solution

  • You can make a custom formatter, something like:

    public class MyFormatter : IFormatProvider, ICustomFormatter
    {
       public object GetFormat(Type formatType)
       {
          if (formatType == typeof(ICustomFormatter))
             return this;
          else
             return null;
       }
    
       public string Format(string fmt, object arg, IFormatProvider formatProvider) 
       {
           if(arg == null) return string.Empty;
    
           if(fmt == "lcase")
               return arg.ToString().ToLower();
           else if(fmt == "ucase")
               return arg.ToString().ToUpper();
           else if(fmt == "nospace")
               return arg.ToString().Replace(" ", "");
           // Use this if you want to handle default formatting also
           else if (arg is IFormattable) 
               return ((IFormattable)arg).ToString(fmt, CultureInfo.CurrentCulture);
           return arg.ToString();
       }
    }
    

    Then use it like:

     string.Format(new MyFormatter(),
                "{0:lcase}, {0:ucase}, {0:nospace}", 
                "My Test String")
    

    This should return:

    my test string, MY TEST STRING, MyTestString