//
// 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;
}