/// <summary>
        /// Used by dependency sort algorithm.
        /// </summary>
        private static void Visit(ViewTypeData viewTypeData, List <ViewTypeData> sorted, string dependencyChain)
        {
            if (viewTypeData.TemporaryMark)
            {
                // cyclical dependency detected
                throw new Exception(String.Format("Cyclical dependency {0}{1} detected.", dependencyChain, viewTypeData.ViewName));
            }
            else if (!viewTypeData.PermanentMark)
            {
                viewTypeData.TemporaryMark = true;
                foreach (var dependency in viewTypeData.Dependencies)
                {
                    Visit(dependency, sorted, String.Format("{0}{1}->", dependencyChain, viewTypeData.ViewName));
                }
                viewTypeData.TemporaryMark = false;
                viewTypeData.PermanentMark = true;

                // add element to list
                sorted.Add(viewTypeData);
            }
        }
        /// <summary>
        /// Loads XUML to view database.
        /// </summary>
        private static void LoadViewXuml(XElement xumlElement, string xuml)
        {
            var viewPresenter = ViewPresenter.Instance;

            viewPresenter.ViewTypeDataList.RemoveAll(x => String.Equals(x.ViewName, xumlElement.Name.LocalName, StringComparison.OrdinalIgnoreCase));

            var viewTypeData = new ViewTypeData();

            viewPresenter.ViewTypeDataList.Add(viewTypeData);

            viewTypeData.Xuml        = xuml;
            viewTypeData.XumlElement = xumlElement;
            viewTypeData.ViewName    = xumlElement.Name.LocalName;

            // set dependency names
            foreach (var descendant in xumlElement.Descendants())
            {
                if (!viewTypeData.DependencyNames.Contains(descendant.Name.LocalName, StringComparer.OrdinalIgnoreCase))
                {
                    viewTypeData.DependencyNames.Add(descendant.Name.LocalName);
                }
            }

            // set view type
            var type = GetViewType(viewTypeData.ViewName);

            if (type == null)
            {
                type = typeof(View);
            }

            // set if view is internal
            viewTypeData.HideInPresenter = type.GetCustomAttributes(typeof(HideInPresenter), false).Any();

            // set view action fields
            var viewActionType = typeof(ViewAction);
            var actionFields   = type.GetFields().Where(x => x.FieldType == viewActionType).Select(y => y.Name);

            viewTypeData.ViewActionFields.AddRange(actionFields);

            // set dependency fields
            var viewFieldBaseType = typeof(ViewFieldBase);
            var dependencyFields  = type.GetFields().Where(x => viewFieldBaseType.IsAssignableFrom(x.FieldType)).Select(y => y.Name);

            viewTypeData.DependencyFields.AddRange(dependencyFields);

            // set component fields
            var componentType   = typeof(Component);
            var baseViewType    = typeof(View);
            var componentFields = type.GetFields().Where(x => componentType.IsAssignableFrom(x.FieldType) &&
                                                         !baseViewType.IsAssignableFrom(x.FieldType)).Select(y => y.Name);

            viewTypeData.ComponentFields.AddRange(componentFields);

            // set reference fields
            var referenceFields = type.GetFields().Where(x => baseViewType.IsAssignableFrom(x.FieldType) &&
                                                         x.Name != "Parent" && x.Name != "LayoutParent").Select(y => y.Name);

            viewTypeData.ReferenceFields.AddRange(referenceFields);
            viewTypeData.ReferenceFields.Add("GameObject");

            // set excluded component fields
            var excludedComponentFields = type.GetCustomAttributes(typeof(ExcludeComponent), true);

            viewTypeData.ExcludedComponentFields.AddRange(excludedComponentFields.Select(x => (x as ExcludeComponent).ComponentFieldName));

            // set mapped fields and their converters and change handlers
            var mapFields      = type.GetFields().SelectMany(x => x.GetCustomAttributes(typeof(MapViewField), true));
            var mapClassFields = type.GetCustomAttributes(typeof(MapViewField), true);

            viewTypeData.MapViewFields.AddRange(mapFields.Select(x => (x as MapViewField).MapFieldData));
            viewTypeData.MapViewFields.AddRange(mapClassFields.Select(x => (x as MapViewField).MapFieldData));

            // .. add mapped dependency fields
            foreach (var field in type.GetFields())
            {
                var mapTo = field.GetCustomAttributes(typeof(MapTo), true).FirstOrDefault() as MapTo;
                if (mapTo == null)
                {
                    continue;
                }

                mapTo.MapFieldData.From = field.Name;
                viewTypeData.MapViewFields.Add(mapTo.MapFieldData);
            }

            //  .. init change handlers and value converters
            foreach (var mapField in viewTypeData.MapViewFields)
            {
                if (mapField.ValueConverterTypeSet)
                {
                    viewTypeData.ViewFieldConverters.Add(new ViewFieldConverterData {
                        ValueConverterType = mapField.ValueConverterType, ViewField = mapField.To
                    });
                }

                if (mapField.ChangeHandlerNameSet)
                {
                    viewTypeData.ViewFieldChangeHandlers.Add(new ViewFieldChangeHandler
                    {
                        ChangeHandlerName  = mapField.ChangeHandlerName,
                        ViewField          = mapField.To,
                        TriggerImmediately = mapField.TriggerChangeHandlerImmediately
                    });
                }
            }

            // set view field converters and change handlers
            foreach (var field in type.GetFields())
            {
                var valueConverter = field.GetCustomAttributes(typeof(ValueConverter), true).FirstOrDefault();
                if (valueConverter != null)
                {
                    viewTypeData.ViewFieldConverters.Add(new ViewFieldConverterData {
                        ViewField = field.Name, ValueConverterType = valueConverter.GetType().Name
                    });
                }

                var changeHandler = field.GetCustomAttributes(typeof(ChangeHandler), true).FirstOrDefault() as ChangeHandler;
                if (changeHandler != null)
                {
                    viewTypeData.ViewFieldChangeHandlers.Add(new ViewFieldChangeHandler {
                        ViewField = field.Name, ChangeHandlerName = changeHandler.Name, TriggerImmediately = changeHandler.TriggerImmediately
                    });
                }

                var notNotSetFromXuml = field.GetCustomAttributes(typeof(NotSetFromXuml), true).FirstOrDefault() as NotSetFromXuml;
                if (notNotSetFromXuml != null)
                {
                    viewTypeData.FieldsNotSetFromXuml.Add(field.Name);
                }

                var genericViewField = field.GetCustomAttributes(typeof(GenericViewField), true).FirstOrDefault();
                if (genericViewField != null)
                {
                    viewTypeData.GenericViewFields.Add(field.Name);
                }
            }

            // get the normal fields that aren't mapped
            var fields = type.GetFields().Where(x =>
                                                !viewTypeData.FieldsNotSetFromXuml.Contains(x.Name) &&
                                                !viewTypeData.ReferenceFields.Contains(x.Name) &&
                                                !viewTypeData.ComponentFields.Contains(x.Name) &&
                                                !viewTypeData.ViewActionFields.Contains(x.Name) &&
                                                !viewTypeData.DependencyFields.Contains(x.Name) &&
                                                !x.IsStatic
                                                ).Select(y => y.Name);
            var properties = type.GetProperties().Where(x =>
                                                        !viewTypeData.FieldsNotSetFromXuml.Contains(x.Name) &&
                                                        !viewTypeData.ReferenceFields.Contains(x.Name) &&
                                                        !viewTypeData.ComponentFields.Contains(x.Name) &&
                                                        !viewTypeData.ViewActionFields.Contains(x.Name) &&
                                                        !viewTypeData.DependencyFields.Contains(x.Name) &&
#if !UNITY_WINRT || UNITY_WINRT_10_0 || UNITY_EDITOR
                                                        x.GetSetMethod() != null &&
                                                        x.GetGetMethod() != null &&
#endif
                                                        x.Name != "enabled" &&
                                                        x.Name != "useGUILayout" &&
                                                        x.Name != "tag" &&
                                                        x.Name != "hideFlags" &&
                                                        x.Name != "name"
                                                        ).Select(y => y.Name);

            viewTypeData.ViewFields.AddRange(fields);
            viewTypeData.ViewFields.AddRange(properties);
        }
