/// <summary> /// Loads the contract type details from the given config node. /// </summary> /// <param name="configNode">The config node to load from.</param> /// <returns>Whether the load was successful.</returns> public bool Load(ConfigNode configNode) { LoggingUtil.LogLevel origLogLevel = LoggingUtil.logLevel; try { // Logging on LoggingUtil.CaptureLog = true; ConfigNodeUtil.SetCurrentDataNode(null); // Load values that are immediately required bool valid = true; valid &= ConfigNodeUtil.ParseValue<ContractGroup>(configNode, "group", x => group = x, this, (ContractGroup)null); // Set up the data node dataNode = new DataNode(configNode.GetValue("name"), group != null ? group.dataNode : null, this); ConfigNodeUtil.SetCurrentDataNode(dataNode); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "name", x => name = x, this); // Try to turn on trace mode valid &= ConfigNodeUtil.ParseValue<bool>(configNode, "trace", x => trace = x, this, false); if (trace) { LoggingUtil.logLevel = LoggingUtil.LogLevel.VERBOSE; LoggingUtil.LogWarning(this, "Tracing enabled for contract type " + name); } // Load contract text details valid &= ConfigNodeUtil.ParseValue<string>(configNode, "title", x => title = x, this); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "tag", x => tag = x, this, ""); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "description", x => description = x, this, (string)null); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "topic", x => topic = x, this, ""); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "subject", x => subject = x, this, ""); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "motivation", x => motivation = x, this, ""); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "notes", x => notes = x, this, (string)null); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "synopsis", x => synopsis = x, this); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "completedMessage", x => completedMessage = x, this); // Load optional attributes valid &= ConfigNodeUtil.ParseValue<Agent>(configNode, "agent", x => agent = x, this, (Agent)null); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "minExpiry", x => minExpiry = x, this, 1.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "maxExpiry", x => maxExpiry = x, this, 7.0f, x => Validation.GE(x, minExpiry)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "deadline", x => deadline = x, this, 0.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<bool>(configNode, "cancellable", x => cancellable = x, this, true); valid &= ConfigNodeUtil.ParseValue<bool>(configNode, "declinable", x => declinable = x, this, true); valid &= ConfigNodeUtil.ParseValue<bool>(configNode, "autoAccept", x => autoAccept = x, this, false); valid &= ConfigNodeUtil.ParseValue<List<Contract.ContractPrestige>>(configNode, "prestige", x => prestige = x, this, new List<Contract.ContractPrestige>()); valid &= ConfigNodeUtil.ParseValue<CelestialBody>(configNode, "targetBody", x => targetBody = x, this, (CelestialBody)null); valid &= ConfigNodeUtil.ParseValue<int>(configNode, "maxCompletions", x => maxCompletions = x, this, 0, x => Validation.GE(x, 0)); valid &= ConfigNodeUtil.ParseValue<int>(configNode, "maxSimultaneous", x => maxSimultaneous = x, this, 0, x => Validation.GE(x, 0)); // Load rewards valid &= ConfigNodeUtil.ParseValue<float>(configNode, "rewardFunds", x => rewardFunds = x, this, 0.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "rewardReputation", x => rewardReputation = x, this, 0.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "rewardScience", x => rewardScience = x, this, 0.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "failureFunds", x => failureFunds = x, this, 0.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "failureReputation", x => failureReputation = x, this, 0.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "advanceFunds", x => advanceFunds = x, this, 0.0f, x => Validation.GE(x, 0.0f)); // Load other values valid &= ConfigNodeUtil.ParseValue<double>(configNode, "weight", x => weight = x, this, 1.0, x => Validation.GE(x, 0.0f)); // Merge in data from the parent contract group for (ContractGroup currentGroup = group; currentGroup != null; currentGroup = currentGroup.parent) { // Merge dataValues - this is a flag saying what values need to be unique at the contract level foreach (KeyValuePair<string, bool> pair in currentGroup.dataValues) { dataValues[group.name + ":" + pair.Key] = pair.Value; } // Merge uniquenessChecks foreach (KeyValuePair<string, DataNode.UniquenessCheck> pair in currentGroup.uniquenessChecks) { uniquenessChecks[group.name + ":" + pair.Key] = pair.Value; } } // Load DATA nodes valid &= dataNode.ParseDataNodes(configNode, this, dataValues, uniquenessChecks); // Check for unexpected values - always do this last valid &= ConfigNodeUtil.ValidateUnexpectedValues(configNode, this); log = LoggingUtil.capturedLog; LoggingUtil.CaptureLog = false; // Load parameters foreach (ConfigNode contractParameter in ConfigNodeUtil.GetChildNodes(configNode, "PARAMETER")) { ParameterFactory paramFactory = null; valid &= ParameterFactory.GenerateParameterFactory(contractParameter, this, out paramFactory); if (paramFactory != null) { paramFactories.Add(paramFactory); if (paramFactory.hasWarnings) { hasWarnings = true; } } } // Load behaviours foreach (ConfigNode requirementNode in ConfigNodeUtil.GetChildNodes(configNode, "BEHAVIOUR")) { BehaviourFactory behaviourFactory = null; valid &= BehaviourFactory.GenerateBehaviourFactory(requirementNode, this, out behaviourFactory); if (behaviourFactory != null) { behaviourFactories.Add(behaviourFactory); if (behaviourFactory.hasWarnings) { hasWarnings = true; } } } // Load requirements foreach (ConfigNode requirementNode in ConfigNodeUtil.GetChildNodes(configNode, "REQUIREMENT")) { ContractRequirement requirement = null; valid &= ContractRequirement.GenerateRequirement(requirementNode, this, out requirement); if (requirement != null) { requirements.Add(requirement); if (requirement.hasWarnings) { hasWarnings = true; } } } // Logging on LoggingUtil.CaptureLog = true; // Check we have at least one valid parameter if (paramFactories.Count() == 0) { LoggingUtil.LogError(this.GetType(), ErrorPrefix() + ": Need at least one parameter for a contract!"); valid = false; } // Do the deferred loads valid &= ConfigNodeUtil.ExecuteDeferredLoads(); config = configNode.ToString(); hash = config.GetHashCode(); enabled = valid; log += LoggingUtil.capturedLog; if (LoggingUtil.logLevel == LoggingUtil.LogLevel.VERBOSE || LoggingUtil.logLevel == LoggingUtil.LogLevel.DEBUG) { //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // to write the complete config and log for contract to both the system log and // a seperate CC log file // string pattern = @"\[(VERBOSE|DEBUG|INFO|WARNING|ERROR)\] ContractConfigurator\.ExpressionParser.BaseParser.+\n"; string replacement = ""; Regex rgx = new Regex(pattern); // First, write to the standard log file. the regex strips out the leading text of the line, but // if you want the text there, then just remove the rgx.Replace LoggingUtil.LogDebug(this, config); // Write the log out, ignoring the BaseParser lines LoggingUtil.LogDebug(this, rgx.Replace(log, replacement)); // Now write to the CC log file, in a much cleaner manner string path = ccLogFile; // Delete the file first time through, ignore any errors if (deleteCCLogfile) { deleteCCLogfile = false; try { if (File.Exists(path)) File.Delete(path); } catch { LoggingUtil.LogError(this, "Exception while attempting to delete the file: " + path); } } // Create the file if it doesn't exist if (!File.Exists(path)) { // Create a file to write to. try { using (StreamWriter sw = File.CreateText(path)) {} } catch { LoggingUtil.LogError(this, "Exception while attempting to create the file: " + path); } } // This regex also strips out the second part of the line, so that the output is very clean string pattern2 = @"\[(VERBOSE|DEBUG|INFO|WARNING|ERROR)\] ContractConfigurator\.ExpressionParser\.DataNode: "; Regex rgx2 = new Regex(pattern2); // Now write the config and the cleaned up log to it try { using (StreamWriter sw = File.AppendText (path)) { sw.WriteLine (config); sw.WriteLine("++++++++++\n"); sw.WriteLine(rgx2.Replace(rgx.Replace(log, replacement), replacement)); sw.WriteLine("=================================================================================="); } } catch { LoggingUtil.LogError(this, "Exception while attempting to write to the file: " + path); } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ } LoggingUtil.CaptureLog = false; return valid; } catch { enabled = false; throw; } finally { LoggingUtil.logLevel = origLogLevel; loaded = true; } }
/// <summary> /// Loads the contract group details from the given config node. /// </summary> /// <param name="configNode">The config node to load from</param> /// <returns>Whether we were successful.</returns> public bool Load(ConfigNode configNode) { try { dataNode = new DataNode(configNode.GetValue("name"), this); LoggingUtil.CaptureLog = true; ConfigNodeUtil.SetCurrentDataNode(dataNode); bool valid = true; valid &= ConfigNodeUtil.ParseValue<string>(configNode, "name", x => name = x, this); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "displayName", x => displayName = x, this, name); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "minVersion", x => minVersion = x, this, ""); valid &= ConfigNodeUtil.ParseValue<int>(configNode, "maxCompletions", x => maxCompletions = x, this, 0, x => Validation.GE(x, 0)); valid &= ConfigNodeUtil.ParseValue<int>(configNode, "maxSimultaneous", x => maxSimultaneous = x, this, 0, x => Validation.GE(x, 0)); valid &= ConfigNodeUtil.ParseValue<List<string>>(configNode, "disabledContractType", x => disabledContractType = x, this, new List<string>()); if (!string.IsNullOrEmpty(minVersion)) { if (Util.Version.VerifyAssemblyVersion("ContractConfigurator", minVersion) == null) { valid = false; var ainfoV = Attribute.GetCustomAttribute(typeof(ExceptionLogWindow).Assembly, typeof(AssemblyInformationalVersionAttribute)) as AssemblyInformationalVersionAttribute; string title = "Contract Configurator " + ainfoV.InformationalVersion + " Message"; string message = "The contract group '" + name + "' requires at least Contract Configurator " + minVersion + " to work, and you are running version " + ainfoV.InformationalVersion + ". Please upgrade Contract Configurator to use the contracts in this group."; DialogOption dialogOption = new DialogOption("Okay", new Callback(DoNothing), true); PopupDialog.SpawnPopupDialog(new MultiOptionDialog(message, title, HighLogic.Skin, dialogOption), false, HighLogic.Skin); } } // Load DATA nodes valid &= dataNode.ParseDataNodes(configNode, this, dataValues, uniquenessChecks); // Do the deferred loads valid &= ConfigNodeUtil.ExecuteDeferredLoads(); config = configNode.ToString(); log += LoggingUtil.capturedLog; LoggingUtil.CaptureLog = false; // Load child groups foreach (ConfigNode childNode in ConfigNodeUtil.GetChildNodes(configNode, "CONTRACT_GROUP")) { ContractGroup child = null; string childName = childNode.GetValue("name"); try { child = new ContractGroup(childName); } catch (ArgumentException) { LoggingUtil.LogError(this, "Couldn't load CONTRACT_GROUP '" + childName + "' due to a duplicate name."); valid = false; continue; } valid &= child.Load(childNode); child.parent = this; child.dataNode.Parent = dataNode; if (child.hasWarnings) { hasWarnings = true; } } // Check for unexpected values - always do this last valid &= ConfigNodeUtil.ValidateUnexpectedValues(configNode, this); // Invalidate children if (!valid) { Invalidate(); } enabled = valid; return valid; } catch { enabled = false; throw; } }
/// <summary> /// Loads the contract group details from the given config node. /// </summary> /// <param name="configNode">The config node to load from</param> /// <returns>Whether we were successful.</returns> public bool Load(ConfigNode configNode) { try { dataNode = new DataNode(configNode.GetValue("name"), this); LoggingUtil.CaptureLog = true; ConfigNodeUtil.SetCurrentDataNode(dataNode); bool valid = true; string unused; valid &= ConfigNodeUtil.ParseValue<string>(configNode, "name", x => name = x, this); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "displayName", x => displayName = x, this, name); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "minVersion", x => minVersionStr = x, this, ""); valid &= ConfigNodeUtil.ParseValue<int>(configNode, "maxCompletions", x => maxCompletions = x, this, 0, x => Validation.GE(x, 0)); valid &= ConfigNodeUtil.ParseValue<int>(configNode, "maxSimultaneous", x => maxSimultaneous = x, this, 0, x => Validation.GE(x, 0)); valid &= ConfigNodeUtil.ParseValue<List<string>>(configNode, "disabledContractType", x => disabledContractType = x, this, new List<string>()); valid &= ConfigNodeUtil.ParseValue<Agent>(configNode, "agent", x => agent = x, this, (Agent)null); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "sortKey", x => sortKey = x, this, displayName); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "tip", x => unused = x, this, ""); if (configNode.HasValue("sortKey") && parent == null) { sortKey = displayName; LoggingUtil.LogWarning(this, ErrorPrefix() + ": Using the sortKey field is only applicable on child CONTRACT_GROUP elements"); } if (!string.IsNullOrEmpty(minVersionStr)) { if (Util.Version.VerifyAssemblyVersion("ContractConfigurator", minVersionStr) == null) { valid = false; var ainfoV = Attribute.GetCustomAttribute(typeof(ExceptionLogWindow).Assembly, typeof(AssemblyInformationalVersionAttribute)) as AssemblyInformationalVersionAttribute; string title = "Contract Configurator " + ainfoV.InformationalVersion + " Message"; string message = "The contract group '" + name + "' requires at least Contract Configurator " + minVersionStr + " to work, and you are running version " + ainfoV.InformationalVersion + ". Please upgrade Contract Configurator to use the contracts in this group."; DialogGUIButton dialogOption = new DialogGUIButton("Okay", new Callback(DoNothing), true); PopupDialog.SpawnPopupDialog(new MultiOptionDialog(message, title, UISkinManager.GetSkin("default"), dialogOption), false, UISkinManager.GetSkin("default")); } } // Load DATA nodes valid &= dataNode.ParseDataNodes(configNode, this, dataValues, uniquenessChecks); // Do the deferred loads valid &= ConfigNodeUtil.ExecuteDeferredLoads(); // Do post-deferred load warnings if (agent == null) { LoggingUtil.LogWarning(this, ErrorPrefix() + ": Providing the agent field for all CONTRACT_GROUP nodes is highly recommended, as the agent is used to group contracts in Mission Control."); } if (string.IsNullOrEmpty(minVersionStr) || minVersion < ContractConfigurator.ENHANCED_UI_VERSION) { LoggingUtil.LogWarning(this, ErrorPrefix() + ": No minVersion or older minVersion provided. It is recommended that the minVersion is set to at least 1.15.0 to turn important warnings for deprecated functionality into errors."); } if (!configNode.HasValue("displayName")) { LoggingUtil.LogWarning(this, ErrorPrefix() + ": No display name provided. A display name is recommended, as it is used in the Mission Control UI."); } config = configNode.ToString(); log += LoggingUtil.capturedLog; LoggingUtil.CaptureLog = false; // Load child groups foreach (ConfigNode childNode in ConfigNodeUtil.GetChildNodes(configNode, "CONTRACT_GROUP")) { ContractGroup child = null; string childName = childNode.GetValue("name"); try { child = new ContractGroup(childName); } catch (ArgumentException) { LoggingUtil.LogError(this, "Couldn't load CONTRACT_GROUP '" + childName + "' due to a duplicate name."); valid = false; continue; } child.parent = this; valid &= child.Load(childNode); child.dataNode.Parent = dataNode; if (child.hasWarnings) { hasWarnings = true; } } // Check for unexpected values - always do this last valid &= ConfigNodeUtil.ValidateUnexpectedValues(configNode, this); // Invalidate children if (!valid) { Invalidate(); } enabled = valid; return valid; } catch { enabled = false; throw; } }
/// <summary> /// Loads the contract type details from the given config node. /// </summary> /// <param name="configNode">The config node to load from.</param> /// <returns>Whether the load was successful.</returns> public bool Load(ConfigNode configNode) { LoggingUtil.LogLevel origLogLevel = LoggingUtil.logLevel; try { // Logging on LoggingUtil.CaptureLog = true; ConfigNodeUtil.SetCurrentDataNode(null); // Load values that are immediately required bool valid = true; valid &= ConfigNodeUtil.ParseValue<ContractGroup>(configNode, "group", x => group = x, this, (ContractGroup)null); // Set up the data node dataNode = new DataNode(configNode.GetValue("name"), group != null ? group.dataNode : null, this); ConfigNodeUtil.SetCurrentDataNode(dataNode); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "name", x => name = x, this); // Try to turn on trace mode valid &= ConfigNodeUtil.ParseValue<bool>(configNode, "trace", x => trace = x, this, false); if (trace) { LoggingUtil.logLevel = LoggingUtil.LogLevel.VERBOSE; LoggingUtil.LogWarning(this, "Tracing enabled for contract type " + name); } // Load contract text details valid &= ConfigNodeUtil.ParseValue<string>(configNode, "title", x => title = x, this); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "tag", x => tag = x, this, ""); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "description", x => description = x, this, (string)null); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "topic", x => topic = x, this, ""); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "subject", x => subject = x, this, ""); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "motivation", x => motivation = x, this, ""); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "notes", x => notes = x, this, (string)null); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "synopsis", x => synopsis = x, this); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "completedMessage", x => completedMessage = x, this); // Load optional attributes valid &= ConfigNodeUtil.ParseValue<Agent>(configNode, "agent", x => agent = x, this, (Agent)null); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "minExpiry", x => minExpiry = x, this, 1.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "maxExpiry", x => maxExpiry = x, this, 7.0f, x => Validation.GE(x, minExpiry)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "deadline", x => deadline = x, this, 0.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<bool>(configNode, "cancellable", x => cancellable = x, this, true); valid &= ConfigNodeUtil.ParseValue<bool>(configNode, "declinable", x => declinable = x, this, true); valid &= ConfigNodeUtil.ParseValue<bool>(configNode, "autoAccept", x => autoAccept = x, this, false); valid &= ConfigNodeUtil.ParseValue<List<Contract.ContractPrestige>>(configNode, "prestige", x => prestige = x, this, new List<Contract.ContractPrestige>()); valid &= ConfigNodeUtil.ParseValue<CelestialBody>(configNode, "targetBody", x => targetBody = x, this, (CelestialBody)null); valid &= ConfigNodeUtil.ParseValue<int>(configNode, "maxCompletions", x => maxCompletions = x, this, 0, x => Validation.GE(x, 0)); valid &= ConfigNodeUtil.ParseValue<int>(configNode, "maxSimultaneous", x => maxSimultaneous = x, this, 0, x => Validation.GE(x, 0)); // Load rewards valid &= ConfigNodeUtil.ParseValue<float>(configNode, "rewardFunds", x => rewardFunds = x, this, 0.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "rewardReputation", x => rewardReputation = x, this, 0.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "rewardScience", x => rewardScience = x, this, 0.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "failureFunds", x => failureFunds = x, this, 0.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "failureReputation", x => failureReputation = x, this, 0.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "advanceFunds", x => advanceFunds = x, this, 0.0f, x => Validation.GE(x, 0.0f)); // Load other values valid &= ConfigNodeUtil.ParseValue<double>(configNode, "weight", x => weight = x, this, 1.0, x => Validation.GE(x, 0.0f)); // Merge in data from the parent contract group for (ContractGroup currentGroup = group; currentGroup != null; currentGroup = currentGroup.parent) { // Merge dataValues - this is a flag saying what values need to be unique at the contract level foreach (KeyValuePair<string, bool> pair in currentGroup.dataValues) { dataValues[group.name + ":" + pair.Key] = pair.Value; } // Merge uniqueValues - this is just a flag saying what values to do uniqueness checks on foreach (KeyValuePair<string, bool> pair in currentGroup.uniqueValues) { uniqueValues[group.name + ":" + pair.Key] = pair.Value; } } // Load DATA nodes valid &= dataNode.ParseDataNodes(configNode, this, dataValues, uniqueValues); // Check for unexpected values - always do this last valid &= ConfigNodeUtil.ValidateUnexpectedValues(configNode, this); log = LoggingUtil.capturedLog; LoggingUtil.CaptureLog = false; // Load parameters foreach (ConfigNode contractParameter in ConfigNodeUtil.GetChildNodes(configNode, "PARAMETER")) { ParameterFactory paramFactory = null; valid &= ParameterFactory.GenerateParameterFactory(contractParameter, this, out paramFactory); if (paramFactory != null) { paramFactories.Add(paramFactory); if (paramFactory.hasWarnings) { hasWarnings = true; } } } // Load behaviours foreach (ConfigNode requirementNode in ConfigNodeUtil.GetChildNodes(configNode, "BEHAVIOUR")) { BehaviourFactory behaviourFactory = null; valid &= BehaviourFactory.GenerateBehaviourFactory(requirementNode, this, out behaviourFactory); if (behaviourFactory != null) { behaviourFactories.Add(behaviourFactory); if (behaviourFactory.hasWarnings) { hasWarnings = true; } } } // Load requirements foreach (ConfigNode requirementNode in ConfigNodeUtil.GetChildNodes(configNode, "REQUIREMENT")) { ContractRequirement requirement = null; valid &= ContractRequirement.GenerateRequirement(requirementNode, this, out requirement); if (requirement != null) { requirements.Add(requirement); if (requirement.hasWarnings) { hasWarnings = true; } } } // Logging on LoggingUtil.CaptureLog = true; // Check we have at least one valid parameter if (paramFactories.Count() == 0) { LoggingUtil.LogError(this.GetType(), ErrorPrefix() + ": Need at least one parameter for a contract!"); valid = false; } // Do the deferred loads valid &= ConfigNodeUtil.ExecuteDeferredLoads(); config = configNode.ToString(); hash = config.GetHashCode(); enabled = valid; log += LoggingUtil.capturedLog; LoggingUtil.CaptureLog = false; return valid; } catch { enabled = false; throw; } finally { LoggingUtil.logLevel = origLogLevel; loaded = true; } }