internal void ValidateBasedOnAttributes(INode node, IDictionary <string, string> parameters) { var metadata = CfgMetadataCache.GetMetadata(Type); var keys = CfgMetadataCache.PropertyNames(Type).ToArray(); if (!keys.Any()) { return; } for (var i = 0; i < keys.Length; i++) { var key = keys[i]; var item = metadata[key]; var objectValue = item.Getter(this); if (objectValue == null) { continue; } var stringValue = item.PropertyInfo.PropertyType == typeof(string) ? (string)objectValue : objectValue.ToString(); if (item.Attribute.unique) { UniqueProperties[key] = stringValue; } if (item.Attribute.DomainSet) { if (!item.IsInDomain(stringValue)) { Events.ValueNotInDomain(key, stringValue, item.Attribute.domain.Replace(item.Attribute.delimiter.ToString(), ", ")); } } CheckValueLength(item.Attribute, key, stringValue); CheckValueBoundaries(item.Attribute, key, objectValue); CheckValueMatchesRegex(item, key, stringValue); } }
private void LoadProperties(INode node, string parentName, IDictionary <string, string> parameters, IList <ICustomizer> customizers) { var metadata = CfgMetadataCache.GetMetadata(Type); var keys = CfgMetadataCache.PropertyNames(Type).ToArray(); if (!keys.Any()) { return; } var keyHits = new HashSet <string>(); var nullWarnings = new HashSet <string>(); // first pass, set default values and report invalid attributes foreach (var attribute in node.Attributes) { var attributeKey = CfgMetadataCache.NormalizeName(Type, attribute.Name); if (metadata.ContainsKey(attributeKey)) { var item = metadata[attributeKey]; if (attribute.Value != null) { continue; } // if attribute is null, use the getter var maybe = item.Getter(this); if (maybe == null) { if (nullWarnings.Add(attribute.Name)) { Events.Warning($"'{attribute.Name}' in '{parentName}' is susceptible to nulls."); } continue; } attribute.Value = maybe; } else { if (attributeKey != "sequence") { Events.InvalidAttribute(parentName, node.Name, attribute.Name, string.Join(", ", keys)); } } } foreach (var customizer in customizers) { try { customizer.Customize(parentName, node, parameters, Events.Logger); } catch (Exception ex) { Events.Error($"{customizer.GetType().Name} error: {ex.Message}"); } } // second pass, after customizers, adjust case and trim, set property value foreach (var attribute in node.Attributes) { var attributeKey = CfgMetadataCache.NormalizeName(Type, attribute.Name); if (metadata.ContainsKey(attributeKey)) { var item = metadata[attributeKey]; if (item.PropertyInfo.PropertyType == typeof(string)) { if (attribute.Value == null) // user has not provided a default { continue; } var stringValue = attribute.Value.ToString(); if (Enabled) { if (item.Attribute.toLower) { stringValue = stringValue.ToLower(); } else if (item.Attribute.toUpper) { stringValue = stringValue.ToUpper(); } if (item.Attribute.trim || item.Attribute.trimStart && item.Attribute.trimEnd) { stringValue = stringValue.Trim(); } else { if (item.Attribute.trimStart) { stringValue = stringValue.TrimStart(); } if (item.Attribute.trimEnd) { stringValue = stringValue.TrimEnd(); } } } attribute.Value = stringValue; item.Setter(this, attribute.Value); keyHits.Add(attributeKey); } else { try { item.Setter(this, CfgConstants.Converter[item.PropertyInfo.PropertyType](attribute.Value)); keyHits.Add(attributeKey); } catch (Exception ex) { Events.SettingValue(attribute.Name, attribute.Value, parentName, node.Name, ex.Message); } } } } // missing any required attributes? if (Enabled) { foreach (var key in keys.Except(keyHits)) { var item = metadata[key]; if (item.Attribute.required) { Events.MissingAttribute(parentName, node.Name, key); } } } }