Exemplo n.º 1
0
        /// <summary>
        /// Tries read an entry of the data by the path and creates a new class/struct.
        /// </summary>
        /// <param name="type"> The type. </param>
        /// <param name="className"> Name of the class. </param>
        /// <param name="values"> Values of the class. </param>
        /// <param name="path"> The path. </param>
        /// <param name="storer"> The storer. </param>
        /// <param name="entries"> List of the entries of the storer. </param>
        /// <param name="references"> Dictionary that contains references to the objects. </param>
        /// <returns> Graph if graph has been created successfully, otherwise null. </returns>
        private object TryReadFormattable(string path, Type type, string className, IDictionary <string, string> values, IReadOnlyDataStorer storer, LinkedList <IDataStorerEntry> entries, Dictionary <string, object> references)
        {
            // Tries get the formattable type that is related (same) with the declared type

            FormattableType formattableType = this.formattableTypes.FindOrDefault(f => f.Name == className && f.IsRelatedType(type, false));

            if (formattableType == null)
            {
                // Tries get the formattable type that is related (not same, derived) with the declared type
                formattableType = this.formattableTypes.FindOrDefault(f => f.IsRelatedType(type, true));
            }

            if (formattableType == null)
            {
                // Formattable type is null -> type isn't supported -> returns null
                return(null);
            }

            object graph = formattableType.CreateInstance(type);

            references.Add(path, graph);

            formattableType.OnDeserializing(graph);

            // Restores the keys and values of the objects

            FormattableValue[] formattableValues = formattableType.GetValues(type);
            int length = formattableValues.Length;

            FormattableValue value     = null;
            Type             valueType = null;
            string           valueName = "";

            for (int i = 0; i < length; i++)
            {
                value     = formattableValues[i];
                valueType = value.Type;
                valueName = value.Name;

                if (this.IsPrimitive(valueType))
                {
                    // Value of the object is primitive - reads it from information file

                    Func <string, object> primitiveConverter = this.GetPrimitiveConverterToObject(valueType);

                    if (values.ContainsKey(value.Name))
                    {
                        value.SetValue(graph, primitiveConverter(values[valueName]));
                    }
                    else
                    {
                        if (!value.Optional)
                        {
                            throw new KeyCanNotLoadedException(formattableType, valueName);
                        }
                    }
                }
                else
                {
                    // Value of the object isn't primitive - reads it from special file

                    try
                    {
                        value.SetValue(graph,
                                       this.Read(
                                           value.Type,
                                           StringUtils.Combine(path, valueName, DirectorySeparatorString),
                                           storer,
                                           entries,
                                           references
                                           ));
                    }
                    catch (Exception ex)
                    {
                        // Thrown error if value isn't optional

                        if (!value.Optional)
                        {
                            throw new KeyCanNotLoadedException(formattableType, valueName, ex);
                        }
                    }
                }
            }

            formattableType.OnDeserialized(graph);

            // Makes the substitution (if required)

            object substitution = formattableType.Substitution(graph);

            if (substitution != graph)
            {
                references.Remove(path);
                references.Add(path, substitution);

                // Returns the substituted graph

                return(substitution);
            }
            else
            {
                // Returns the created graph

                return(graph);
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Builds a target type that based on declared type that is associated with the current type.
        /// </summary>
        /// <param name="declaredType"> Declared type. </param>
        private void BuildType(Type declaredType)
        {
            Type createdType = null;

            if (!this.createdTypes.TryGetValue(declaredType, out createdType))
            {
                // Creates a new type

                createdType = (this.isGenericTypeDefinition) ? this.hostType.MakeGenericType(declaredType.GetGenericArguments()) : this.hostType;

                // Creates an activator for the created type

                IFunctionCallback <object> factoryMethod = ReflectionUtils.CreateInstance(createdType);

                // Creates the callbacks for the get/set accessors of the fields

                KeyAttribute     keyAttribute;
                FormattableValue value;
                LinkedList <FormattableValue>      loadedValues = new LinkedList <FormattableValue>();
                IFunctionCallback <object, object> getAccessor  = null;
                IActionCallback <object, object>   setAccessor  = null;

                FieldInfo[] fields       = createdType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
                int         fieldsLength = fields.Length;
                FieldInfo   field        = null;

                for (int i = 0; i < fieldsLength; i++)
                {
                    field        = fields[i];
                    keyAttribute = field.GetAttribute <KeyAttribute>(true);

                    if (keyAttribute != null)
                    {
                        getAccessor = ReflectionUtils.CreateGetAccessor(createdType, field);
                        setAccessor = ReflectionUtils.CreateSetAccessor(createdType, field);

                        value = new FormattableValue(
                            keyAttribute.Name,
                            keyAttribute.Optional,
                            keyAttribute.Order,
                            field.FieldType,
                            getAccessor,
                            setAccessor
                            );

                        loadedValues.AddLast(value);
                    }
                }

                // Action that used for getting the key attribute and property info of the overridden properties

                PropertyInfo property          = null;
                MethodInfo   propertyGetMethod = null;
                Type         baseType          = null;

                Action <Type, string> getPropertyKeyAttributeFromBase = null;
                getPropertyKeyAttributeFromBase = (t, n) =>
                {
                    baseType = t.BaseType;
                    if (baseType == null)
                    {
                        return;
                    }

                    property = baseType.GetProperty(n, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);

                    if (property != null)
                    {
                        keyAttribute = property.GetAttribute <KeyAttribute>(true);
                        if (keyAttribute == null)
                        {
                            propertyGetMethod = property.GetGetMethod(true);
                            if (propertyGetMethod == null || propertyGetMethod.GetBaseDefinition() != propertyGetMethod)
                            {
                                // Property is overridden - tests the properties of the base type
                                getPropertyKeyAttributeFromBase(baseType, n);
                            }
                        }
                    }
                    else
                    {
                        // Required property isn't exists in the type - tests the properties of the base type
                        getPropertyKeyAttributeFromBase(baseType, n);
                    }
                };

                // Creates the callbacks for the get/set accessors of the properties

                PropertyInfo[] properties       = createdType.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
                int            propertiesLength = properties.Length;

                for (int i = 0; i < propertiesLength; i++)
                {
                    property     = properties[i];
                    keyAttribute = property.GetAttribute <KeyAttribute>(true);

                    if (keyAttribute == null)
                    {
                        propertyGetMethod = property.GetGetMethod(true);
                        if (propertyGetMethod == null || propertyGetMethod.GetBaseDefinition() != propertyGetMethod)
                        {
                            // Property is overridden - tests the properties of the base type

                            getPropertyKeyAttributeFromBase(createdType, property.Name);
                        }
                    }

                    if (keyAttribute == null || property.GetIndexParameters().Length != 0)
                    {
                        continue;
                    }

                    getAccessor = ReflectionUtils.CreateGetAccessor(createdType, property);
                    setAccessor = ReflectionUtils.CreateSetAccessor(createdType, property);

                    value = new FormattableValue(
                        keyAttribute.Name,
                        keyAttribute.Optional,
                        keyAttribute.Order,
                        property.PropertyType,
                        getAccessor,
                        setAccessor
                        );

                    loadedValues.AddLast(value);
                }

                // Sorts the values by order

                FormattableValue[] sortedValues = loadedValues.ToArray();
                SortUtils.QuickSort(true, sortedValues);

                // Saves the factory method, sorted values and created type

                this.factoryMethods.Add(declaredType, factoryMethod);
                this.values.Add(declaredType, sortedValues);
                this.createdTypes.Add(declaredType, createdType);
            }
        }