private static Expression CompileFormatString()

in Source/Tx.Windows/EventFormatter.cs [54:116]


        private static Expression CompileFormatString(Type type)
        {
            var attribute = type.GetCustomAttribute<FormatAttribute>();

            string format = attribute == null ? type.Name : attribute.FormatString;

            PropertyInfo[] properties = type.GetProperties();

            ParameterExpression par = Expression.Parameter(type, "e");
            var tokens = new List<Expression>();

            format = format.Replace("%n", "\n");
            format = format.Replace("%t", "    ");

            int startIndex = 0;
            while (startIndex < format.Length - 1)
            {
                int percentIndex = format.IndexOf('%', startIndex); // no more arguments

                SkipEscapedPercent:

                if (percentIndex < 0)
                {
                    string last = format.Substring(startIndex);
                    tokens.Add(Expression.Constant(last));
                    break;
                }
                if (format[percentIndex + 1] == '%') // special case %% means % escaped
                {
                    percentIndex = format.IndexOf('%', percentIndex + 2);
                    goto SkipEscapedPercent;
                }

                string prefix = format.Substring(startIndex, percentIndex - startIndex);
                tokens.Add(Expression.Constant(prefix));

                int beginNumberIndex = percentIndex + 1;
                int endNumberIndex = beginNumberIndex;
                while (endNumberIndex < format.Length)
                {
                    if (format[endNumberIndex] < '0' || format[endNumberIndex] > '9')
                        break;

                    endNumberIndex++;
                }

                string s = format.Substring(beginNumberIndex, endNumberIndex - beginNumberIndex);
                PropertyInfo p = properties[int.Parse(s) - 1]; // the indexes in the formatting strings are 1-based
                tokens.Add(
                    Expression.Call(
                        Expression.Property(par, p),
                        p.PropertyType.GetMethod("ToString", new Type[] {})));

                startIndex = endNumberIndex;
            }

            MethodCallExpression call = Expression.Call(
                typeof (EventFormatter).GetMethod("Concatenate", BindingFlags.Static | BindingFlags.NonPublic),
                Expression.NewArrayInit(typeof (string), tokens.ToArray()));

            LambdaExpression exp = Expression.Lambda(call, par);
            return exp;
        }