Exemple #3
0
        /// <summary>
        /// Loads XUML to view database.
        /// </summary>
        private static void LoadViewXuml(XElement xumlElement, string xuml)
        {
            var viewPresenter = ViewPresenter.Instance;

            viewPresenter.ViewTypeDataList.RemoveAll(x => String.Equals(x.ViewTypeName, xumlElement.Name.LocalName, StringComparison.OrdinalIgnoreCase));

            var viewTypeData = new ViewTypeData();

            viewPresenter.ViewTypeDataList.Add(viewTypeData);

            viewTypeData.Xuml         = xuml;
            viewTypeData.XumlElement  = xumlElement;
            viewTypeData.ViewTypeName = xumlElement.Name.LocalName;
            viewTypeData.ViewNameAliases.Add(viewTypeData.ViewTypeName);

            // set dependency names
            foreach (var descendant in xumlElement.Descendants())
            {
                if (!viewTypeData.DependencyNames.Contains(descendant.Name.LocalName, StringComparer.OrdinalIgnoreCase))
                {
                    viewTypeData.DependencyNames.Add(descendant.Name.LocalName);
                }
            }

            // set view type
            var type = GetViewType(viewTypeData.ViewTypeName);

            if (type == null)
            {
                type = typeof(View);
            }
            var typeFields      = type.GetFields();
            var typeFieldsCount = typeFields.Length;

            // set if view is internal
            viewTypeData.HideInPresenter = type.GetCustomAttributes(typeof(HideInPresenter), false).Any();

            // set view action fields
            var viewActionType   = typeof(ViewAction);
            var viewActionFields = viewTypeData.ViewActionFields;

            for (var i = 0; i < typeFieldsCount; ++i)
            {
                var x = typeFields[i];
                if (x.FieldType == viewActionType)
                {
                    viewActionFields.Add(x.Name);
                }
            }


            // set dependency fields
            var viewFieldBaseType = typeof(ViewFieldBase);
            var dependencyFields  = viewTypeData.DependencyFields;

            for (var i = 0; i < typeFieldsCount; ++i)
            {
                var x = typeFields[i];
                if (viewFieldBaseType.IsAssignableFrom(x.FieldType))
                {
                    dependencyFields.Add(x.Name);
                }
            }

            // set component fields
            var componentType   = typeof(Component);
            var baseViewType    = typeof(View);
            var componentFields = viewTypeData.ComponentFields;

            for (var i = 0; i < typeFieldsCount; ++i)
            {
                var x = typeFields[i];
                if (componentType.IsAssignableFrom(x.FieldType) && !baseViewType.IsAssignableFrom(x.FieldType))
                {
                    componentFields.Add(x.Name);
                }
            }

            // set reference fields
            var referenceFields = viewTypeData.ReferenceFields;

            for (var i = 0; i < typeFieldsCount; ++i)
            {
                var x = typeFields[i];
                if (baseViewType.IsAssignableFrom(x.FieldType) && x.Name != "Parent" && x.Name != "LayoutParent")
                {
                    referenceFields.Add(x.Name);
                }
            }
            referenceFields.Add("GameObject");

            // set excluded component fields
            var excludedComponentFields = type.GetCustomAttributes(typeof(ExcludeComponent), true);

            viewTypeData.ExcludedComponentFields.AddRange(excludedComponentFields.Select(x => (x as ExcludeComponent).ComponentFieldName));

            // set view-model to view mappings
            var viewNameAliases = type.GetCustomAttributes(typeof(ViewNameAlias), false);

            viewTypeData.ViewNameAliases.AddRange(viewNameAliases.Select(x => (x as ViewNameAlias).ViewAlias));

            // set view-model replacements
            var replacesViewModel = type.GetCustomAttributes(typeof(ReplacesViewModel), false).FirstOrDefault();

            if (replacesViewModel != null)
            {
                viewTypeData.ReplacesViewModel = (replacesViewModel as ReplacesViewModel).ViewTypeName;
            }

            // set mapped fields and their converters and change handlers
            var mapFields      = typeFields.SelectMany(x => x.GetCustomAttributes(typeof(MapViewField), true));
            var mapClassFields = type.GetCustomAttributes(typeof(MapViewField), true);

            viewTypeData.MapViewFields.AddRange(mapFields.Select(x => (x as MapViewField).MapFieldData));
            viewTypeData.MapViewFields.AddRange(mapClassFields.Select(x => (x as MapViewField).MapFieldData));

            // .. add mapped dependency fields
            foreach (var field in typeFields)
            {
                var mapTo = field.GetCustomAttributes(typeof(MapTo), true).FirstOrDefault() as MapTo;
                if (mapTo == null)
                {
                    continue;
                }

                mapTo.MapFieldData.From = field.Name;
                viewTypeData.MapViewFields.Add(mapTo.MapFieldData);
            }

            // ... see if any dependency fields are remapped
            var remappedViewFields = type.GetCustomAttributes(typeof(RemappedField), true).Cast <RemappedField>();

            foreach (var remappedViewField in remappedViewFields)
            {
                // add or update mapping of old dependency field so it points to the new one
                var mappedDependencyFieldData = viewTypeData.MapViewFields.FirstOrDefault(x => String.Equals(x.From, remappedViewField.MapFieldData.From, StringComparison.OrdinalIgnoreCase));
                if (mappedDependencyFieldData != null)
                {
                    // update so it maps to the new dependency field
                    mappedDependencyFieldData.To = remappedViewField.MapFieldData.To;
                    mappedDependencyFieldData.ValueConverterType              = remappedViewField.MapFieldData.ValueConverterType;
                    mappedDependencyFieldData.ValueConverterTypeSet           = remappedViewField.MapFieldData.ValueConverterTypeSet;
                    mappedDependencyFieldData.ChangeHandlerName               = remappedViewField.MapFieldData.ChangeHandlerName;
                    mappedDependencyFieldData.ChangeHandlerNameSet            = remappedViewField.MapFieldData.ChangeHandlerNameSet;
                    mappedDependencyFieldData.TriggerChangeHandlerImmediately = remappedViewField.MapFieldData.TriggerChangeHandlerImmediately;
                }
                else
                {
                    // add new mapped value
                    viewTypeData.MapViewFields.Add(remappedViewField.MapFieldData);
                }
            }

            //  .. init change handlers and value converters
            foreach (var mapField in viewTypeData.MapViewFields)
            {
                if (mapField.ValueConverterTypeSet)
                {
                    viewTypeData.ViewFieldConverters.Add(new ViewFieldConverterData {
                        ValueConverterType = mapField.ValueConverterType, ViewField = mapField.To
                    });
                }

                if (mapField.ChangeHandlerNameSet)
                {
                    viewTypeData.ViewFieldChangeHandlers.Add(new ViewFieldChangeHandler
                    {
                        ChangeHandlerName  = mapField.ChangeHandlerName,
                        ViewField          = mapField.To,
                        TriggerImmediately = mapField.TriggerChangeHandlerImmediately
                    });
                }
            }

            // set view field converters and change handlers
            foreach (var field in typeFields)
            {
                var valueConverter = field.GetCustomAttributes(typeof(ValueConverter), true).FirstOrDefault();
                if (valueConverter != null)
                {
                    viewTypeData.ViewFieldConverters.Add(new ViewFieldConverterData {
                        ViewField = field.Name, ValueConverterType = valueConverter.GetType().Name
                    });
                }

                var changeHandler = field.GetCustomAttributes(typeof(ChangeHandler), true).FirstOrDefault() as ChangeHandler;
                if (changeHandler != null)
                {
                    viewTypeData.ViewFieldChangeHandlers.Add(new ViewFieldChangeHandler {
                        ViewField = field.Name, ChangeHandlerName = changeHandler.Name, TriggerImmediately = changeHandler.TriggerImmediately
                    });
                }

                var notNotSetFromXuml = field.GetCustomAttributes(typeof(NotSetFromXuml), true).FirstOrDefault() as NotSetFromXuml;
                if (notNotSetFromXuml != null)
                {
                    viewTypeData.FieldsNotSetFromXuml.Add(field.Name);
                }

                var genericViewField = field.GetCustomAttributes(typeof(GenericViewField), true).FirstOrDefault();
                if (genericViewField != null)
                {
                    viewTypeData.GenericViewFields.Add(field.Name);
                }

                // see if any component fields are replaced
                var replacedComponentField = field.GetCustomAttributes(typeof(ReplacesComponentField), true).FirstOrDefault() as ReplacesComponentField;
                if (replacedComponentField != null)
                {
                    // when a component field is replaced we need to update the mappings of other fields so they point to the new component
                    foreach (var mappedField in viewTypeData.MapViewFields)
                    {
                        int indexOf = mappedField.To.IndexOf(replacedComponentField.ReplacedComponentField);
                        if (indexOf != 0)
                        {
                            continue;
                        }

                        mappedField.To = mappedField.To.ReplaceFirst(replacedComponentField.ReplacedComponentField, field.Name);
                    }
                }

                // see if any dependency fields are replaced
                var replacedViewField = field.GetCustomAttributes(typeof(ReplacesDependencyField), true).FirstOrDefault() as ReplacesDependencyField;
                if (replacedViewField != null)
                {
                    // add or update mapping of old dependency field so it points to the new one
                    var mappedDependencyFieldData = viewTypeData.MapViewFields.FirstOrDefault(x => String.Equals(x.From, field.Name, StringComparison.OrdinalIgnoreCase));
                    if (mappedDependencyFieldData != null)
                    {
                        var oldMappedDependencyFieldData = viewTypeData.MapViewFields.FirstOrDefault(x => String.Equals(x.From, replacedViewField.ReplacedDependencyField, StringComparison.OrdinalIgnoreCase));
                        if (oldMappedDependencyFieldData != null)
                        {
                            // update so it maps to the new dependency field
                            oldMappedDependencyFieldData.To = mappedDependencyFieldData.To;
                            oldMappedDependencyFieldData.ValueConverterType              = mappedDependencyFieldData.ValueConverterType;
                            oldMappedDependencyFieldData.ValueConverterTypeSet           = mappedDependencyFieldData.ValueConverterTypeSet;
                            oldMappedDependencyFieldData.ChangeHandlerName               = mappedDependencyFieldData.ChangeHandlerName;
                            oldMappedDependencyFieldData.ChangeHandlerNameSet            = mappedDependencyFieldData.ChangeHandlerNameSet;
                            oldMappedDependencyFieldData.TriggerChangeHandlerImmediately = mappedDependencyFieldData.TriggerChangeHandlerImmediately;
                        }
                        else
                        {
                            // add new mapped value
                            var mapViewField = new MapViewFieldData();
                            mapViewField.From = replacedViewField.ReplacedDependencyField;
                            mapViewField.To   = mappedDependencyFieldData.To;
                            mapViewField.ValueConverterType              = mappedDependencyFieldData.ValueConverterType;
                            mapViewField.ValueConverterTypeSet           = mappedDependencyFieldData.ValueConverterTypeSet;
                            mapViewField.ChangeHandlerName               = mappedDependencyFieldData.ChangeHandlerName;
                            mapViewField.ChangeHandlerNameSet            = mappedDependencyFieldData.ChangeHandlerNameSet;
                            mapViewField.TriggerChangeHandlerImmediately = mappedDependencyFieldData.TriggerChangeHandlerImmediately;
                            viewTypeData.MapViewFields.Add(mapViewField);
                        }
                    }
                }
            }

            // get the normal fields that aren't mapped
            var fields = typeFields.Where(x =>
                                          !viewTypeData.FieldsNotSetFromXuml.Contains(x.Name) &&
                                          !viewTypeData.ReferenceFields.Contains(x.Name) &&
                                          !viewTypeData.ComponentFields.Contains(x.Name) &&
                                          !viewTypeData.ViewActionFields.Contains(x.Name) &&
                                          !viewTypeData.DependencyFields.Contains(x.Name) &&
                                          !x.IsStatic
                                          ).Select(y => y.Name);
            var properties = type.GetProperties().Where(x =>
                                                        !viewTypeData.FieldsNotSetFromXuml.Contains(x.Name) &&
                                                        !viewTypeData.ReferenceFields.Contains(x.Name) &&
                                                        !viewTypeData.ComponentFields.Contains(x.Name) &&
                                                        !viewTypeData.ViewActionFields.Contains(x.Name) &&
                                                        !viewTypeData.DependencyFields.Contains(x.Name) &&
#if !UNITY_WINRT || UNITY_WINRT_10_0 || UNITY_EDITOR
                                                        x.GetSetMethod() != null &&
                                                        x.GetGetMethod() != null &&
#endif
                                                        x.Name != "enabled" &&
                                                        x.Name != "useGUILayout" &&
                                                        x.Name != "tag" &&
                                                        x.Name != "hideFlags" &&
                                                        x.Name != "name"
                                                        ).Select(y => y.Name);

            viewTypeData.ViewFields.AddRange(fields);
            viewTypeData.ViewFields.AddRange(properties);
        }