private bool AssignToFallbackOrDefaultValues(ref bool isDirty)
        {
            bool   isModfied     = false;
            object defaultValue  = null;
            object fallbackValue = null;

            MemberInfo[] memberInfos = ChoTypeMembersCache.GetAllMemberInfos(ConfigObject.GetType());
            if (memberInfos != null && memberInfos.Length > 0)
            {
                //Set member values
                string name;
                ChoPropertyInfoAttribute memberInfoAttribute = null;
                foreach (MemberInfo memberInfo in memberInfos)
                {
                    if (memberInfo.GetCustomAttribute <ChoIgnorePropertyAttribute>() != null)
                    {
                        continue;
                    }

                    name = ChoType.GetMemberName(memberInfo);
                    memberInfoAttribute = (ChoPropertyInfoAttribute)ChoType.GetMemberAttribute(memberInfo, typeof(ChoPropertyInfoAttribute));
                    //if (memberInfoAttribute == null) continue;

                    defaultValue  = null;
                    fallbackValue = null;

                    bool isDefaultValueSpecified = ChoConfigurationMetaDataManager.TryConfigDefaultValue(this, name, memberInfoAttribute, out defaultValue);
                    ChoConfigurationMetaDataManager.TryConfigFallbackValue(this, name, memberInfoAttribute, out fallbackValue);

                    if (fallbackValue == null)
                    {
                        if (!isDefaultValueSpecified)
                        {
                            continue;
                        }
                    }

                    bool hasError = !ChoConfigurationObjectErrorManagerService.GetObjectMemberError(ConfigObject, memberInfo.Name).IsNullOrEmpty();
                    if (hasError)
                    {
                        isModfied = true;
                        if (_firstTime)
                        {
                            AssignToFallbackOrDefaultValue(defaultValue, fallbackValue, memberInfo);
                        }
                    }
                }
            }
            return(isModfied);
        }
        private void Reset()
        {
            if (ConfigObject == null)
            {
                return;
            }

            ChoConfigurationObjectErrorManagerService.ResetObjectErrors(ConfigObject);

            //MemberInfo[] memberInfos = ChoType.GetMembers(ConfigObject.GetType(), typeof(ChoConfigurationPropertyAttribute));
            MemberInfo[] memberInfos = ChoTypeMembersCache.GetAllMemberInfos(ConfigObject.GetType());
            if (memberInfos != null && memberInfos.Length > 0)
            {
                ChoPropertyInfoAttribute memberInfoAttribute = null;
                foreach (MemberInfo memberInfo in memberInfos)
                {
                    memberInfoAttribute = (ChoPropertyInfoAttribute)ChoType.GetMemberAttribute(memberInfo, typeof(ChoPropertyInfoAttribute));
                    string name                    = ChoType.GetMemberName(memberInfo);
                    object defaultValue            = null;
                    bool   isDefaultValueSpecified = ChoConfigurationMetaDataManager.TryConfigDefaultValue(this, name, memberInfoAttribute, out defaultValue);
                    if (memberInfoAttribute == null || !isDefaultValueSpecified)
                    {
                        continue;
                    }

                    try
                    {
                        //object newConvertedValue = memberInfoAttribute.DefaultValue;
                        object newConvertedValue = ChoConvert.ConvertFrom(ConfigObject, defaultValue, ChoType.GetMemberType(memberInfo),
                                                                          ChoTypeDescriptor.GetTypeConverters(memberInfo), ChoTypeDescriptor.GetTypeConverterParams(memberInfo));
                        SetConfigPropertyValue(newConvertedValue, memberInfo);
                        //ChoType.SetMemberValue(ConfigObject, memberInfo, newConvertedValue);
                    }
                    catch (Exception innerEx)
                    {
                        ChoConfigurationObjectErrorManagerService.SetObjectMemberError(ConfigObject, memberInfo.Name, String.Format("Failed to assign `{0}` default value. {1}", ChoString.ToString(defaultValue), innerEx.Message));
                    }
                }
            }
        }
        private bool SetNThrowException(Exception ex, ref bool isModified)
        {
            bool handled = false;

            if (ex == null)
            {
                return(handled);
            }

            if (ConfigObject != null && ConfigObject is ChoConfigurableObject)
            {
                handled = ((ChoConfigurableObject)ConfigObject).RaiseConfigurationObjectLoadError(ex, ref isModified);
            }

            if (!handled)
            {
                if (ConfigObject != null && ConfigObject is IChoExceptionHandledObject)
                {
                    handled = ((IChoExceptionHandledObject)ConfigObject).HandleException(ex, ref isModified);
                }
            }

            //ChoConfigurationErrorsProfiler.Me.AppendLine(ChoApplicationException.ToString(ex));

            if (!Silent)
            {
                throw new ChoConfigurationConstructionException("Failed to build configuration element.", ex);
            }
            else
            {
                //if (_configSection is IChoCustomConfigSection)
                //    ChoConfigurationObjectErrorManagerService.SetObjectError(_configSection.ConfigData, ChoApplicationException.ToString(ex));
                //else
                ChoConfigurationObjectErrorManagerService.SetObjectError(ConfigObject, ChoApplicationException.ToString(ex));
            }
            return(handled);
        }
        private bool ExtractNPopulateValues(ref bool hasErrors, ref bool isDirty)
        {
            bool   isModfied     = false;
            object oldValue      = null;
            object newValue      = null;
            object origValue     = null;
            object defaultValue  = null;
            object fallbackValue = null;

            bool isConfigmemberDefined = false;

            //MemberInfo[] memberInfos = ChoType.GetMembers(ConfigObject.GetType(), typeof(ChoConfigurationPropertyAttribute));
            MemberInfo[] memberInfos = ChoTypeMembersCache.GetAllMemberInfos(ConfigObject.GetType());
            if (memberInfos != null && memberInfos.Length > 0)
            {
                //Set member values
                string name;
                ChoPropertyInfoAttribute memberInfoAttribute = null;
                foreach (MemberInfo memberInfo in memberInfos)
                {
                    if (memberInfo.GetCustomAttribute <ChoIgnorePropertyAttribute>() != null)
                    {
                        continue;
                    }

                    memberInfoAttribute = (ChoPropertyInfoAttribute)ChoType.GetMemberAttribute(memberInfo, typeof(ChoPropertyInfoAttribute));

                    //if (memberInfoAttribute == null) continue;

                    oldValue      = null;
                    newValue      = null;
                    origValue     = null;
                    defaultValue  = null;
                    fallbackValue = null;

                    name = ChoType.GetMemberName(memberInfo);
                    isConfigmemberDefined = ConfigSection.HasConfigMemberDefined(name);

                    oldValue = ChoType.GetMemberValue(ConfigObject, memberInfo.Name);

                    object configFallbackValue     = null;
                    object configDefaultValue      = null;
                    bool   isDefaultValueSpecified = ChoConfigurationMetaDataManager.TryConfigDefaultValue(this, name, memberInfoAttribute, out configDefaultValue);
                    ChoConfigurationMetaDataManager.TryConfigFallbackValue(this, name, memberInfoAttribute, out configFallbackValue);

                    if (configFallbackValue == null)
                    {
                        if (isDefaultValueSpecified)
                        {
                            defaultValue = origValue = newValue = configDefaultValue;
                        }
                    }
                    else
                    {
                        fallbackValue = origValue = newValue = configFallbackValue;
                    }

                    if (!isConfigmemberDefined)
                    {
                        if (!isDirty)
                        {
                            isDirty = memberInfoAttribute != null && memberInfoAttribute.Persistable ? true : false;
                        }
                    }
                    else
                    {
                        origValue = newValue = ConfigSection[name];
                    }

                    try
                    {
                        object newConvertedValue = ChoConvert.ConvertFrom(ConfigObject, newValue, ChoType.GetMemberType(memberInfo),
                                                                          ChoTypeDescriptor.GetTypeConverters(memberInfo), ChoTypeDescriptor.GetTypeConverterParams(memberInfo));
                        newValue = newConvertedValue;
                    }
                    catch { }

                    ChoConfigurableObject configObject = ConfigObject as ChoConfigurableObject;
                    if (configObject != null)
                    {
                        if (!configObject.IsMemeberValueEqualInternal(memberInfo, oldValue, newValue))
                        {
                            if (!configObject.RaiseBeforeConfigurationObjectMemberLoaded(memberInfo.Name, name, origValue, ref newValue))
                            {
                                try
                                {
                                    //ChoType.SetMemberValue(ConfigObject, memberInfo.Name, newValue != null ? ChoConvert.ConvertFrom(ConfigObject, newValue,
                                    //    ChoType.GetMemberType(memberInfo), ChoTypeConvertersCache.GetTypeConverters(memberInfo)) : null);
                                    SetConfigPropertyValue(newValue, memberInfo);
                                    if (!_firstTime)
                                    {
                                        isModfied = true;
                                    }

                                    configObject.RaiseAfterConfigurationObjectMemberLoaded(memberInfo.Name, name, newValue);
                                    ChoConfigurationObjectErrorManagerService.ResetObjectMemberError(ConfigObject, memberInfo.Name);
                                }
                                catch (Exception innerEx)
                                {
                                    if (!configObject.RaiseConfigurationObjectMemberLoadError(memberInfo.Name, name, origValue, innerEx))
                                    {
                                        if (Silent)
                                        {
                                            if (_firstTime)
                                            {
                                                AssignToFallbackOrDefaultValue(defaultValue, fallbackValue, memberInfo);
                                            }

                                            ChoConfigurationObjectErrorManagerService.SetObjectMemberError(ConfigObject, memberInfo.Name, String.Format(Resources.ConfigConstructMsg, ChoString.ToString(origValue), innerEx.Message));
                                        }
                                        else
                                        {
                                            throw new ChoConfigurationConstructionException(String.Format(Resources.ConfigConstructExceptionMsg, ChoString.ToString(origValue), ConfigObject.GetType().FullName,
                                                                                                          memberInfo.Name), innerEx);
                                        }
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        try
                        {
                            //ChoType.SetMemberValue(ConfigObject, memberInfo.Name, newValue != null ? ChoConvert.ConvertFrom(ConfigObject, newValue,
                            //    ChoType.GetMemberType(memberInfo), ChoTypeConvertersCache.GetTypeConverters(memberInfo)) : null);
                            SetConfigPropertyValue(newValue, memberInfo);
                            if (!_firstTime)
                            {
                                isModfied = true;
                            }
                            ChoConfigurationObjectErrorManagerService.ResetObjectMemberError(ConfigObject, memberInfo.Name);
                        }
                        catch (Exception innerEx)
                        {
                            if (Silent)
                            {
                                if (_firstTime)
                                {
                                    AssignToFallbackOrDefaultValue(defaultValue, fallbackValue, memberInfo);
                                }
                                ChoConfigurationObjectErrorManagerService.SetObjectMemberError(ConfigObject, memberInfo.Name, String.Format(Resources.ConfigConstructMsg, ChoString.ToString(origValue), innerEx.Message));
                            }
                            else
                            {
                                throw new ChoConfigurationConstructionException(String.Format(Resources.ConfigConstructExceptionMsg, ChoString.ToString(origValue), ConfigObject.GetType().FullName,
                                                                                              memberInfo.Name), innerEx);
                            }
                        }
                    }
                }
            }

            return(isModfied);
        }
        internal void Refresh(bool refresh)
        {
            if (_inLoadingProcess)
            {
                return;
            }

            lock (SyncRoot)
            {
                if (ConfigObject is IChoConfigurationParametersOverridable)
                {
                    ((IChoConfigurationParametersOverridable)ConfigObject).OverrideParameters(this);
                }

                _modifiedStateObject.ResetModified();

                bool isDirty        = false;
                bool errorHandled   = false;
                bool canTraceOutput = true;
                bool hasErrors      = false;
                this[ChoConfigurationConstants.FORCE_PERSIST] = false;

                _inLoadingProcess = true;

                ChoConfigSection prevConfigSection = ConfigSection;

                if (ConfigSection != null)
                {
                    ConfigSection.StopWatching();
                }

                try
                {
                    if (ConfigObject != null)
                    {
                        //ChoConfigurationObjectErrorManagerService.ResetObjectErrors(ConfigObject);

                        if (ConfigObject is ChoInterceptableObject)
                        {
                            ChoInterceptableObject interceptableObject = ConfigObject as ChoInterceptableObject;
                            interceptableObject.SetDirty(false);
                            interceptableObject.SetSilent(false);
                            interceptableObject.SetInitialized(false);
                            interceptableObject.IsConfigObjectSilent = Silent;
                        }
                    }

                    GetConfig(ConfigObjectType, refresh);
                }
                catch (ConfigurationErrorsException configErrorsEx)
                {
                    bool isModified = false;
                    errorHandled = SetNThrowException(configErrorsEx, ref isModified);
                    _modifiedStateObject.SetModified(isModified);
                }
                catch (TypeInitializationException typeEx)
                {
                    bool isModified = false;
                    errorHandled = SetNThrowException(typeEx, ref isModified);
                    _modifiedStateObject.SetModified(isModified);
                }
                catch (ChoFatalApplicationException)
                {
                    canTraceOutput = false;
                    throw;
                }
                catch (Exception ex)
                {
                    bool isModified = false;
                    errorHandled = SetNThrowException(ex, ref isModified);
                    _modifiedStateObject.SetModified(isModified);
                }
                finally
                {
                    if (ConfigSection != null && ConfigObject is ChoConfigurableObject)
                    {
                        //Call Notify Property Changed for all default values
                        CallNotifyPropertyChangedForAllDefaultableMembers();
                        ConfigSection.Initialize();
                    }

                    if (ConfigSection != null && ConfigSection.ConfigLoadException != null)
                    {
                        bool isModified = false;
                        errorHandled = SetNThrowException(ConfigSection.ConfigLoadException, ref isModified);
                        _modifiedStateObject.SetModified(isModified);
                    }

                    ////Update configuration meta data information
                    //if (ConfigSection != null && ConfigSection.MetaDataInfo != null)
                    //    ApplyConfigMetaData(ConfigSection.MetaDataInfo);

                    //Print the output to file
                    if (canTraceOutput)
                    {
                        //Set default trace output file name
                        if (LogFileName.IsNullOrEmpty())
                        {
                            LogFileName = ChoPath.AddExtension(ConfigObject.GetType().FullName, ChoReservedFileExt.Log);
                        }

                        //if (ConfigSection is IChoCustomConfigSection)
                        //{
                        //    if (ConfigSection.ConfigData != null)
                        //        ConfigSection.ConfigObject = ConfigSection.ConfigData as ChoConfigurableObject;
                        //    ChoObjectManagementFactory.SetInstance(ConfigObject);
                        //}

                        if ((ConfigSection == null || ConfigSection.ConfigData == null) && !_defaultable /*&& !_persistable*/)
                        {
                            throw new ChoConfigurationConstructionException(String.Format("Failed to load '[{0}]' configuration section.", this._configElementPath));
                        }
                        else
                        {
                            if (prevConfigSection != null)
                            {
                                prevConfigSection.Dispose();
                            }

                            if (ConfigObject is ChoConfigurableObject)
                            {
                                ((ChoConfigurableObject)ConfigObject).SetReadOnly(true);
                            }

                            bool hasConfigSectionDefined = ConfigSection != null ? ConfigSection.HasConfigSectionDefined : false;

                            try
                            {
                                if (!errorHandled)
                                {
                                    if (!(ConfigSection is IChoCustomConfigSection))
                                    {
                                        if (hasConfigSectionDefined)
                                        {
                                            _modifiedStateObject.SetModified(ExtractNPopulateValues(ref hasErrors, ref isDirty));
                                        }
                                        else
                                        {
                                            _modifiedStateObject.SetModified(AssignToFallbackOrDefaultValues(ref isDirty));
                                        }
                                    }
                                    else
                                    {
                                        if (hasConfigSectionDefined)
                                        {
                                            //isModfied = true;
                                            if (ConfigSection == null)
                                            {
                                                _modifiedStateObject.SetModified(AssignToFallbackOrDefaultValues(ref isDirty));
                                            }
                                            else if (!ChoObject.Equals(ConfigSection, prevConfigSection))
                                            {
                                                _modifiedStateObject.SetModified(true);
                                            }
                                            else
                                            {
                                                _modifiedStateObject.SetModified(AssignToFallbackOrDefaultValues(ref isDirty));
                                            }
                                        }
                                        else
                                        {
                                            _modifiedStateObject.SetModified(AssignToFallbackOrDefaultValues(ref isDirty));
                                        }
                                    }
                                }

                                if (!hasErrors)
                                {
                                    hasErrors = ChoConfigurationObjectErrorManagerService.ContainsObjectError(ConfigObject);
                                }

                                ChoObjectInitializer.Initialize(ConfigObject, false, ConfigSection != null ? ConfigObject : null);

                                SetWatcher(false);

                                if (ConfigObject is ChoInterceptableObject)
                                {
                                    ChoInterceptableObject interceptableObject = ConfigObject as ChoInterceptableObject;
                                    if (interceptableObject.Dirty)
                                    {
                                        isDirty = interceptableObject.Dirty;
                                    }
                                    //if (interceptableObject.IsModified)
                                    //{
                                    //    isModfied = interceptableObject.IsModified;
                                    //}
                                    interceptableObject.SetDirty(false);
                                    //interceptableObject.SetSilent(false);
                                    interceptableObject.SetInitialized(true);
                                }

                                if (ConfigObject is ChoConfigurableObject)
                                {
                                    bool invokeObjectLoaded = /* isDirty || */ _firstTime || _modifiedStateObject.IsModified;
                                    if (invokeObjectLoaded || hasErrors)
                                    {
                                        TraceOutput(false);
                                        if (invokeObjectLoaded)
                                        {
                                            ((ChoConfigurableObject)ConfigObject).RaiseAfterConfigurationObjectLoaded();
                                        }
                                    }

                                    //if (isDirty)
                                    //{
                                    //    TraceOutput(false);
                                    //    ((ChoConfigurableObject)ConfigObject).OnAfterConfigurationObjectLoaded();
                                    //}
                                    //else if (hasErrors)
                                    //    TraceOutput(false);
                                }
                                else
                                {
                                    TraceOutput(false);
                                }

                                if (!isDirty && ConfigSection != null)
                                {
                                    isDirty = ConfigSection.IsMetaDataDefinitionChanged;
                                }
                            }
                            finally
                            {
                                if (prevConfigSection != null)
                                {
                                    prevConfigSection.Dispose();
                                    prevConfigSection = null;
                                }

                                if (ConfigObject is ChoConfigurableObject)
                                {
                                    ((ChoConfigurableObject)ConfigObject).SetReadOnly(false);
                                }

                                if (!hasConfigSectionDefined || isDirty || hasErrors)
                                {
                                    if (_defaultable)
                                    {
                                        Persist(false, null);
                                    }
                                }
                                else if ((bool)this[ChoConfigurationConstants.FORCE_PERSIST])
                                {
                                    Persist(false, null);
                                }

                                _inLoadingProcess = false;
                                if (_watchChange && ConfigSection != null)
                                {
                                    ConfigSection.StartWatching();
                                }

                                ChoConfigurationObjectErrorManagerService.ResetObjectErrors(ConfigObject);
                                _firstTime = false;
                            }
                        }
                    }
                }
            }
        }