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