using System; using System.Collections.Generic; using System.Linq.Expressions; using System.Linq; using System.Globalization; using System.ComponentModel; using System.Collections; namespace LeanCloud.Storage.Internal { /// /// So here's the deal. We have a lot of internal APIs for AVObject, AVUser, etc. /// /// These cannot be 'internal' anymore if we are fully modularizing things out, because /// they are no longer a part of the same library, especially as we create things like /// Installation inside push library. /// /// So this class contains a bunch of extension methods that can live inside another /// namespace, which 'wrap' the intenral APIs that already exist. /// public static class AVObjectExtensions { public static T FromState(IObjectState state, string defaultClassName) where T : AVObject { return AVObject.FromState(state, defaultClassName); } public static IObjectState GetState(this AVObject obj) { return obj.State; } public static void HandleFetchResult(this AVObject obj, IObjectState serverState) { obj.HandleFetchResult(serverState); } public static IDictionary GetCurrentOperations(this AVObject obj) { return obj.CurrentOperations; } public static IDictionary Encode(this AVObject obj) { return PointerOrLocalIdEncoder.Instance.EncodeAVObject(obj, false); } public static IEnumerable DeepTraversal(object root, bool traverseAVObjects = false, bool yieldRoot = false) { return AVObject.DeepTraversal(root, traverseAVObjects, yieldRoot); } public static void SetIfDifferent(this AVObject obj, string key, T value) { obj.SetIfDifferent(key, value); } public static IDictionary ServerDataToJSONObjectForSerialization(this AVObject obj) { return obj.ServerDataToJSONObjectForSerialization(); } public static void Set(this AVObject obj, string key, object value) { obj.Set(key, value); } public static void DisableHooks(this AVObject obj, IEnumerable hookKeys) { obj.Set("__ignore_hooks", hookKeys); } public static void DisableHook(this AVObject obj, string hookKey) { var newList = new List(); if (obj.ContainsKey("__ignore_hooks")) { var hookKeys = obj.Get>("__ignore_hooks"); newList = hookKeys.ToList(); } newList.Add(hookKey); obj.DisableHooks(newList); } public static void DisableAfterHook(this AVObject obj) { obj.DisableAfterSave(); obj.DisableAfterUpdate(); obj.DisableAfterDelete(); } public static void DisableBeforeHook(this AVObject obj) { obj.DisableBeforeSave(); obj.DisableBeforeDelete(); obj.DisableBeforeUpdate(); } public static void DisableBeforeSave(this AVObject obj) { obj.DisableHook("beforeSave"); } public static void DisableAfterSave(this AVObject obj) { obj.DisableHook("afterSave"); } public static void DisableBeforeUpdate(this AVObject obj) { obj.DisableHook("beforeUpdate"); } public static void DisableAfterUpdate(this AVObject obj) { obj.DisableHook("afterUpdate"); } public static void DisableBeforeDelete(this AVObject obj) { obj.DisableHook("beforeDelete"); } public static void DisableAfterDelete(this AVObject obj) { obj.DisableHook("afterDelete"); } #region on property updated or changed or collection updated /// /// On the property changed. /// /// Av object. /// Property name. /// Handler. public static void OnPropertyChanged(this AVObject avObj, string propertyName, PropertyChangedEventHandler handler) { avObj.PropertyChanged += (sender, e) => { if (e.PropertyName == propertyName) { handler(sender, e); } }; } /// /// On the property updated. /// /// Av object. /// Property name. /// Handler. public static void OnPropertyUpdated(this AVObject avObj, string propertyName, PropertyUpdatedEventHandler handler) { avObj.PropertyUpdated += (sender, e) => { if (e.PropertyName == propertyName) { handler(sender, e); } }; } /// /// On the property updated. /// /// Av object. /// Property name. /// Handler. public static void OnPropertyUpdated(this AVObject avObj, string propertyName, Action handler) { avObj.OnPropertyUpdated(propertyName,(object sender, PropertyUpdatedEventArgs e) => { handler(e.OldValue, e.NewValue); }); } /// /// On the collection property updated. /// /// Av object. /// Property name. /// Handler. public static void OnCollectionPropertyUpdated(this AVObject avObj, string propertyName, CollectionPropertyUpdatedEventHandler handler) { avObj.CollectionPropertyUpdated += (sender, e) => { if (e.PropertyName == propertyName) { handler(sender, e); } }; } /// /// On the collection property added. /// /// Av object. /// Property name. /// Handler. public static void OnCollectionPropertyAdded(this AVObject avObj, string propertyName, Action handler) { avObj.OnCollectionPropertyUpdated(propertyName, (sender, e) => { if (e.CollectionAction == NotifyCollectionUpdatedAction.Add) { handler(e.NewValues); } }); } /// /// On the collection property removed. /// /// Av object. /// Property name. /// Handler. public static void OnCollectionPropertyRemoved(this AVObject avObj, string propertyName, Action handler) { avObj.OnCollectionPropertyUpdated(propertyName, (sender, e) => { if (e.CollectionAction == NotifyCollectionUpdatedAction.Remove) { handler(e.NewValues); } }); } #endregion } }