- NVelocity(Caslte project)
- Brail(Caslte project)
- NHaml
- Spark
- StringTemplate .NET
- etc...
- Use string format placeholders {0}, {1}, etc - it is good solution if you have only 2-3 placeholders, do not need descriptiveness of them, and (may be) need to use specific formatters such as {0:d}, {0:X} etc:
string result = string.Format("{0} + {1} = {2}", 4, 5, 6);
- Use replacement, handwritten placeholders: #ID#, #NAME#, etc - they are more descriptive, but without formatters:
string result = "#Arg1# + #Arg2# = #Res#" .Replace("#Arg1#", 4) .Replace("#Arg2#", 5) .Replace("#Res#", 9);
public static StringBuilder AppendFormatEx(this StringBuilder self, string format, object args, MemberKind memberKind) { MemberInfo[] members; switch (memberKind) { case MemberKind.Property: members = args.GetType().GetProperties(); break; case MemberKind.Field: members = args.GetType().GetFields(); break; default: throw new ArgumentOutOfRangeException("memberKind"); } foreach (MemberInfo member in members) { string placeholder = string.Format("{{{0}}}", member.Name); object value; if (member is FieldInfo) value = (member as FieldInfo).GetValue(args); else if (member is PropertyInfo) value = (member as PropertyInfo).GetValue(args, null); else throw new InvalidOperationException("Only fields and properties are supported. But you use " + member.GetType().Name); format = format.Replace(placeholder, Convert.ToString(value)); } self.Append(format); return self; }
It is a simplified for readability main method that contains all the functionality. First of all, we take an array of public members from args, kind of members (property or field) you can specify by argument memberKind. Then for each extracted member we create name of the placeholder, get the value of the member and replace placeholder by value. Thats all.. as simple as possible.
An overloaded version of this method working only with public properties:
public static StringBuilder AppendFormatEx(this StringBuilder self, string format, object args) { return AppendFormatEx(self, format, args, MemberKind.Property); }
For String I have an overloaded extension method too:
public static string Format(this string format, object args, MemberKind memberKind) { StringBuilder builder = new StringBuilder(); builder.AppendFormatEx(format, args, memberKind); return builder.ToString(); }It is uses a StringBuilder's method to format a string. An instance of the string represents a format. And overloaded version working only with public properties:
public static string Format(this string format, object args) { return Format(format, args, MemberKind.Property); }Now I show you simple test console application, that gives you an idea how this works in code:
using System; using System.Text; namespace HennadiyKurabko.StringFormattersEx { class Program { static void Main(string[] args) { // Arrange string format = "{Name}:\t\t{Age} year(s)\t\t{Login}\r\n"; object[] users = new object[] { new { Name = "Jane Siemens", Age = 25, Login = "janes" }, new { Name = "Tom Clancy", Age = 25, Login = "tomc" }, new { Name = "Sofi Payne", Age = 25, Login = "sofip" } }; // Act [String] Console.WriteLine("String extensions test"); Console.WriteLine(); foreach (var user in users) { Console.Write(format.Format(user)); } Console.WriteLine("-----------------------------"); // Act [StringBuilder] StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("StringBuilder extensions test"); stringBuilder.AppendLine(); foreach (var user in users) { stringBuilder.AppendFormatEx(format, user); } stringBuilder.AppendLine("-----------------------------"); Console.WriteLine(stringBuilder.ToString()); } } }
You see, that format string contains placeholders with property names: {Name}, {Age}, {Login}. It is far more descriptive as {0}, {1}. But in that case you cannot use specific formatters. So, it is your choice what of the methods to use. Hope this helps you.
An example for this article you can download here: StringFormattersEx.zip
Good luck and happy coding!
No comments:
Post a Comment