/// <summary> /// Pads the generic IList. /// </summary> /// <param name="list">The list.</param> /// <param name="property">The property.</param> /// <param name="toIndex">To index.</param> private void PadGenericIList(object list, ControllerProperty property, int toIndex) { while (property.GenericIListCount(list) < toIndex) { property.GenericIListAdd(list, GetDefaultValue(property.GenericIListType)); } }
/// <summary> /// Removes the observable collection. /// </summary> /// <param name="property">The property.</param> private void RemoveObservableCollection(ControllerProperty property) { if (property.ObservableCollection != null) { property.ObservableCollection.CollectionChanged -= property.NotifyCollectionChangedEventHandler; } property.NotifyCollectionChangedEventHandler = null; property.ObservableCollection = null; }
/// <summary> /// Adds the observable collection. /// </summary> /// <param name="property">The property.</param> /// <returns></returns> private void AddObservableCollection(ControllerProperty property) { RemoveObservableCollection(property); property.ObservableCollection = (INotifyCollectionChanged)property.GetDelegate.DynamicInvoke(this); if (property.ObservableCollection != null) { property.NotifyCollectionChangedEventHandler = new NotifyCollectionChangedEventHandler((sender, e) => { CollectionChangedHandle(sender, e, property); }); property.ObservableCollection.CollectionChanged += property.NotifyCollectionChangedEventHandler; } }
/// <summary> /// Sets the property value. /// </summary> /// <param name="property">The property.</param> /// <param name="value">The value.</param> /// <param name="sync">if set to <c>true</c> synchronize changes.</param> private void SetPropertyValueInternal(ControllerProperty property, object value, bool sync) { try { SyncChanges = sync; property.SetDelegate.DynamicInvoke(this, value); } finally { SyncChanges = true; } }
/// <summary> /// Adds the generic IList info. /// </summary> /// <param name="property">The property.</param> private void AddGenericIListInfo(ControllerProperty property) { property.GenericIListAddDelegate = ExpressionUtility.CreateMethodDelegate(property.PropertyType.GetMethod("Add")); property.GenericIListRemoveAtDelegate = ExpressionUtility.CreateMethodDelegate(property.PropertyType.GetMethod("RemoveAt")); property.GenericIListCountDelegate = ExpressionUtility.CreateMethodDelegate(property.PropertyType.GetProperty("Count").GetGetMethod()); property.GenericIListInsertDelegate = ExpressionUtility.CreateMethodDelegate(property.PropertyType.GetMethod("Insert")); var indexMethod = property.PropertyType.GetProperties() .Single(p => p.GetIndexParameters().Length == 1 && p.GetIndexParameters()[0].ParameterType == typeof(int)) .GetSetMethod(false); property.GenericIListReplaceDelegate = ExpressionUtility.CreateMethodDelegate(indexMethod); property.GenericIListType = property.PropertyType.GetGenericArguments()[0]; }
/// <summary> /// Sets the Array changes. /// </summary> /// <param name="array">The array.</param> /// <param name="property">The property.</param> /// <param name="changes">The changes.</param> /// <param name="sync">if set to <c>true</c> synchronize changes.</param> private void SetArrayChanges(Array array, ControllerProperty property, ObservableCollectionChanges changes, bool sync) { // TODO; fix throw exceptions try { SyncChanges = sync; foreach (var change in changes.Actions) { if (change.Action == ObservableCollectionChangeAction.Add) { throw new PropertyMismatchException(Name, property.Name, string.Format("{0}/{1}", typeof(IList).Name, typeof(IList <>).Name), property.PropertyType.Name); } else if (change.Action == ObservableCollectionChangeAction.Remove) { throw new PropertyMismatchException(Name, property.Name, string.Format("{0}/{1}", typeof(IList).Name, typeof(IList <>).Name), property.PropertyType.Name); } else if (change.Action == ObservableCollectionChangeAction.Replace) { var startIndex = change.NewStartingIndex.Value; foreach (var item in change.NewItems) { if (startIndex >= array.Length) { throw new PropertyMismatchException(Name, property.Name, string.Format("{0}/{1}", typeof(IList).Name, typeof(IList <>).Name), property.PropertyType.Name); } array.SetValue(item.ToObject(property.ArrayType), startIndex); startIndex++; } } } } finally { SyncChanges = true; } }
/// <summary> /// Finds the property. /// </summary> /// <param name="propertyName">Name of the property.</param> /// <returns></returns> private ControllerProperty FindProperty(string propertyName) { ControllerProperty property = null; if (ObservableControllerTypeInfo.Properties.TryGetValue(propertyName, out property)) { return(property); } if (ObservableControllerTypeInfo.Properties.TryGetValue(StringUtility.PascalCase(propertyName), out property)) { return(property); } if (ObservableControllerTypeInfo.Properties.TryGetValue(StringUtility.CamelCase(propertyName), out property)) { return(property); } return(null); }
private void CollectionChangedHandle(object sender, NotifyCollectionChangedEventArgs e, ControllerProperty property) { if (!SyncChanges) { return; } if (!ObservableCollectionChanges.ContainsKey(property.Name)) { ObservableCollectionChanges.Add(property.Name, new ObservableCollectionChanges { Name = property.Name }); } var changes = ObservableCollectionChanges[property.Name]; if (!changes.IsReset) { switch (e.Action) { case NotifyCollectionChangedAction.Add: changes.Actions.Add(new ObservableCollectionChange { NewItems = new JArray(e.NewItems), NewStartingIndex = e.NewStartingIndex, Action = ObservableCollectionChangeAction.Add }); break; case NotifyCollectionChangedAction.Move: changes.Actions.Add(new ObservableCollectionChange { OldStartingIndex = e.OldStartingIndex, NewStartingIndex = e.NewStartingIndex, Action = ObservableCollectionChangeAction.Move }); break; case NotifyCollectionChangedAction.Remove: changes.Actions.Add(new ObservableCollectionChange { OldStartingIndex = e.OldStartingIndex, Action = ObservableCollectionChangeAction.Remove }); break; case NotifyCollectionChangedAction.Replace: changes.Actions.Add(new ObservableCollectionChange { NewItems = new JArray(e.NewItems), NewStartingIndex = e.NewStartingIndex, Action = ObservableCollectionChangeAction.Replace }); break; case NotifyCollectionChangedAction.Reset: changes.Actions = new List <ObservableCollectionChange>(); changes.IsReset = true; break; } } }
/// <summary> /// Sets the generic IList changes. /// </summary> /// <param name="list">The list.</param> /// <param name="property">The property.</param> /// <param name="changes">The changes.</param> /// <param name="sync">if set to <c>true</c> synchronize changes.</param> private void SetGenericIListChanges(object list, ControllerProperty property, ObservableCollectionChanges changes, bool sync) { try { SyncChanges = sync; foreach (var change in changes.Actions) { if (change.Action == ObservableCollectionChangeAction.Add) { var startIndex = change.NewStartingIndex.Value; foreach (var item in change.NewItems) { PadGenericIList(list, property, startIndex); if (startIndex >= property.GenericIListCount(list)) { property.GenericIListAdd(list, item.ToObject(property.GenericIListType)); } else { property.GenericIListInsert(list, startIndex, item.ToObject(property.GenericIListType)); } startIndex++; } } else if (change.Action == ObservableCollectionChangeAction.Remove) { var removeIndex = change.OldStartingIndex.Value; if (property.GenericIListCount(list) > removeIndex) { property.GenericIListRemoveAt(list, removeIndex); } } else if (change.Action == ObservableCollectionChangeAction.Replace) { var startIndex = change.NewStartingIndex.Value; foreach (var item in change.NewItems) { PadGenericIList(list, property, startIndex); if (startIndex >= property.GenericIListCount(list)) { property.GenericIListAdd(list, item.ToObject(property.GenericIListType)); } else { property.GenericIListReplace(list, startIndex, item.ToObject(property.GenericIListType)); } startIndex++; } } } } finally { SyncChanges = true; } }
/// <summary> /// Sets the IList changes. /// </summary> /// <param name="list">The list.</param> /// <param name="property">The property.</param> /// <param name="changes">The changes.</param> /// <param name="sync">if set to <c>true</c> synchronize changes.</param> private void SetIListChanges(IList list, ControllerProperty property, ObservableCollectionChanges changes, bool sync) { try { SyncChanges = sync; var itemType = property.IsGenericIList ? property.GenericIListType : typeof(object); foreach (var change in changes.Actions) { if (change.Action == ObservableCollectionChangeAction.Add) { var startIndex = change.NewStartingIndex.Value; foreach (var item in change.NewItems) { PadIList(list, startIndex, itemType); if (startIndex >= list.Count) { list.Add(item.ToObject(itemType)); } else { list.Insert(startIndex, item.ToObject(itemType)); } startIndex++; } } else if (change.Action == ObservableCollectionChangeAction.Remove) { var removeIndex = change.OldStartingIndex.Value; if (list.Count > removeIndex) { list.RemoveAt(removeIndex); } } else if (change.Action == ObservableCollectionChangeAction.Replace) { var startIndex = change.NewStartingIndex.Value; foreach (var item in change.NewItems) { PadIList(list, startIndex, itemType); if (startIndex >= list.Count) { list.Add(item.ToObject(itemType)); } else { list[startIndex] = item.ToObject(itemType); } startIndex++; } } } } finally { SyncChanges = true; } }
/// <summary> /// Adds the array information. /// </summary> /// <param name="property">The property.</param> private void AddArrayInfo(ControllerProperty property) { property.ArrayType = property.PropertyType.GetElementType(); }
/// <summary> /// Finds the properties. /// </summary> /// <param name="type">The type.</param> /// <returns></returns> private Dictionary <string, ControllerProperty> FindProperties(Type type) { var properties = new Dictionary <string, ControllerProperty>(); foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { // ignore properties with exclude attribute if (property.GetCustomAttribute <ExcludeAttribute>() == null) { var getMethod = property.GetGetMethod(false); var setMethod = property.GetSetMethod(false); Access?access = null; // access if (property.CanRead && getMethod != null && property.CanWrite && setMethod != null) { access = Access.Read | Access.Write; } else if (property.CanRead && getMethod != null) { access = Access.Read; } else if (property.CanWrite && setMethod != null) { access = Access.Write; } // add if (access != null) { var controllerProperty = new ControllerProperty { Name = property.Name, PropertyType = property.PropertyType, IsObservableCollection = IsObservableCollection(property.PropertyType), IsCollection = IsCollection(property.PropertyType), IsIList = IsIList(property.PropertyType), IsGenericIList = IsGenericIList(property.PropertyType), IsArray = property.PropertyType.IsArray, GetDelegate = getMethod != null?ExpressionUtility.CreateMethodDelegate(getMethod) : null, SetDelegate = setMethod != null?ExpressionUtility.CreateMethodDelegate(setMethod) : null, Access = access.Value }; if (controllerProperty.IsArray) { AddArrayInfo(controllerProperty); } if (controllerProperty.IsGenericIList) { AddGenericIListInfo(controllerProperty); } if (controllerProperty.IsObservableCollection) { AddObservableCollection(controllerProperty); } properties.Add(controllerProperty.Name, controllerProperty); } } } return(properties); }