public string Format(string line, string data, params string[] values)
        {
            // #TODO Logic for skip line should be implemented somewhere here.

            StringBuilder      sb                 = new StringBuilder();
            PlaceHolder        placeholder        = new PlaceHolder();
            PlaceHolderMethods placeholderMethods = new PlaceHolderMethods();
            bool skippedData = false;

            foreach (PlaceHolder p in PlaceHolders)
            {
                if (p.GetType() == typeof(PlaceHolder))
                {
                    placeholder = (PlaceHolder)p;
                    sb.Append(placeholder.Text);
                }
                if (p.GetType() == typeof(PlaceHolderMethods))
                {
                    placeholderMethods = (PlaceHolderMethods)p;
                    sb.Append(placeholderMethods.Execute(values, line, data, LineNumber, IsLastCommand, out skippedData));
                    if (skippedData)
                    {
                        LineNumber++;
                        return(string.Empty);
                    }
                }
            }
            LineNumber++;
            return(sb.ToString());
        }
        private void CompilePlaceHolder(string[] templates, string template)
        {
            // First element in placeholder has two tastes name or index.
            string[] fields      = Utils.TrimByLength(template, 1).Split(new char[] { ':' });
            string   inlinecalls = string.Empty;
            int      pointer     = -1;

            // {0}
            // {0:Guid}
            // {Guid}
            if (fields.Length == 1)
            {
                if (Utils.IsNumeric(fields[0]) || fields[0] == "X" || fields[0] == "Y")
                {
                    // index based
                    pointer = ConvertUtility.ToInt32(fields[0], 0);

                    if (fields[0] == "X")
                    {
                        pointer = -2;
                    }

                    if (fields[0] == "Y")
                    {
                        pointer = -3;
                    }

                    PlaceHolderMethods phmIndexOnly = new PlaceHolderMethods();
                    phmIndexOnly.Methods     = new List <MethodBase>();
                    phmIndexOnly.Templates   = templates;
                    phmIndexOnly.Text        = template;
                    phmIndexOnly.ValuesIndex = pointer;
                    this.PlaceHolders.Add(phmIndexOnly);
                    return;
                }
                else
                {
                    // Method based
                    inlinecalls = fields[0];
                }
            }
            if (fields.Length == 2)
            {
                // index based
                pointer = ConvertUtility.ToInt32(fields[0], 0);
                if (fields[0] == "X")
                {
                    pointer = -2;
                }

                if (fields[0] == "Y")
                {
                    pointer = -3;
                }

                inlinecalls = fields[1];
            }

            // find out which methods to use.
            string[] methodcalls = Utils.SplitEscaped(inlinecalls, ",", "(", ")");

            PlaceHolderMethods phm = new PlaceHolderMethods();

            phm.Text        = template;
            phm.Templates   = templates;
            phm.ValuesIndex = pointer;

            foreach (string call in methodcalls)
            {
                MethodInstance clone = MethodInstance.GetMethodInstance(getCallName(call));
                if (clone != null)
                {
                    // can be Guid, Guid() PadLeft(3,0) etc
                    // parameters
                    string   parametersString = getCallParameters(call).Trim(new char[] { '(', ')' });
                    string[] parameters       = Utils.SplitEscaped(parametersString, ',', '"');

                    for (int ii = 0; ii < parameters.Length; ii++)
                    {
                        parameters[ii] = parameters[ii].Trim();
                        if (parameters[ii].Length > 1)
                        {
                            parameters[ii] = parameters[ii].Trim(new char[] { '"' });
                        }

                        Type t = typeof(object);
                        if (clone.Properties.Count > 0)
                        {
                            t = clone.Properties[Utils.Bound(ii, 0, clone.Properties.Count)].PropertyReference.PropertyType;
                        }
                        if (ii < clone.Properties.Count)
                        {
                            if (StringTemplateItem.PropertyTypeSupported(t))
                            {
                                StringTemplateItem.SetPropertyValue(clone.Properties[ii].PropertyReference, clone.Formatter, parameters[ii]);
                            }

                            if (StringTemplateItem.PropertyArrayTypeSupported(t))
                            {
                                // if next property to be set is an array, all remaining parameters will be asigned to this property.
                                StringTemplateItem.SetPropertyValueArray(clone.Properties[ii].PropertyReference, clone.Formatter, parameters, ii);
                                break;
                            }
                        }
                    }
                    phm.Methods.Add(clone.Formatter);
                }
            }
            this.PlaceHolders.Add(phm);
        }