internal static bool TryGetDefaultValue(ChoCommandLineArgObject target, string propName,
                                                ChoDefaultCommandLineArgAttribute memberInfoAttribute, out string defaultValue)
        {
            defaultValue = null;

            ChoGuard.ArgumentNotNull(target, "CommandLineArgObject");
            ChoGuard.ArgumentNotNull(propName, "PropertyName");

            ChoPropertyInfos propertyInfo = GetPropertyInfos(target);

            if (propertyInfo != null)
            {
                ChoPropertyInfo propInfo = propertyInfo[propName];
                if (propInfo == null)
                {
                    if (memberInfoAttribute != null && memberInfoAttribute.IsDefaultValueSpecified)
                    {
                        defaultValue = memberInfoAttribute.DefaultValue;
                        return(memberInfoAttribute.IsDefaultValueSpecified);
                    }
                }

                defaultValue = propInfo != null && propInfo.DefaultValue != null ? propInfo.DefaultValue.Value : null;
                return(propInfo != null ? propInfo.IsDefaultValueSpecified : false);
            }
            else if (memberInfoAttribute != null && memberInfoAttribute.IsDefaultValueSpecified)
            {
                defaultValue = memberInfoAttribute.DefaultValue;
                return(memberInfoAttribute.IsDefaultValueSpecified);
            }

            return(false);
        }
        private static void SetMetaDataSection(ChoCommandLineArgObject cmdLineArgObject, ChoPropertyInfos propertyInfos)
        {
            return;

            if (cmdLineArgObject == null)
            {
                return;
            }

            string elementPath = cmdLineArgObject.GetType().Name;

            using (ChoXmlDocument xmlDocument = new ChoXmlDocument(_metaDataFilepath))
            {
                if (elementPath.IsNullOrEmpty())
                {
                    return;
                }

                XmlNode node = xmlDocument.XmlDocument.SelectSingleNode(elementPath);
                if (node == null)
                {
                    node = xmlDocument.XmlDocument.MakeXPath(elementPath);
                }

                if (node != null)
                {
                    xmlDocument.XmlDocument.InnerXml = ChoXmlDocument.AppendToInnerXml(node, propertyInfos.ToXml());

                    xmlDocument.Save();
                }
            }
        }
        private static ChoPropertyInfos GetPropertyInfos(ChoCommandLineArgObject cmdLineArgObject)
        {
            string elementPath = cmdLineArgObject.GetType().Name;

            if (elementPath.IsNullOrWhiteSpace())
            {
                return(null);
            }

            Dictionary <string, ChoPropertyInfos> propDict = _propDict;

            if (!propDict.ContainsKey(elementPath))
            {
                lock (_padLock)
                {
                    if (!propDict.ContainsKey(elementPath))
                    {
                        string  xpath = @"//{0}/propertyInfos".FormatString(elementPath);
                        XmlNode node  = null;

                        if (_rootNode != null)
                        {
                            node = _rootNode.SelectSingleNode(xpath);
                        }

                        if (node != null)
                        {
                            propDict.Add(elementPath, ChoPropertyInfos.Default);

                            ChoPropertyInfos propertyInfos = node.ToObject(typeof(ChoPropertyInfos)) as ChoPropertyInfos;
                            propertyInfos.Initialize();
                            propDict[elementPath] = propertyInfos;
                        }
                        else
                        {
                            propDict[elementPath] = ConstructPropertyInfos(cmdLineArgObject);
                        }
                    }
                }
            }

            return(propDict.ContainsKey(elementPath) ? propDict[elementPath] : null);
        }
        public static void Load(object target, string[] commandLineArgs)
        {
            ChoGuard.ArgumentNotNull(target, "Target");

            ChoCommandLineArgObject commandLineArgObject = target as ChoCommandLineArgObject;

            Exception exception = null;

            if (commandLineArgObject != null)
            {
                commandLineArgObject.CommandLineArgs = commandLineArgs;
            }

            using (ChoCommandLineArgParser commandLineArgParser = new ChoCommandLineArgParser(commandLineArgs))
            {
                commandLineArgParser.UnrecognizedCommandLineArgFound += ((sender, eventArgs) =>
                {
                    if (commandLineArgObject != null)
                    {
                        commandLineArgObject.OnUnrecognizedCommandLineArgFound(eventArgs);
                    }
                });

                commandLineArgParser.Parse();

                if (commandLineArgParser.IsUsageArgSpecified)
                {
                    throw new ChoCommandLineArgUsageException(GetUsage(target));
                }

                string cmdLineSwitch = null;
                if (commandLineArgObject == null || !commandLineArgObject.OnBeforeCommandLineArgObjectLoaded(commandLineArgs))
                {
                    MemberInfo[] memberInfos  = ChoType.GetMemberInfos(target.GetType(), typeof(ChoCommandLineArgAttribute));
                    MemberInfo[] memberInfos1 = ChoType.GetMemberInfos(target.GetType(), typeof(ChoDefaultCommandLineArgAttribute));

                    ChoCommandLineParserSettings commandLineParserSettings = ChoCommandLineParserSettings.Me;
                    memberInfos = memberInfos.Concat(memberInfos1).ToArray();
                    if (memberInfos != null && memberInfos.Length > 0)
                    {
                        foreach (MemberInfo memberInfo in memberInfos)
                        {
                            ChoCommandLineArgAttribute commandLineArgumentAttribute = (ChoCommandLineArgAttribute)memberInfo.GetCustomAttribute <ChoCommandLineArgAttribute>(true);
                            if (commandLineArgumentAttribute == null)
                            {
                                continue;
                            }

                            cmdLineSwitch = commandLineArgumentAttribute.CommandLineSwitch;
                            bool isSwitchSpecified = IsSwitchSpecified(commandLineArgParser.Switches, cmdLineSwitch, commandLineParserSettings.IgnoreCase);

                            exception = ExtractNPopulateValue(target, memberInfo, cmdLineSwitch, commandLineArgParser, commandLineArgObject, isSwitchSpecified);

                            if (exception != null)
                            {
                                break;
                            }
                        }

                        if (exception == null)
                        {
                            cmdLineSwitch = DefaultCmdLineSwitch;
                            MemberInfo defaultMemberInfo = GetMemberForDefaultSwitch(memberInfos1);
                            exception = ExtractNPopulateValue(target, defaultMemberInfo, DefaultCmdLineSwitch, commandLineArgParser, commandLineArgObject, false);
                        }
                    }
                }

                if (commandLineArgObject != null)
                {
                    if (exception != null)
                    {
                        if (!commandLineArgObject.OnCommandLineArgObjectLoadError(commandLineArgs, exception))
                        {
                            throw new ChoCommandLineArgException("Found exception while loading `{3}` command line argument. {0}{0}{2}{0}{0}{1}".FormatString(
                                                                     Environment.NewLine, GetUsage(target), exception.Message, cmdLineSwitch), exception);
                        }
                    }
                    else
                    {
                        commandLineArgObject.OnAfterCommandLineArgObjectLoaded(commandLineArgs);
                    }
                }
            }
        }
        private static Exception ExtractNPopulateValue(object target, MemberInfo memberInfo, string switchString, ChoCommandLineArgParser commandLineArgParser,
                                                       ChoCommandLineArgObject commandLineArgObject, bool isSwitchSpecified)
        {
            ChoCommandLineArgAttribute        commandLineArgumentAttribute   = null;
            ChoDefaultCommandLineArgAttribute defaultCommandLineArgAttribute = null;

            if (memberInfo == null)
            {
                if (commandLineArgObject != null)
                {
                    commandLineArgObject.OnCommandLineArgMemberNotFound(switchString, commandLineArgParser[switchString]);
                }
            }
            else
            {
                //if (ChoType.IsReadOnlyMember(memberInfo))
                //    return null;

                commandLineArgumentAttribute   = null;
                defaultCommandLineArgAttribute = null;

                commandLineArgumentAttribute = (ChoCommandLineArgAttribute)memberInfo.GetCustomAttribute <ChoCommandLineArgAttribute>(true);
                if (commandLineArgumentAttribute == null)
                {
                    defaultCommandLineArgAttribute = (ChoDefaultCommandLineArgAttribute)memberInfo.GetCustomAttribute <ChoDefaultCommandLineArgAttribute>(true);
                    if (defaultCommandLineArgAttribute == null)
                    {
                        return(null);
                    }
                }

                string cmdLineArgValue    = null;
                object newCmdLineArgValue = null;

                try
                {
                    if (defaultCommandLineArgAttribute != null)
                    {
                        cmdLineArgValue = commandLineArgParser.DefaultArgs.Length > 0 ? commandLineArgParser.DefaultArgs[0] : null;
                    }
                    else if (commandLineArgumentAttribute != null)
                    {
                        cmdLineArgValue = commandLineArgParser[commandLineArgumentAttribute.CommandLineSwitch];
                        defaultCommandLineArgAttribute = commandLineArgumentAttribute;
                    }
                    else
                    {
                        return(null);
                    }

                    object defaultCmdLineArgValue = defaultCommandLineArgAttribute.DefaultValue;

                    if (isSwitchSpecified && cmdLineArgValue == null && defaultCommandLineArgAttribute.FallbackValue != null)
                    {
                        defaultCmdLineArgValue = defaultCommandLineArgAttribute.FallbackValue;
                    }

                    if (commandLineArgObject == null || !commandLineArgObject.OnBeforeCommandLineArgLoaded(memberInfo.Name, cmdLineArgValue, defaultCommandLineArgAttribute.DefaultValue, defaultCommandLineArgAttribute.FallbackValue))
                    {
                        if (!cmdLineArgValue.IsNullOrWhiteSpace())
                        {
                            newCmdLineArgValue = ChoConvert.ConvertFrom(target, ChoString.ExpandPropertiesEx(cmdLineArgValue),
                                                                        ChoType.GetMemberType(memberInfo),
                                                                        ChoTypeDescriptor.GetTypeConverters(memberInfo), ChoTypeDescriptor.GetTypeConverterParams(memberInfo));
                        }
                        else if (defaultCmdLineArgValue != null)
                        {
                            if (defaultCmdLineArgValue is string)
                            {
                                newCmdLineArgValue = ChoConvert.ConvertFrom(target, ChoString.ExpandPropertiesEx(defaultCmdLineArgValue as string),
                                                                            ChoType.GetMemberType(memberInfo),
                                                                            ChoTypeDescriptor.GetTypeConverters(memberInfo), ChoTypeDescriptor.GetTypeConverterParams(memberInfo));
                            }
                            else
                            {
                                newCmdLineArgValue = ChoConvert.ConvertFrom(target, defaultCmdLineArgValue, ChoType.GetMemberType(memberInfo),
                                                                            ChoTypeDescriptor.GetTypeConverters(memberInfo), ChoTypeDescriptor.GetTypeConverterParams(memberInfo));
                            }
                        }

                        if (newCmdLineArgValue != null)
                        {
                            ChoType.SetMemberValue(target, memberInfo, newCmdLineArgValue);
                            if (commandLineArgObject != null)
                            {
                                commandLineArgObject.OnAfterCommandLineArgLoaded(memberInfo.Name, newCmdLineArgValue);
                            }
                        }
                        else if (defaultCommandLineArgAttribute.IsRequired)
                        {
                            throw new ChoCommandLineArgException("Missing arg value for '{0}' required command line switch.".FormatString(
                                                                     commandLineArgumentAttribute == null ? DefaultCmdLineSwitch : commandLineArgumentAttribute.CommandLineSwitch));
                        }
                    }
                }
                catch (ChoFatalApplicationException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    if (commandLineArgObject != null && commandLineArgObject.OnCommandLineArgLoadError(memberInfo.Name, cmdLineArgValue, ex))
                    {
                    }
                    else
                    {
                        return(ex);
                    }
                }
            }

            return(null);
        }
        private static ChoPropertyInfos ConstructPropertyInfos(ChoCommandLineArgObject cmdLineArgObject)
        {
            if (cmdLineArgObject != null)
            {
                Dictionary <string, ChoPropertyInfos> propDict = _propDict;
                string elementPath = cmdLineArgObject.GetType().Name;

                if (elementPath.IsNullOrWhiteSpace())
                {
                    return(ChoPropertyInfos.Default);
                }

                if (!propDict.ContainsKey(elementPath))
                {
                    lock (_padLock)
                    {
                        if (!propDict.ContainsKey(elementPath))
                        {
                            MemberInfo[] memberInfos = ChoTypeMembersCache.GetAllMemberInfos(cmdLineArgObject.GetType());
                            if (memberInfos != null && memberInfos.Length > 0)
                            {
                                //Set member values
                                List <ChoPropertyInfo>            propertyInfoList    = new List <ChoPropertyInfo>();
                                ChoDefaultCommandLineArgAttribute memberInfoAttribute = null;

                                foreach (MemberInfo memberInfo in memberInfos)
                                {
                                    memberInfoAttribute = (ChoDefaultCommandLineArgAttribute)ChoType.GetMemberAttributeByBaseType(memberInfo, typeof(ChoDefaultCommandLineArgAttribute));
                                    if (memberInfoAttribute == null)
                                    {
                                        continue;
                                    }

                                    ChoPropertyInfo propInfo = new ChoPropertyInfo();

                                    propInfo.Name = ChoType.GetMemberName(memberInfo);

                                    if (ChoType.GetMemberType(memberInfo) != typeof(bool))
                                    {
                                        propInfo.DefaultValue             = new ChoCDATA(memberInfoAttribute.DefaultValue);
                                        propInfo.FallbackValue            = new ChoCDATA(memberInfoAttribute.FallbackValue);
                                        propInfo.IsDefaultValueSpecified  = memberInfoAttribute.IsDefaultValueSpecified;
                                        propInfo.IsFallbackValueSpecified = memberInfoAttribute.IsFallbackValueSpecified;
                                        propertyInfoList.Add(propInfo);
                                    }
                                }

                                if (propertyInfoList != null)
                                {
                                    ChoPropertyInfos propertyInfos = new ChoPropertyInfos();
                                    propertyInfos.PropertyInfoArr = propertyInfoList.ToArray();

                                    SetMetaDataSection(cmdLineArgObject, propertyInfos);
                                    return(propertyInfos);
                                }
                            }
                        }
                    }
                }
            }

            return(ChoPropertyInfos.Default);
        }
        public static void Load(object target, string[] commandLineArgs)
        {
            ChoGuard.ArgumentNotNull(target, "Target");

            ChoCommandLineArgBuilder commandLineArgBuilder = target as ChoCommandLineArgBuilder;

            if (commandLineArgBuilder == null)
            {
                throw new ChoApplicationException("Target is not ChoCommandLineArgBuilder.");
            }

            using (ChoCommandLineArgParser commandLineArgParser = new ChoCommandLineArgParser())
            {
                //commandLineArgParser.UnrecognizedCommandLineArgFound += ((sender, eventArgs) =>
                //{
                //    if (commandLineArgBuilder != null)
                //        commandLineArgBuilder.RaiseUnrecognizedCommandLineArgFound(eventArgs);
                //});

                commandLineArgParser.Parse(commandLineArgs);
                if (commandLineArgBuilder != null)
                {
                    ChoEnvironment.CommandLineArgs = ChoEnvironment.CommandLineArgs.Skip(1).ToArray();
                }

                bool isUsageAvail = true;
                ChoCommandLineArgObjectAttribute commandLineArgumentsObjectAttribute = commandLineArgBuilder.GetType().GetCustomAttribute(typeof(ChoCommandLineArgObjectAttribute)) as ChoCommandLineArgObjectAttribute;
                if (commandLineArgumentsObjectAttribute != null)
                {
                    isUsageAvail = !commandLineArgumentsObjectAttribute.Silent;
                }

                if (commandLineArgParser.PosArgs.Length == 0 && commandLineArgParser.Switches.Count == 0)
                {
                    if (isUsageAvail)
                    {
                        throw new ChoCommandLineArgUsageException(commandLineArgBuilder.GetUsage());
                    }
                }

                if (commandLineArgParser.PosArgs.Length == 0 && commandLineArgParser.IsUsageArgSpecified)
                {
                    if (isUsageAvail)
                    {
                        throw new ChoCommandLineArgUsageException(commandLineArgBuilder.GetUsage());
                    }
                }

                string command = commandLineArgParser.PosArgs[0];
                if (command.IsNullOrWhiteSpace())
                {
                    if (isUsageAvail)
                    {
                        throw new ChoCommandLineArgUsageException(commandLineArgBuilder.GetUsage());
                    }
                }

                Type commandLineArgObjectType = commandLineArgBuilder.GetCommandLineArgObjectType(command);

                if (commandLineArgObjectType == null)
                {
                    if (isUsageAvail)
                    {
                        throw new ChoCommandLineArgUsageException("Command '{1}' not found.{0}{0}{2}".FormatString(Environment.NewLine, command, commandLineArgBuilder.GetUsage()));
                    }
                }

                try
                {
                    ChoCommandLineArgObject argObj = ChoActivator.CreateInstance(commandLineArgObjectType) as ChoCommandLineArgObject;
                    commandLineArgBuilder.CommandLineArgObject = argObj;
                }
                catch (ChoCommandLineArgUsageException uEx)
                {
                    throw new ChoCommandLineArgUsageException(uEx.Message.Insert(uEx.Message.IndexOf(' '), " " + command));
                }
                catch (ChoCommandLineArgException aEx)
                {
                    throw new ChoCommandLineArgUsageException(
                              "{1}{0}{0}{2}".FormatString(Environment.NewLine, aEx.ErrorMessage, aEx.UsageMessage.Insert(aEx.UsageMessage.IndexOf(' '), " " + command)));
                }
            }
        }
        //private static void AssignToDefaultValues(ChoCommandLineArgObject commandLineArgObject)
        //{
        //    object newCmdLineArgValue = null;

        //    string name = null;
        //    string defaultValue = null;
        //    bool isDefaultValueSpecified;
        //    MemberInfo[] memberInfos = ChoTypeMembersCache.GetAllMemberInfos(commandLineArgObject.GetType());
        //    if (memberInfos != null && memberInfos.Length > 0)
        //    {
        //        ChoCommandLineArgAttribute defaultCommandLineArgAttribute = null;
        //        foreach (MemberInfo memberInfo in memberInfos)
        //        {
        //            defaultCommandLineArgAttribute = (ChoCommandLineArgAttribute)ChoType.GetMemberAttribute(memberInfo, typeof(ChoCommandLineArgAttribute));
        //            if (defaultCommandLineArgAttribute == null) continue;

        //            name = ChoType.GetMemberName(memberInfo);
        //            defaultValue = null;
        //            if (ChoType.GetMemberType(memberInfo) == typeof(bool))
        //                continue;

        //            isDefaultValueSpecified = ChoCmdLineArgMetaDataManager.TryGetDefaultValue(commandLineArgObject, name, defaultCommandLineArgAttribute, out defaultValue);
        //            if (!isDefaultValueSpecified)
        //                continue;
        //            try
        //            {
        //                defaultValue = ChoString.ExpandPropertiesEx(defaultValue);
        //                object newConvertedValue = ChoConvert.ConvertFrom(defaultValue, memberInfo, commandLineArgObject);

        //                //object newConvertedValue = ChoConvert.ConvertFrom(commandLineArgObject, defaultValue, ChoType.GetMemberType(memberInfo),
        //                //    ChoTypeDescriptor.GetTypeConverters(memberInfo), ChoTypeDescriptor.GetTypeConverterParams(memberInfo));
        //                ChoType.SetMemberValue(commandLineArgObject, memberInfo, newCmdLineArgValue);
        //            }
        //            catch //(Exception ex)
        //            {
        //            }
        //        }
        //    }
        //}

        private static Exception ExtractNPopulateValue(ChoCommandLineArgObject commandLineArgObject, MemberInfo memberInfo, ChoCommandLineArgParser commandLineArgParser)
        {
            ChoDefaultCommandLineArgAttribute    defaultCommandLineArgAttribute = null;
            ChoCommandLineArgAttribute           commandLineArgumentAttribute   = null;
            ChoPositionalCommandLineArgAttribute posCommandLineArgAttribute     = null;

            if (ChoType.IsReadOnlyMember(memberInfo))
            {
                return(null);
            }

            commandLineArgumentAttribute = null;
            posCommandLineArgAttribute   = null;

            defaultCommandLineArgAttribute = commandLineArgumentAttribute = (ChoCommandLineArgAttribute)memberInfo.GetCustomAttribute <ChoCommandLineArgAttribute>(true);
            if (commandLineArgumentAttribute == null)
            {
                defaultCommandLineArgAttribute = posCommandLineArgAttribute = (ChoPositionalCommandLineArgAttribute)memberInfo.GetCustomAttribute <ChoPositionalCommandLineArgAttribute>(true);
                if (posCommandLineArgAttribute == null)
                {
                    return(null);
                }
            }

            bool   containsCmdLineArg       = false;
            string cmdLineArgValue          = null;
            object newCmdLineArgValue       = null;
            string defaultValue             = null;
            bool   isDefaultValueSpecified  = false;
            bool   isFallbackValueSpecified = false;
            string name             = null;
            string fallbackValue    = null;
            object fallbackValueObj = null;
            object defaultValueObj  = null;

            name = ChoType.GetMemberName(memberInfo);

            try
            {
                if (posCommandLineArgAttribute != null)
                {
                    if (!commandLineArgParser.IsSwitchSpecified(posCommandLineArgAttribute.Position))
                    {
                        commandLineArgObject.RaiseCommandLineArgNotFound(posCommandLineArgAttribute.Position.ToString(), ref cmdLineArgValue);
                    }
                    cmdLineArgValue = commandLineArgParser[posCommandLineArgAttribute.Position];
                }
                else if (commandLineArgumentAttribute != null)
                {
                    if (!commandLineArgParser.IsSwitchSpecified(commandLineArgumentAttribute.CommandLineSwitch))
                    {
                        commandLineArgObject.RaiseCommandLineArgNotFound(commandLineArgumentAttribute.CommandLineSwitch, ref cmdLineArgValue);
                    }

                    if (ChoType.GetMemberType(memberInfo) == typeof(bool))
                    {
                        containsCmdLineArg = IsSwitchSpecified(commandLineArgParser, commandLineArgumentAttribute.CommandLineSwitch, commandLineArgumentAttribute.Aliases);
                        if (containsCmdLineArg)
                        {
                            cmdLineArgValue = "True";
                            //cmdLineArgValue = GetCmdLineArgValue(commandLineArgParser, commandLineArgumentAttribute.CommandLineSwitch, commandLineArgumentAttribute.Aliases);
                            //if (cmdLineArgValue.IsNullOrWhiteSpace())
                            //    cmdLineArgValue = "True";
                        }
                        else
                        {
                            containsCmdLineArg = IsSwitchSpecified(commandLineArgParser, "{0}-".FormatString(commandLineArgumentAttribute.CommandLineSwitch), commandLineArgumentAttribute.Aliases);
                            if (containsCmdLineArg)
                            {
                                cmdLineArgValue = "False";
                            }
                        }
                    }
                    //else if (ChoType.GetMemberType(memberInfo).IsEnum)
                    //{
                    //    containsCmdLineArg = IsSwitchSpecified(commandLineArgParser, Enum.GetNames(ChoType.GetMemberType(memberInfo)));
                    //    if (containsCmdLineArg)
                    //        cmdLineArgValue = GetCmdLineArgValue(commandLineArgParser, Enum.GetNames(ChoType.GetMemberType(memberInfo)));
                    //    else
                    //        cmdLineArgValue = GetCmdLineArgValue(commandLineArgParser, commandLineArgumentAttribute.CommandLineSwitch, commandLineArgumentAttribute.Aliases);
                    //}
                    else
                    {
                        cmdLineArgValue = GetCmdLineArgValue(commandLineArgParser, commandLineArgumentAttribute.CommandLineSwitch, commandLineArgumentAttribute.Aliases);
                    }
                }
                else
                {
                    return(null);
                }

                //if (ChoType.GetMemberType(memberInfo) != typeof(bool))
                //{
                isDefaultValueSpecified  = ChoCmdLineArgMetaDataManager.TryGetDefaultValue(commandLineArgObject, name, defaultCommandLineArgAttribute, out defaultValue);
                isFallbackValueSpecified = ChoCmdLineArgMetaDataManager.TryGetFallbackValue(commandLineArgObject, name, defaultCommandLineArgAttribute, out fallbackValue);
                //}

                try
                {
                    if (isFallbackValueSpecified)
                    {
                        //                    fallbackValueObj = ChoConvert.ConvertFrom(commandLineArgObject, ChoString.ExpandPropertiesEx(fallbackValue),
                        //ChoType.GetMemberType(memberInfo),
                        //ChoTypeDescriptor.GetTypeConverters(memberInfo), ChoTypeDescriptor.GetTypeConverterParams(memberInfo));

                        fallbackValueObj = ChoConvert.ConvertFrom(ChoString.ExpandPropertiesEx(fallbackValue), memberInfo, commandLineArgObject);
                    }
                }
                catch
                {
                }

                try
                {
                    if (isDefaultValueSpecified)
                    {
                        //defaultValueObj = ChoConvert.ConvertFrom(commandLineArgObject, ChoString.ExpandPropertiesEx(defaultValue), ChoType.GetMemberType(memberInfo),
                        //    ChoTypeDescriptor.GetTypeConverters(memberInfo), ChoTypeDescriptor.GetTypeConverterParams(memberInfo));
                        defaultValueObj = ChoConvert.ConvertFrom(ChoString.ExpandPropertiesEx(defaultValue), memberInfo, commandLineArgObject);
                    }
                }
                catch
                {
                }

                if (commandLineArgObject != null && !commandLineArgObject.RaiseBeforeCommandLineArgLoaded(memberInfo.Name, ref cmdLineArgValue, defaultValueObj, fallbackValueObj))
                {
                    if (!cmdLineArgValue.IsNull())
                    {
                        newCmdLineArgValue = ChoConvert.ConvertFrom(ChoString.ExpandPropertiesEx(cmdLineArgValue), memberInfo, commandLineArgObject);

                        //newCmdLineArgValue = ChoConvert.ConvertFrom(commandLineArgObject, ChoString.ExpandPropertiesEx(cmdLineArgValue),
                        //    ChoType.GetMemberType(memberInfo),
                        //    ChoTypeDescriptor.GetTypeConverters(memberInfo), ChoTypeDescriptor.GetTypeConverterParams(memberInfo));
                    }

                    if (newCmdLineArgValue == null && defaultCommandLineArgAttribute.IsRequired)
                    {
                        if (ChoType.GetMemberType(memberInfo) != typeof(bool))
                        {
                            if (commandLineArgumentAttribute != null)
                            {
                                throw new ChoCommandLineArgException("Missing arg value for '{0}' required command line switch.".FormatString(
                                                                         commandLineArgumentAttribute == null ? ChoCommandLineArgObject.DefaultCmdLineSwitch : commandLineArgumentAttribute.CommandLineSwitch),
                                                                     commandLineArgObject.GetUsage());
                            }
                            else if (posCommandLineArgAttribute != null)
                            {
                                if (posCommandLineArgAttribute.ShortName.IsNull())
                                {
                                    throw new ChoCommandLineArgException("Missing positional arg value at '{0}' position.".FormatString(
                                                                             posCommandLineArgAttribute == null ? ChoCommandLineArgObject.DefaultCmdLineSwitch : posCommandLineArgAttribute.Position.ToString()), commandLineArgObject.GetUsage());
                                }
                                else
                                {
                                    throw new ChoCommandLineArgException("Missing '{0}' argument.".FormatString(posCommandLineArgAttribute.ShortName), commandLineArgObject.GetUsage());
                                }
                            }
                            else
                            {
                                throw new ChoCommandLineArgException("Missing arg value at '{0}' position.".FormatString(ChoCommandLineArgObject.DefaultCmdLineSwitch), commandLineArgObject.GetUsage());
                            }
                        }
                    }
                    else
                    {
                        if (newCmdLineArgValue == null)
                        {
                            if (isDefaultValueSpecified)
                            {
                                //if (ChoType.GetMemberType(memberInfo) != typeof(bool))
                                newCmdLineArgValue = defaultValueObj;
                                //else
                                //    newCmdLineArgValue = false;
                            }
                        }

                        ChoType.SetMemberValue(commandLineArgObject, memberInfo, newCmdLineArgValue);
                        if (commandLineArgObject != null)
                        {
                            commandLineArgObject.RaiseAfterCommandLineArgLoaded(memberInfo.Name, newCmdLineArgValue);
                        }
                    }
                }
            }
            catch (ChoFatalApplicationException)
            {
                throw;
            }
            catch (Exception ex)
            {
                if (commandLineArgObject != null && commandLineArgObject.RaiseCommandLineArgLoadError(memberInfo.Name, cmdLineArgValue, ex))
                {
                }
                else
                {
                    if (defaultCommandLineArgAttribute.IsRequired)
                    {
                        return(ex);
                    }

                    if (fallbackValueObj != null)
                    {
                        ChoType.SetMemberValue(commandLineArgObject, memberInfo, fallbackValueObj);
                    }
                    else
                    {
                        return(ex);
                    }
                }
            }
            return(null);
        }
        public static void Load(object target, string[] commandLineArgs)
        {
            ChoGuard.ArgumentNotNull(target, "Target");

            ChoCommandLineArgObject commandLineArgObject = target as ChoCommandLineArgObject;

            if (commandLineArgObject == null)
            {
                throw new ChoApplicationException("Target is not ChoCommandLineArgObject.");
            }

            ChoCommandLineArgObjectAttribute commandLineArgumentsObjectAttribute = commandLineArgObject.GetType().GetCustomAttribute(typeof(ChoCommandLineArgObjectAttribute)) as ChoCommandLineArgObjectAttribute;

            if (commandLineArgumentsObjectAttribute == null)
            {
                throw new ChoApplicationException("Missing ChoCommandLineArgObjectAttribute. Must be specified.");
            }

            ChoCommandLineParserSettings commandLineParserSettings = ChoCommandLineParserSettings.Me;

            bool isUsageAvail = !commandLineArgumentsObjectAttribute.Silent;

            bool showUsageIfEmpty = commandLineArgumentsObjectAttribute.GetShowUsageIfEmpty();

            if (commandLineArgs.IsNullOrEmpty() && showUsageIfEmpty)
            {
                if (isUsageAvail)
                {
                    throw new ChoCommandLineArgUsageException(commandLineArgObject.GetUsage());
                }
            }

            Exception exception = null;

            using (ChoCommandLineArgParser commandLineArgParser = new ChoCommandLineArgParser())
            {
                commandLineArgParser.UnrecognizedCommandLineArgFound += ((sender, eventArgs) =>
                {
                    if (commandLineArgObject != null)
                    {
                        commandLineArgObject.RaiseUnrecognizedCommandLineArgFound(eventArgs);
                    }
                });

                commandLineArgParser.Parse(commandLineArgs);

                if (commandLineArgObject != null)
                {
                    commandLineArgObject.CommandLineArgs = commandLineArgs;
                }

                if ((commandLineArgParser.IsUsageArgSpecified && commandLineArgumentsObjectAttribute.UsageSwitch.IsNullOrWhiteSpace()) ||
                    (!commandLineArgumentsObjectAttribute.UsageSwitch.IsNullOrWhiteSpace() && HasUsageSwitchSpecified(commandLineArgParser, commandLineArgumentsObjectAttribute))
                    )
                {
                    if (isUsageAvail)
                    {
                        throw new ChoCommandLineArgUsageException(commandLineArgObject.GetUsage());
                    }
                }

                string cmdLineSwitch = null;
                if (commandLineArgObject == null || !commandLineArgObject.RaiseBeforeCommandLineArgObjectLoaded(commandLineArgs))
                {
                    MemberInfo[] memberInfos  = ChoType.GetMemberInfos(target.GetType(), typeof(ChoCommandLineArgAttribute));
                    MemberInfo[] memberInfos1 = ChoType.GetMemberInfos(target.GetType(), typeof(ChoPositionalCommandLineArgAttribute));

                    memberInfos = memberInfos1.Concat(memberInfos).ToArray();
                    if (memberInfos != null && memberInfos.Length > 0)
                    {
                        foreach (MemberInfo memberInfo in memberInfos)
                        {
                            cmdLineSwitch = GetCmdLineSwitch(memberInfo);
                            exception     = ExtractNPopulateValue(commandLineArgObject, memberInfo, commandLineArgParser);

                            if (isUsageAvail)
                            {
                                if (exception != null)
                                {
                                    break;
                                }
                            }
                        }
                    }
                }

                if (commandLineArgObject != null)
                {
                    if (exception != null)
                    {
                        if (!commandLineArgObject.RaiseCommandLineArgObjectLoadError(commandLineArgs, exception))
                        {
                            if (isUsageAvail)
                            {
                                if (exception is ChoCommandLineArgException)
                                {
                                    throw exception;
                                }
                                else
                                {
                                    throw new ChoCommandLineArgException("Found exception while loading `{2}` command line argument. {0}{0}{1}".FormatString(
                                                                             Environment.NewLine, exception.Message, cmdLineSwitch), commandLineArgObject.GetUsage(), exception);
                                }
                            }
                        }
                    }
                    else
                    {
                        commandLineArgObject.RaiseAfterCommandLineArgObjectLoaded(commandLineArgs);
                    }
                }
            }
        }