void CheckValueMatchesRegex(CfgMetadata metaData, string name, string value) { if (!metaData.Attribute.RegexIsSet || metaData.Regex == null) { return; } if (!metaData.Regex.IsMatch(value)) { Events.ValueDoesNotMatchRegex(name, value, metaData.Attribute.regex); } }
void ValidateUniqueAndRequiredProperties( string parent, string listName, CfgMetadata listMetadata, ICollection list ) { //if more than one then uniqueness comes into question if (list.Count > 1) { lock (Locker) { if (listMetadata.UniquePropertiesInList == null) { listMetadata.UniquePropertiesInList = CfgMetadataCache.GetMetadata(listMetadata.ListType) .Where(p => p.Value.Attribute.unique) .Select(p => p.Key) .ToArray(); } } if (listMetadata.UniquePropertiesInList.Length <= 0) { return; } for (var j = 0; j < listMetadata.UniquePropertiesInList.Length; j++) { var unique = listMetadata.UniquePropertiesInList[j]; var duplicates = list .Cast <CfgNode>() .Where(n => n.UniqueProperties.ContainsKey(unique)) .Select(n => n.UniqueProperties[unique]) .GroupBy(n => n) .Where(group => @group.Count() > 1) .Select(group => @group.Key) .ToArray(); for (var l = 0; l < duplicates.Length; l++) { Events.DuplicateSet(unique, duplicates[l], listName); } } } else if (list.Count == 0 && listMetadata.Attribute.required) { Events.MissingRequiredAdd(parent, listName); } }
internal static Dictionary <string, CfgMetadata> GetMetadata(Type type) { Dictionary <string, CfgMetadata> metadata; if (MetadataCache.TryGetValue(type, out metadata)) { return(metadata); } lock (Locker) { NameCache[type] = new Dictionary <string, string>(); var keyCache = new List <string>(); var listCache = new List <string>(); #if NETS var propertyInfos = type.GetRuntimeProperties().ToArray(); #else var propertyInfos = type.GetProperties(); #endif metadata = new Dictionary <string, CfgMetadata>(StringComparer.Ordinal); foreach (var propertyInfo in propertyInfos) { if (!propertyInfo.CanRead) { continue; } if (!propertyInfo.CanWrite) { continue; } #if NETS var attribute = (CfgAttribute)propertyInfo.GetCustomAttribute(typeof(CfgAttribute), true); #else var attribute = (CfgAttribute)Attribute.GetCustomAttribute(propertyInfo, typeof(CfgAttribute), true); #endif if (attribute == null) { continue; } var key = NormalizeName(type, propertyInfo.Name); var item = new CfgMetadata(propertyInfo, attribute) { TypeDefault = GetDefaultValue(propertyInfo.PropertyType) }; // regex try { if (attribute.RegexIsSet) { #if NETS item.Regex = attribute.ignoreCase ? new Regex(attribute.regex, RegexOptions.IgnoreCase) : new Regex(attribute.regex); #else item.Regex = attribute.ignoreCase ? new Regex(attribute.regex, RegexOptions.Compiled | RegexOptions.IgnoreCase) : new Regex(attribute.regex, RegexOptions.Compiled); #endif } } catch (ArgumentException ex) { item.Errors.Add(CfgEvents.InvalidRegex(key, attribute.regex, ex)); } // check default value for type mismatch if (attribute.ValueIsSet) { if (attribute.value.GetType() != propertyInfo.PropertyType) { var value = attribute.value; if (TryConvertValue(ref value, propertyInfo.PropertyType)) { attribute.value = value; } else { item.TypeMismatch = true; item.Errors.Add(CfgEvents.TypeMismatch(key, value, propertyInfo.PropertyType)); } } } // type safety for value, min value, and max value var defaultValue = attribute.value; if (ResolveType(() => attribute.ValueIsSet, ref defaultValue, key, item)) { attribute.value = defaultValue; } var minValue = attribute.minValue; if (ResolveType(() => attribute.MinValueSet, ref minValue, key, item)) { attribute.minValue = minValue; } var maxValue = attribute.maxValue; if (ResolveType(() => attribute.MaxValueSet, ref maxValue, key, item)) { attribute.maxValue = maxValue; } //foreach (var cp in constructors) { // if (!cp.Any()) { // obj = item.ListActivator(); // break; // } // if (cp.Count() == 1) { // if (cp.First().ParameterType == typeof(int)) { // obj = Activator.CreateInstance(item.ListType, add.Attributes.Count); // break; // } // if (cp.First().ParameterType == typeof(string[])) { // var names = add.Attributes.Select(a => a.Name).ToArray(); // obj = Activator.CreateInstance(item.ListType, new object[] { names }); // break; // } // } //} #if NETS var propertyTypeInfo = propertyInfo.PropertyType.GetTypeInfo(); if (propertyTypeInfo.IsGenericType) { listCache.Add(key); item.ListType = propertyTypeInfo.GenericTypeArguments[0]; var listTypeInfo = item.ListType.GetTypeInfo(); item.ImplementsProperties = typeof(IProperties).GetTypeInfo().IsAssignableFrom(listTypeInfo); item.Constructors = propertyTypeInfo.DeclaredConstructors.Select(c => c.GetParameters()); item.ListActivator = () => Activator.CreateInstance(propertyInfo.PropertyType); if (listTypeInfo.IsSubclassOf(typeof(CfgNode))) { item.Loader = () => (CfgNode)Activator.CreateInstance(item.ListType); } } else { keyCache.Add(key); } #else if (propertyInfo.PropertyType.IsGenericType) { listCache.Add(key); item.ListType = propertyInfo.PropertyType.GetGenericArguments()[0]; item.ImplementsProperties = typeof(IProperties).IsAssignableFrom(item.ListType); item.Constructors = item.ListType.GetConstructors().Select(c => c.GetParameters()); item.ListActivator = () => Activator.CreateInstance(propertyInfo.PropertyType); if (item.ListType.IsSubclassOf(typeof(CfgNode))) { item.Loader = () => (CfgNode)Activator.CreateInstance(item.ListType); } } else { keyCache.Add(key); } #endif if (string.IsNullOrEmpty(attribute.name)) { attribute.name = key; } item.Setter = CfgReflectionHelper.CreateSetter(propertyInfo); item.Getter = CfgReflectionHelper.CreateGetter(propertyInfo); metadata[key] = item; } PropertyCache[type] = keyCache; ElementCache[type] = listCache; MetadataCache[type] = metadata; return(metadata); } }
private static bool ResolveType(Func <bool> isSet, ref object input, string key, CfgMetadata metadata) { if (!isSet()) { return(true); } var type = metadata.PropertyInfo.PropertyType; if (input.GetType() == type) { return(true); } var value = input; if (TryConvertValue(ref value, type)) { input = value; return(true); } metadata.TypeMismatch = true; metadata.Errors.Add(CfgEvents.TypeMismatch(key, value, type)); return(false); }
void CheckValidators(CfgMetadata item, string name, object value) { if (!item.Attribute.ValidatorsSet) return; foreach (var validator in item.Validators()) { if (Validators.ContainsKey(validator)) { try { var result = Validators[validator].Validate(name, value); if (result.Valid) continue; if (result.Warnings != null) { foreach (var warning in result.Warnings) { Warn(warning); } } if (result.Errors != null) { foreach (var error in result.Errors) { Error(error); } } } catch (Exception ex) { Events.ValidatorException(validator, ex, value); } } else { Events.MissingValidator(name, validator); } } }
void ValidateUniqueAndRequiredProperties( string parent, string listName, CfgMetadata listMetadata, ICollection list ) { //if more than one then uniqueness comes into question if (list.Count > 1) { lock (Locker) { if (listMetadata.UniquePropertiesInList == null) { listMetadata.UniquePropertiesInList = CfgMetadataCache.GetMetadata(listMetadata.ListType, Events) .Where(p => p.Value.Attribute.unique) .Select(p => p.Key) .ToArray(); } } if (listMetadata.UniquePropertiesInList.Length <= 0) return; for (var j = 0; j < listMetadata.UniquePropertiesInList.Length; j++) { var unique = listMetadata.UniquePropertiesInList[j]; var duplicates = list .Cast<CfgNode>() .Where(n => n.UniqueProperties.ContainsKey(unique)) .Select(n => n.UniqueProperties[unique]) .GroupBy(n => n) .Where(group => @group.Count() > 1) .Select(group => @group.Key) .ToArray(); for (var l = 0; l < duplicates.Length; l++) { Events.DuplicateSet(unique, duplicates[l], listName); } } } else if (list.Count == 0 && listMetadata.Attribute.required) { Events.MissingRequiredAdd(parent, listName); } }