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