System.Configuration.BaseConfigurationRecord.GetSectionRecursive C# (CSharp) Метод

GetSectionRecursive() приватный Метод

private GetSectionRecursive ( string configKey, bool getLkg, bool checkPermission, bool getRuntimeObject, bool requestIsHere, object &result, object &resultRuntimeObject ) : void
configKey string
getLkg bool
checkPermission bool
getRuntimeObject bool
requestIsHere bool
result object
resultRuntimeObject object
Результат void
        private void GetSectionRecursive(
                string configKey, bool getLkg, bool checkPermission, bool getRuntimeObject, bool requestIsHere, 
                out object result, out object resultRuntimeObject) {

            result = null;
            resultRuntimeObject = null;

#if DBG
            Debug.Assert(requestIsHere || !checkPermission, "requestIsHere || !checkPermission");
            if (getLkg) {
                Debug.Assert(getRuntimeObject == true, "getRuntimeObject == true");
                Debug.Assert(requestIsHere == true, "requestIsHere == true");
            }
#endif

            //
            // Store results in temporary variables, because we don't want to return
            // results if an exception is thrown by CheckPermissionAllowed.
            //
            object tmpResult = null;
            object tmpResultRuntimeObject = null;
            bool requirePermission = true;
            bool isResultTrustedWithoutAptca = true;

            // Throw errors from initial parse, if any.
            if (!getLkg) {
                ThrowIfInitErrors();
            }

            //
            // check for a cached result
            //
            bool hasResult = false;
            SectionRecord sectionRecord = GetSectionRecord(configKey, getLkg);
            if (sectionRecord != null && sectionRecord.HasResult) {
                // Results should never be stored if the section has errors.
                Debug.Assert(!sectionRecord.HasErrors, "!sectionRecord.HasErrors");

                // Create the runtime object if requested and does not yet exist.
                if (getRuntimeObject && !sectionRecord.HasResultRuntimeObject) {
                    try {
                        sectionRecord.ResultRuntimeObject = GetRuntimeObject(sectionRecord.Result);
                    }
                    catch {
                        //
                        // Ignore the error if we are attempting to retreive
                        // the last known good configuration.
                        //
                        if (!getLkg) {
                            throw;
                        }
                    }
                }

                // Get the cached result.
                if (!getRuntimeObject || sectionRecord.HasResultRuntimeObject) {
                    requirePermission = sectionRecord.RequirePermission;
                    isResultTrustedWithoutAptca = sectionRecord.IsResultTrustedWithoutAptca;
                    tmpResult = sectionRecord.Result;
                    if (getRuntimeObject) {
                        tmpResultRuntimeObject = sectionRecord.ResultRuntimeObject;
                    }

                    hasResult = true;
                }
            }

            //
            // If there is no cached result, get the parent's section,
            // then merge it with our own input if we have any.
            //
            if (!hasResult) {
                FactoryRecord factoryRecord = null;
                bool hasInput = (sectionRecord != null && sectionRecord.HasInput);

                //
                // We want to cache results in a section record if:
                // - The request is made at this level, and so is likely to be
                //   made here again.
                // OR
                // - The section has input, in which case we want to 
                //   avoid evaluating the same input multiple times.
                //
                bool cacheResults = (requestIsHere || hasInput);

                bool isRootDeclaration;
                try {
                    //
                    // We need to get a factory record to:
                    // - Check whether the caller has permission to access a section.
                    // - Determine if this is the root declaration of a config section,
                    //   and thus the termination point for recursion.
                    // - Get a factory that can create a configuration section.
                    //
                    // Since most factories will be declared in machine.config and not in
                    // child config files, we do not optimize for checking whether a
                    // factory record is the root declaration, as the calculation at
                    // machine.config is trivial.
                    //
                    // It WILL be common in web scenarios for there to be 
                    // deep hierarchies of config files, most of which have
                    // sparse input. Therefore we do not want to retreive a 
                    // factory record if it is not necessary to do so, as 
                    // it would always lead to an order N-squared operation, 
                    // where N is the depth of the config hierarchy.
                    //
                    // We can skip the reteival of a factory record if:
                    // - This is the recursive call to GetSectionRecursive,
                    // AND
                    // - There is no section input at this level,
                    // AND
                    // - No factory is declared at this level.
                    //
                    // In this case, we'll simply continue the recursion to our parent.
                    //
                    if (requestIsHere) {
                        //
                        // Ensure that we have a valid factory record and a valid factory
                        // for creating sections when a request for a section is first
                        // made.
                        //
                        factoryRecord = FindAndEnsureFactoryRecord(configKey, out isRootDeclaration);

                        //
                        // If initialization is delayed, complete initialization if:
                        //  - We can't find the requested factory, and it therefore 
                        //    may be in the file we haven't yet read,
                        //  OR
                        //  - The definition of that factory is allowed at 
                        //    levels of the config hierarchy that have not
                        //    been initialized.
                        //
                        // This works for client config scenarios because the default
                        // for AllowExeDefinition is MachineToApplication. It would not
                        // be useful for Web scenarios, as most sections can be requested
                        // Everywhere.
                        //
                        // Note that configuration errors that may be present in the
                        // file where intialization is delayed will be ignored, and
                        // thus the order in which configuration sections are requested
                        // will affect results. This is considered OK as it is very
                        // expensive to determine configuration paths to 
                        // client user configuration files, which aren't needed by
                        // most applications.
                        //
                        if (   IsInitDelayed
                            && (   factoryRecord == null
                                || _initDelayedRoot.IsDefinitionAllowed(factoryRecord.AllowDefinition, factoryRecord.AllowExeDefinition))) {

                            //
                            // We are going to remove this record, so get any data we need
                            // before the reference to 'this' becomes invalid.
                            //
                            string configPath = this._configPath;
                            InternalConfigRoot configRoot = this._configRoot;

                            // Tell the host to no longer permit delayed initialization.
                            Host.RequireCompleteInit(_initDelayedRoot);

                            // Removed config at the root of where initialization is delayed.
                            _initDelayedRoot.Remove();

                            // Get the config record for this config path
                            BaseConfigurationRecord newRecord = (BaseConfigurationRecord) configRoot.GetConfigRecord(configPath);

                            // Repeat the call to GetSectionRecursive
                            newRecord.GetSectionRecursive(
                                configKey, getLkg, checkPermission, 
                                getRuntimeObject, requestIsHere,
                                out result, out resultRuntimeObject);

                            // Return and make no more references to this record.
                            return;
                        }

                        //
                        // For compatibility with previous versions, 
                        // return null if the section is not found
                        // or is a group.
                        //
                        if (factoryRecord == null || factoryRecord.IsGroup) {
                            return;
                        }

                        //
                        // Use the factory record's copy of the configKey,
                        // so that we don't store more than one instance
                        // of the same configKey.
                        //
                        configKey = factoryRecord.ConfigKey;
                    }
                    else if (hasInput) {
                        //
                        // We'll need a factory to evaluate the input.
                        //
                        factoryRecord = FindAndEnsureFactoryRecord(configKey, out isRootDeclaration);
                        Debug.Assert(factoryRecord != null, "factoryRecord != null");
                    }
                    else {
                        //
                        // We don't need a factory record unless this is the root declaration.
                        // We know it is not the root declaration if there is no factory 
                        // declared here. This is important to avoid a walk up the config
                        // hierachy when there is no input in this record.
                        //
                        factoryRecord = GetFactoryRecord(configKey, false);
                        if (factoryRecord == null) {
                            isRootDeclaration = false;
                        }
                        else {
                            factoryRecord = FindAndEnsureFactoryRecord(configKey, out isRootDeclaration);
                            Debug.Assert(factoryRecord != null, "factoryRecord != null");
                        }
                    }

                    // We need a factory record to check permission.
                    Debug.Assert(!checkPermission || factoryRecord != null, "!checkPermission || factoryRecord != null");

                    //
                    // If this is the root declaration, then we always want to cache
                    // the result, in order to prevent the section default from being 
                    // created multiple times.
                    //
                    if (isRootDeclaration) {
                        cacheResults = true;
                    }

                    //
                    // We'll need a section record to cache results,
                    // and maybe to use in creating the section default.
                    //
                    if (sectionRecord == null && cacheResults) {
                        sectionRecord = EnsureSectionRecord(configKey, true);
                    }

                    //
                    // Retrieve the parent's runtime object if the runtimeObject
                    // is requested, and we are not going to merge that input
                    // with input in this section.
                    //
                    bool getParentRuntimeObject = (getRuntimeObject && !hasInput);

                    object parentResult = null;
                    object parentResultRuntimeObject = null;
                    if (isRootDeclaration) {
                        //
                        // Create the default section.
                        //
                        // Use the existing section record to create it if there is no input,
                        // so that the cached result is attached to the correct record.
                        //
                        SectionRecord sectionRecordForDefault = (hasInput) ? null : sectionRecord;
                        CreateSectionDefault(configKey, getParentRuntimeObject, factoryRecord, sectionRecordForDefault, 
                                out parentResult, out parentResultRuntimeObject);
                    }
                    else {
                        //
                        // Get the parent section.
                        //
                        _parent.GetSectionRecursive(
                                configKey, false /* getLkg */, false /* checkPermission */, 
                                getParentRuntimeObject, false /* requestIsHere */,
                                out parentResult, out parentResultRuntimeObject);
                    }

                    if (hasInput) {
                        // 
                        // Evaluate the input.
                        //
                        // If Evaluate() encounters an error, it may not throw an exception
                        // when getLkg == true.
                        //
                        // The complete success of the evaluation is determined by the return value.
                        //
                        bool success = Evaluate(factoryRecord, sectionRecord, parentResult, getLkg, getRuntimeObject, 
                                out tmpResult, out tmpResultRuntimeObject);

                        Debug.Assert(success || getLkg, "success || getLkg");

                        if (!success) {
                            Debug.Assert(getLkg == true, "getLkg == true");
                            // Do not cache partial results if getLkg was specified.
                            cacheResults = false;
                        }
                    }
                    else {
                        //
                        // If we are going to cache results here, we will need
                        // to create a copy in the case of MgmtConfigurationRecord - 
                        // otherwise we could inadvertently return the parent to the user,
                        // which could then be modified.
                        //
                        if (sectionRecord != null) {
                            tmpResult = UseParentResult(configKey, parentResult, sectionRecord);
                            if (getRuntimeObject) {
                                //
                                // If the parent result is the same as the parent runtime object,
                                // then use the same copy of the parent result for our own runtime object.
                                //
                                if (object.ReferenceEquals(parentResult, parentResultRuntimeObject)) {
                                    tmpResultRuntimeObject = tmpResult;
                                }
                                else {
                                    tmpResultRuntimeObject = UseParentResult(configKey, parentResultRuntimeObject, sectionRecord);
                                }
                            }
                        }
                        else {
                            Debug.Assert(!requestIsHere, "!requestIsHere");

                            //
                            // We don't need to make a copy if we are not storing
                            // the result, and thus not returning the result to the 
                            // caller of GetSection.
                            //
                            tmpResult = parentResult;
                            tmpResultRuntimeObject = parentResultRuntimeObject;
                        }
                    }

                    //
                    // Determine which permissions are required of the caller.
                    //
                    if (cacheResults || checkPermission) {
                        requirePermission = factoryRecord.RequirePermission;
                        isResultTrustedWithoutAptca = factoryRecord.IsFactoryTrustedWithoutAptca;

                        //
                        // Cache the results.
                        //
                        if (cacheResults) {
                            if (sectionRecord == null) {
                                sectionRecord = EnsureSectionRecord(configKey, true);
                            }

                            sectionRecord.Result = tmpResult;
                            if (getRuntimeObject) {
                                sectionRecord.ResultRuntimeObject = tmpResultRuntimeObject;
                            }

                            sectionRecord.RequirePermission = requirePermission;
                            sectionRecord.IsResultTrustedWithoutAptca = isResultTrustedWithoutAptca;
                        }
                    }

                    hasResult = true;
                }
                catch {
                    //
                    // Ignore the error if we are attempting to retreive
                    // the last known good configuration.
                    //
                    if (!getLkg) {
                        throw;
                    }
                }

                //
                // If we don't have a result, ask our parent for its
                // last known good result.
                //
                if (!hasResult) {
                    Debug.Assert(getLkg == true, "getLkg == true");

                    _parent.GetSectionRecursive(
                        configKey, true /* getLkg */, checkPermission, 
                        true /* getRuntimeObject */, true /* requestIsHere */,
                        out result, out resultRuntimeObject);

                    return;
                }
            }

            //
            // Check if permission to access the section is allowed.
            //
            if (checkPermission) {
                CheckPermissionAllowed(configKey, requirePermission, isResultTrustedWithoutAptca);
            }

            //
            // Return the results.
            //
            result = tmpResult;
            if (getRuntimeObject) {
                resultRuntimeObject = tmpResultRuntimeObject;
            }
        }
BaseConfigurationRecord