Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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);
            }
        }