Inject object properties into string
Supplements String.Format by letting you get properties from objects
Source
namespace String.InjecterExtension
{
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
public static class StringExtensions
{
public static string Inject(this string source, IFormatProvider formatProvider, params object[] args)
{
var objectWrappers = new object[args.Length];
for (var i = 0; i < args.Length; i++)
{
objectWrappers[i] = new ObjectWrapper(args[i]);
}
return string.Format(formatProvider, source, objectWrappers);
}
public static string Inject(this string source, params object[] args)
{
return Inject(source, CultureInfo.CurrentUICulture, args);
}
private class ObjectWrapper : IFormattable
{
private readonly object wrapped;
private static readonly Dictionary<string, FormatInfo> Cache = new Dictionary<string, FormatInfo>();
public ObjectWrapper(object wrapped)
{
this.wrapped = wrapped;
}
public string ToString(string format, IFormatProvider formatProvider)
{
if (string.IsNullOrEmpty(format))
{
return this.wrapped.ToString();
}
var type = this.wrapped.GetType();
var key = type.FullName + ":" + format;
FormatInfo wrapperCache;
lock (Cache)
{
if (!Cache.TryGetValue(key, out wrapperCache))
{
wrapperCache = CreateFormatInfo(format, type);
Cache.Add(key, wrapperCache);
}
}
var propertyInfo = wrapperCache.PropertyInfo;
var outputFormat = wrapperCache.OutputFormat;
var value = propertyInfo != null ? propertyInfo.GetValue(this.wrapped) : this.wrapped;
return string.Format(formatProvider, outputFormat, value);
}
private static FormatInfo CreateFormatInfo(string format, IReflect type)
{
var spilt = format.Split(new[] { ':' }, 2);
var param = spilt[0];
var hasSubFormat = spilt.Length == 2;
var subFormat = hasSubFormat ? spilt[1] : string.Empty;
var propertyInfo = type.GetProperty(param, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
var outputFormat = propertyInfo != null ? (hasSubFormat ? "{0:" + subFormat + "}" : "{0}") : "{0:" + format + "}";
return new FormatInfo(propertyInfo, outputFormat);
}
private class FormatInfo
{
public FormatInfo(PropertyInfo propertyInfo, string form)
{
this.PropertyInfo = propertyInfo;
this.OutputFormat = form;
}
public PropertyInfo PropertyInfo { get; private set; }
public string OutputFormat { get; private set; }
}
}
}
}
Example
var sourceObject = new { simpleString = "string", integer = 3, Date = new DateTime(2013, 08, 19) };
Debug.WriteLine("Gettings property by name : '{0:simpleString}' event cast insensitive : {0:date}".Inject(sourceObject));
Debug.WriteLine("The property can be formatted by appending standard String.Format syntax after the property name like this {0:date:yyyy-MM-dd}".Inject(sourceObject));
Debug.WriteLine("Use culture info to format the value to a specific culture '{0:date:dddd}'".Inject(CultureInfo.GetCultureInfo("da-DK"), sourceObject));
Debug.WriteLine("Inject more values and event build in types {0:integer} {1} with build in properties {1:length}".Inject(sourceObject, "simple string"));