Inject object properties into string

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"));

Description

Supplements String.Format by letting you get properties from objects

Details

Double click on the code to select all.

 

;