// // 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. // private bool Evaluate( FactoryRecord factoryRecord, SectionRecord sectionRecord, object parentResult, bool getLkg, bool getRuntimeObject, out object result, out object resultRuntimeObject) { result = null; resultRuntimeObject = null; // // Store results in temporary variables, because we don't want to return // results if an exception is thrown. // object tmpResult = null; object tmpResultRuntimeObject = null; // Factory record should be error-free. Debug.Assert(!factoryRecord.HasErrors, "!factoryRecord.HasErrors"); // We should have some input Debug.Assert(sectionRecord.HasInput, "sectionRecord.HasInput"); // // Grab inputs before checking result, // as inputs may be cleared once the result is set. // List<SectionInput> locationInputs = sectionRecord.LocationInputs; SectionInput fileInput = sectionRecord.FileInput; // // Now that we have our inputs, lets check if there // is a result, because if there is, our inputs might // have been invalidated. // bool success = false; if (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 it 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) { tmpResult = sectionRecord.Result; if (getRuntimeObject) { tmpResultRuntimeObject = sectionRecord.ResultRuntimeObject; } success = true; } } if (!success) { Exception savedException = null; try { string configKey = factoryRecord.ConfigKey; string [] keys = configKey.Split(ConfigPathSeparatorParams); object currentResult = parentResult; // // Evaluate location inputs // if (locationInputs != null) { foreach (SectionInput locationInput in locationInputs) { if (!locationInput.HasResult) { locationInput.ThrowOnErrors(); bool isTrusted = Host.IsTrustedConfigPath(locationInput.SectionXmlInfo.DefinitionConfigPath); locationInput.Result = EvaluateOne(keys, locationInput, isTrusted, factoryRecord, sectionRecord, currentResult); } currentResult = locationInput.Result; } } // // Evaluate file input // if (fileInput != null) { if (!fileInput.HasResult) { fileInput.ThrowOnErrors(); bool isTrusted = _flags[IsTrusted]; fileInput.Result = EvaluateOne(keys, fileInput, isTrusted, factoryRecord, sectionRecord, currentResult); } currentResult = fileInput.Result; } else { // // The section needs its own copy of the result that is distinct // from its location parent result. // Debug.Assert(locationInputs != null, "locationInputs != null"); currentResult = UseParentResult(configKey, currentResult, sectionRecord); } if (getRuntimeObject) { tmpResultRuntimeObject = GetRuntimeObject(currentResult); } tmpResult = currentResult; success = true; } catch (Exception e) { // // Catch the exception if LKG is requested and we have // location input to fall back on. // if (getLkg && locationInputs != null) { savedException = e; } else { throw; } } // // If getLkg, then return a result from the last valid location input. // if (!success) { Debug.Assert(getLkg == true, "getLkg == true"); int i = locationInputs.Count; while (--i >= 0) { SectionInput locationInput = locationInputs[i]; if (locationInput.HasResult) { if (getRuntimeObject && !locationInput.HasResultRuntimeObject) { try { locationInput.ResultRuntimeObject = GetRuntimeObject(locationInput.Result); } catch { } } if (!getRuntimeObject || locationInput.HasResultRuntimeObject) { tmpResult = locationInput.Result; if (getRuntimeObject) { tmpResultRuntimeObject = locationInput.ResultRuntimeObject; } break; } } } if (i < 0) { throw savedException; } } } // // If evaluation was successful, we can remove any saved rawXml. // if (success && !_flags[SupportsKeepInputs]) { sectionRecord.ClearRawXml(); } result = tmpResult; if (getRuntimeObject) { resultRuntimeObject = tmpResultRuntimeObject; } return success; }