internal CommandLineInfoHandler(object commandlineinfo)
            {
                Type infoType = commandlineinfo.GetType();

                SortedList <int, MemberInfo> argumentHandlers = new SortedList <int, MemberInfo>();

                foreach (MemberInfo member in infoType.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetField | BindingFlags.GetProperty))
                {
                    // Retrieve help options:
                    CommandHelpAttribute helpattr = CommandHelpAttribute.Get(member);
                    if (helpattr != null)
                    {
                        this.HelpOptions.AddRange(helpattr.HelpOptions);
                        this.HelpHandler = member;
                        continue; // Skip testing other types of handlers
                    }

                    // Retrieve argument handlers:
                    CommandArgAttribute argattr = CommandArgAttribute.Get(member);
                    if (argattr != null)
                    {
                        argumentHandlers.Add(argattr.Order, member);
                        if (argattr.IsRequired)
                        {
                            this.NumberOfRequiredArgs++;
                        }
                        continue; // Skip testing other types of handlers
                    }

                    // Retrieve argumentlist handler:
                    CommandArgListAttribute arglistattr = CommandArgListAttribute.Get(member);
                    if (arglistattr != null)
                    {
                        this.ArgumentListHandler = member;

                        // Initialize the member to empty list:
                        if (member is FieldInfo)
                        {
                            ((FieldInfo)member).SetValue(commandlineinfo, new List <string>());
                        }
                        else // Assume PropertyInfo
                        {
                            ((PropertyInfo)member).SetValue(commandlineinfo, new List <string>(), null);
                        }

                        if (arglistattr.IsRequired)
                        {
                            this.NumberOfRequiredArgs++;
                        }
                        continue;                         // Skip testing other types of handlers
                    }

                    // Retrieve option handlers:
                    CommandOptionAttribute optattr = CommandOptionAttribute.Get(member);
                    if (optattr != null)
                    {
                        // Option values:
                        Dictionary <string, object> values = new Dictionary <string, object>();

                        // Register name, and eventual shortname:
                        this.OptionHandlers.Add(optattr.Name, member);
                        this.OptionValues.Add(optattr.Name, values);
                        if (optattr.ShortName != null)
                        {
                            this.OptionHandlers.Add(optattr.ShortName, member);
                            this.OptionValues.Add(optattr.ShortName, values);
                        }

                        // If not required, then default value is provided:
                        if (optattr.IsRequired == false)
                        {
                            // Set default value:
                            if (member is FieldInfo)
                            {
                                ((FieldInfo)member).SetValue(commandlineinfo, optattr.DefaultValue);
                            }
                            else if (member is PropertyInfo)
                            {
                                ((PropertyInfo)member).SetValue(commandlineinfo, optattr.DefaultValue, null);
                            }
                        }

                        // Retrieve optionValues:
                        CommandOptionValueAttribute[] optvalattrs = CommandOptionAttribute.GetValues(member);
                        foreach (CommandOptionValueAttribute valattr in optvalattrs)
                        {
                            values.Add(valattr.UserValue, valattr.Value);
                        }
                    }
                }

                this.ArgumentHandlers = argumentHandlers.Values;
            }
        /// <summary>
        /// Generate the parameter section of commandline help
        /// based on the given commandlineinfo type.
        /// The commandlineinfo type must have fields or properties
        /// decorated with CommandArg, CommandOption,... attributes.
        /// </summary>
        public string GenerateHelp(Type commandlineinfotype)
        {
            StringBuilder sb = new StringBuilder();

            Assembly   entryAssembly          = Assembly.GetEntryAssembly();
            MemberInfo help                   = null;
            SortedList <int, MemberInfo> args = new SortedList <int, MemberInfo>();
            MemberInfo        argList         = null;
            List <MemberInfo> options         = new List <MemberInfo>();

            // Retrieve members:
            foreach (MemberInfo member in commandlineinfotype.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetField | BindingFlags.GetProperty))
            {
                if (CommandArgAttribute.Get(member) != null)
                {
                    args.Add(CommandArgAttribute.Get(member).Order, member);
                }
                else if (CommandArgListAttribute.Get(member) != null)
                {
                    argList = member;
                }
                else if (CommandOptionAttribute.Get(member) != null)
                {
                    options.Add(member);
                }
                else if (CommandHelpAttribute.Get(member) != null)
                {
                    help = member;
                }
            }

            // Write application title:
            sb.AppendLine(((AssemblyTitleAttribute)entryAssembly.GetCustomAttributes(typeof(AssemblyTitleAttribute), false)[0]).Title);
            sb.AppendLine();

            // Write application description:
            if (commandlineinfotype.GetCustomAttributes(typeof(CommandInfoAttribute), false).Length > 0)
            {
                // Based on CommandInfoAttribute if available:
                sb.AppendLine(((CommandInfoAttribute)commandlineinfotype.GetCustomAttributes(typeof(CommandInfoAttribute), false)[0]).Description);
                sb.AppendLine();
            }
            else
            {
                // Else based on AssemblyDescriptionAttribute:
                var descattr = ((AssemblyDescriptionAttribute)entryAssembly.GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false)[0]);
                if ((descattr != null) && (!String.IsNullOrWhiteSpace(descattr.Description)))
                {
                    sb.AppendLine(descattr.Description);
                    sb.AppendLine();
                }
            }

            // Write syntax:
            sb.AppendLine("Syntax:");
            sb.Append(" {command}");
            foreach (MemberInfo argMember in args.Values)
            {
                CommandArgAttribute argDef = CommandArgAttribute.Get(argMember);
                sb.Append(' ');

                sb.Append((argDef.IsRequired) ? '<' : '[');
                sb.Append(argDef.Name);
                sb.Append((argDef.IsRequired) ? '>' : ']');
            }
            if (argList != null)
            {
                CommandArgListAttribute arglDef = CommandArgListAttribute.Get(argList);
                sb.Append(' ');
                sb.Append((arglDef.IsRequired) ? '<' : '[');
                sb.Append(arglDef.Name);
                sb.Append("...");
                sb.Append((arglDef.IsRequired) ? '>' : ']');
            }
            foreach (MemberInfo optMember in options)
            {
                CommandOptionAttribute optDef = CommandOptionAttribute.Get(optMember);
                Type optType = CommandOptionAttribute.GetValueType(optMember);
                CommandOptionValueAttribute[] optValues = CommandOptionAttribute.GetValues(optMember);

                sb.Append(' ');

                if (optDef.IsRequired == false)
                {
                    sb.Append('[');
                }

                sb.Append(this.optionMarker);
                sb.Append(optDef.Name);

                if (optValues.Length > 0)
                {
                    sb.Append(this.valueSeparator);
                    string separator = "";
                    foreach (CommandOptionValueAttribute value in optValues)
                    {
                        sb.Append(separator);
                        sb.Append(value.UserValue);
                        separator = "|";
                    }
                }
                else if (optType.Equals(typeof(Boolean)) == false)
                {
                    sb.Append(this.valueSeparator);
                    sb.Append("?");
                }

                if (optDef.IsRequired == false)
                {
                    sb.Append(']');
                }
            }
            sb.AppendLine();
            sb.AppendLine();

            // Write argument details:
            foreach (MemberInfo argMember in args.Values)
            {
                CommandArgAttribute  argDef = CommandArgAttribute.Get(argMember);
                CommandInfoAttribute info   = CommandInfoAttribute.Get(argMember);

                sb.Append(' ');
                sb.Append(String.Concat(argDef.Name, new String(' ', 13)).Substring(0, 13));
                sb.Append(' ');
                if (info != null)
                {
                    sb.Append(info.Description);
                }
                else
                {
                    sb.Append(argDef.Name);
                }
                sb.AppendLine();
            }
            if (argList != null)
            {
                CommandArgListAttribute arglDef = CommandArgListAttribute.Get(argList);
                CommandInfoAttribute    info    = CommandInfoAttribute.Get(argList);

                sb.Append(' ');
                sb.Append(String.Concat(arglDef.Name, new String(' ', 13)).Substring(0, 13));
                sb.Append(' ');
                if (info != null)
                {
                    sb.Append(info.Description);
                }
                else
                {
                    sb.Append("...");
                }
                sb.AppendLine();
            }

            // Write option details:
            foreach (MemberInfo optMember in options)
            {
                CommandOptionAttribute optDef = CommandOptionAttribute.Get(optMember);
                CommandInfoAttribute   info   = CommandInfoAttribute.Get(optMember);
                Type optType = CommandOptionAttribute.GetValueType(optMember);
                CommandOptionValueAttribute[] optValues = CommandOptionAttribute.GetValues(optMember);

                string optname = this.optionMarker + optDef.Name;
                if (optDef.ShortName != null)
                {
                    optname += "|" + optDef.ShortName;
                }

                sb.Append(' ');
                sb.Append(String.Concat(optname, new String(' ', 13)).Substring(0, 13));
                sb.Append(' ');
                if (info != null)
                {
                    sb.Append(info.Description);
                }
                else
                {
                    sb.Append(optDef.Name);
                }
                if (optValues.Length > 0)
                {
                    sb.Append(':');
                }
                sb.AppendLine();
                foreach (CommandOptionValueAttribute value in optValues)
                {
                    sb.Append("   ");
                    sb.Append(String.Concat(value.UserValue, new String(' ', 13)).Substring(0, 13));
                    sb.Append(' ');
                    sb.Append(value.Description);
                    sb.AppendLine();
                }
            }
            sb.AppendLine();

            // Write samples:
            if (commandlineinfotype.GetCustomAttributes(typeof(CommandExampleAttribute), false).Length > 0)
            {
                sb.AppendLine("Examples:");
                CommandExampleAttribute[] samples = CommandExampleAttribute.GetValues(commandlineinfotype);
                for (int i = samples.Length - 1; i >= 0; i--)
                {
                    CommandExampleAttribute sample = samples[i];
                    sb.Append(" {command} ");
                    sb.AppendLine(sample.Sample);
                    if (!String.IsNullOrEmpty(sample.Description))
                    {
                        sb.Append("    ");
                        sb.AppendLine(sample.Description);
                    }
                }
                sb.AppendLine();
            }

            // Write application copyright:
            if (AssemblyCopyrightAttribute.GetCustomAttribute(entryAssembly, typeof(AssemblyCopyrightAttribute)) != null)
            {
                sb.AppendLine(((AssemblyCopyrightAttribute)AssemblyCopyrightAttribute.GetCustomAttribute(entryAssembly, typeof(AssemblyCopyrightAttribute))).Copyright.Replace("©", "(C)"));
                sb.AppendLine();
            }

            // Perform substitutions of variables:
            sb = sb.Replace("{command}", System.Diagnostics.Process.GetCurrentProcess().ProcessName);

            // Returns the whole help:
            return(sb.ToString());
        }