internal IBindingTypeConverter GetConverterForTypes(Type lhs, Type rhs) { lock (_typeConverterCache) { return(_typeConverterCache.Get(Tuple.Create(lhs, rhs))); } }
/// <inheritdoc/> public int GetAffinityForObject(Type type, string propertyName, bool beforeChanged = false) { lock (declaredInNSObject) { return(declaredInNSObject.Get(Tuple.Create(type, propertyName)) ? 15 : 0); } }
public static IDisposable BindCommandToObject(ICommand command, object target, IObservable <object> commandParameter, string eventName) { var type = target.GetType(); var binder = bindCommandEventCache.Get(type); if (binder == null) { throw new Exception(String.Format("Couldn't find a Command Binder for {0} and event {1}", type.FullName, eventName)); } var eventArgsType = Reflection.GetEventArgsTypeForEvent(type, eventName); var mi = binder.GetType().GetTypeInfo().DeclaredMethods.First(x => x.Name == "BindCommandToObject" && x.IsGenericMethod); mi = mi.MakeGenericMethod(new[] { eventArgsType }); //var ret = binder.BindCommandToObject<TEventArgs>(command, target, commandParameter, eventName); var ret = (IDisposable)mi.Invoke(binder, new[] { command, target, commandParameter, eventName }); if (ret == null) { throw new Exception(String.Format("Couldn't bind Command Binder for {0} and event {1}", type.FullName, eventName)); } return(ret); }
string getPropertyValidationError(string propName) { PropertyExtraInfo pei; lock (allValidatedProperties) { if (!allValidatedProperties.Get(this.GetType()).TryGetValue(propName, out pei)) { return(null); } } foreach (var v in pei.ValidationAttributes) { try { var ctx = new ValidationContext(this, null, null) { MemberName = propName }; var pi = RxApp.getPropertyInfoForProperty(pei.Type, propName); v.Validate(pi.GetValue(this, null), ctx); } catch (Exception ex) { this.Log().InfoFormat("{0:X}.{1} failed validation: {2}", this.GetHashCode(), propName, ex.Message); return(ex.Message); } } return(null); }
public static Action <object, object> GetValueSetterForProperty(Type type, string propName) { Contract.Requires(type != null); Contract.Requires(propName != null); lock (propReaderCache) { return(propWriterCache.Get(Tuple.Create(type, propName))); } }
public bool TryConvert(object from, Type toType, object conversionHint, out object result) { Contract.Requires(toType != null); var mi = referenceCastCache.Get(toType); result = mi.Invoke(null, new[] { from }); return(true); }
public static IRxUIFullLogger GetLogger(Type type) { if (type == typeof(MemoizingMRUCache <Type, IRxUIFullLogger>)) { return(nullLogger); } lock (loggerCache) { return(loggerCache.Get(type)); } }
/// <summary> /// Gets a Type from the specified type name. /// Uses a cache to avoid having to use Reflection every time. /// </summary> /// <param name="type">The name of the type.</param> /// <param name="throwOnFailure">If we should throw an exception if the type can't be found.</param> /// <returns>The type that was found or null.</returns> /// <exception cref="TypeLoadException">If we were unable to find the type.</exception> public static Type ReallyFindType(string type, bool throwOnFailure) { Type ret = typeCache.Get(type); if (ret != null || !throwOnFailure) { return(ret); } throw new TypeLoadException(); }
internal static Type reallyFindType(string type, bool throwOnFailure) { lock (typeCache) { var ret = typeCache.Get(type); if (ret != null || !throwOnFailure) { return(ret); } throw new TypeLoadException(); } }
internal static PropertyInfo getPropertyInfoForProperty(Type type, string prop_name) { Contract.Requires(prop_name != null); PropertyInfo pi; #if SILVERLIGHT lock (propInfoTypeCache) { pi = propInfoTypeCache.Get(new Tuple <Type, string>(type, prop_name)); } #else pi = propInfoTypeCache.Get(new Tuple <Type, string>(type, prop_name)); #endif if (pi == null) { throw new ArgumentException("You must declare a property named: " + prop_name); } return(pi); }
/// <summary> /// Log returns the current logger object, which allows the object to /// log messages with the type name attached. /// </summary> /// <returns></returns> public static ILog Log(this IEnableLogger This) { // Prevent recursive meta-logging if (This is MemoizingMRUCache <int, ILog> ) { return(mruLogger); } lock (loggerCache) { return(loggerCache.Get(This.GetHashCode(), This)); } }
private static IObservable <IObservedChange <object, object> > NotifyForProperty(object sender, Expression expression, bool beforeChange, bool suppressWarnings) { var propertyName = expression.GetMemberInfo().Name; var result = notifyFactoryCache.Get(Tuple.Create(sender.GetType(), propertyName, beforeChange)); if (result == null) { throw new Exception($"Could not find a ICreatesObservableForProperty for {sender.GetType()} property {propertyName}. This should never happen, your service locator is probably broken. Please make sure you have installed the latest version of the ReactiveUI packages for your platform. See https://reactiveui.net/docs/getting-started/installation/nuget-packages for guidance."); } return(result.GetNotificationForProperty(sender, expression, propertyName, beforeChange, suppressWarnings)); }
static IObservable <IObservedChange <object, object> > notifyForProperty(object sender, string propertyName, bool beforeChange) { var result = notifyFactoryCache.Get(sender.GetType()); if (result == null) { throw new Exception( String.Format("Couldn't find a ICreatesObservableForProperty for {0}. This should never happen, your service locator is probably broken.", sender.GetType())); } return(result.GetNotificationForProperty(sender, propertyName, beforeChange)); }
public IFullLogger GetLogger(Type type) { if (RxApp.suppressLogging) { return(nullLogger); } if (type == typeof(MemoizingMRUCache <Type, IFullLogger>)) { return(nullLogger); } lock (loggerCache) { return(loggerCache.Get(type)); } }
static IObservable <IObservedChange <object, object> > notifyForProperty(object sender, Expression expression, bool beforeChange) { var result = default(ICreatesObservableForProperty); lock (notifyFactoryCache) { result = notifyFactoryCache.Get(Tuple.Create(sender.GetType(), expression.GetMemberInfo().Name, beforeChange)); } if (result == null) { throw new Exception( String.Format("Couldn't find a ICreatesObservableForProperty for {0}. This should never happen, your service locator is probably broken.", sender.GetType())); } return(result.GetNotificationForProperty(sender, expression, beforeChange)); }
internal static FieldInfo getFieldInfoForProperty <TObj>(string prop_name) where TObj : IReactiveNotifyPropertyChanged { Contract.Requires(prop_name != null); FieldInfo field; lock (fieldInfoTypeCache) { field = fieldInfoTypeCache.Get(new Tuple <Type, string>(typeof(TObj), prop_name)); } if (field == null) { throw new ArgumentException("You must declare a backing field for this property named: " + RxApp.GetFieldNameForProperty(prop_name)); } return(field); }
/// <summary> /// AutoPersist allows you to automatically call a method when an object /// has changed, throttling on a certain interval. Note that this object /// must mark its persistable properties via the [DataMember] attribute. /// Changes to properties not marked with DataMember will not trigger the /// object to be saved. /// </summary> /// <typeparam name="T">The reactive object type.</typeparam> /// <typeparam name="TDontCare">The save signal type.</typeparam> /// <param name="this"> /// The reactive object to watch for changes. /// </param> /// <param name="doPersist"> /// The asynchronous method to call to save the object to disk. /// </param> /// <param name="manualSaveSignal"> /// When invoked, the object will be saved regardless of whether it has changed. /// </param> /// <param name="interval"> /// The interval to save the object on. Note that if an object is constantly changing, /// it is possible that it will never be saved. /// </param> /// <returns>A Disposable to disable automatic persistence.</returns> public static IDisposable AutoPersist <T, TDontCare>(this T @this, Func <T, IObservable <Unit> > doPersist, IObservable <TDontCare> manualSaveSignal, TimeSpan?interval = null) where T : IReactiveObject { interval = interval ?? TimeSpan.FromSeconds(3.0); lock (dataContractCheckCache) { if (!dataContractCheckCache.Get(@this.GetType())) { throw new ArgumentException("AutoPersist can only be applied to objects with [DataContract]"); } } Dictionary <string, bool> persistableProperties; lock (persistablePropertiesCache) { persistableProperties = persistablePropertiesCache.Get(@this.GetType()); } var saveHint = Observable.Merge( @this.GetChangedObservable().Where(x => persistableProperties.ContainsKey(x.PropertyName)).Select(_ => Unit.Default), manualSaveSignal.Select(_ => Unit.Default)); var autoSaver = saveHint .Throttle(interval.Value, RxApp.TaskpoolScheduler) .SelectMany(_ => doPersist(@this)) .Publish(); // NB: This rigamarole is to prevent the initialization of a class // from triggering a save var ret = new SingleAssignmentDisposable(); RxApp.MainThreadScheduler.Schedule(() => { if (ret.IsDisposed) { return; } ret.Disposable = autoSaver.Connect(); }); return(ret); }
public bool TryConvert(object from, Type toType, object conversionHint, out object result) { Contract.Requires(toType != null); var mi = default(MethodInfo); lock (referenceCastCache) { mi = referenceCastCache.Get(toType); } try { result = mi.Invoke(null, new[] { from }); } catch (Exception ex) { this.Log().WarnException("Couldn't convert object to type: " + toType, ex); result = null; return(false); } return(true); }
/// <summary> /// Issues an request to fetch the value for the specified key as an /// async operation. The Observable returned will fire one time when the /// async operation finishes. If the operation is cached, an Observable /// that immediately fires upon subscribing will be returned. /// </summary> /// <param name="key">The key to provide to the calculation function.</param> /// <returns>Returns an Observable representing the future result.</returns> public IObservable <TVal> AsyncGet(TParam key) { IObservable <TVal> result; int myCall; var rs = new ReplaySubject <TVal>(); lock (_innerCache) { if (_innerCache.TryGet(key, out result)) { this.Log().Debug("Cache hit: '{0}'", key); return(result); } myCall = Interlocked.Increment(ref currentCall); _callQueue.Where(x => x == myCall).Subscribe(_ => { this.Log().Debug("Dispatching '{0}'", key); IObservable <TVal> fetched = null; try { fetched = _fetcher(key); } catch (Exception ex) { _callQueue.Release(); rs.OnError(ex); return; } fetched.Subscribe(x => { rs.OnNext(x); }, ex => { _callQueue.Release(); rs.OnError(ex); }, () => { _callQueue.Release(); rs.OnCompleted(); }); }); _innerCache.Get(key, rs); } _callQueue.OnNext(myCall); return(rs); }
/// <inheritdoc/> public bool TryConvert(object from, Type toType, object conversionHint, out object result) { Contract.Requires(toType != null); var mi = _referenceCastCache.Get(toType); try { result = mi.Invoke(null, new[] { from, toType }); } catch (Exception ex) { this.Log().Warn(ex, "Couldn't convert object to type: " + toType); result = null; return(false); } return(true); }
public static IDisposable BindCommandToObject(ICommand command, object target, IObservable <object> commandParameter) { var type = target.GetType(); var binder = bindCommandCache.Get(type); if (binder == null) { throw new Exception($"Couldn't find a Command Binder for {type.FullName}"); } var ret = binder.BindCommandToObject(command, target, commandParameter); if (ret == null) { throw new Exception($"Couldn't bind Command Binder for {type.FullName}"); } return(ret); }
static IReactiveNotifyPropertyChanged wrapInpcObjectIfNeeded(object obj) { if (obj == null) { return(null); } var ret = obj as IReactiveNotifyPropertyChanged; if (ret != null) { return(ret); } var inpc = obj as INotifyPropertyChanged; if (inpc != null) { return(wrapperCache.Get(inpc)); } return(null); }
public static IDisposable BindCommandToObject(ICommand command, object target, IObservable <object> commandParameter) { var binder = default(ICreatesCommandBinding); var type = target.GetType(); lock (bindCommandCache) { binder = bindCommandCache.Get(type); } if (binder == null) { throw new Exception(String.Format("Couldn't find a Command Binder for {0}", type.FullName)); } var ret = binder.BindCommandToObject(command, target, commandParameter); if (ret == null) { throw new Exception(String.Format("Couldn't bind Command Binder for {0}", type.FullName)); } return(ret); }
/// <summary> /// WhenActivated allows you to register a Func to be called when a /// View is Activated. /// </summary> /// <param name="this">Object that supports activation.</param> /// <param name="block"> /// The method to be called when the corresponding /// View is activated. It returns a list of Disposables that will be /// cleaned up when the View is deactivated. /// </param> /// <param name="view"> /// The IActivatable will ordinarily also host the View /// Model, but in the event it is not, a class implementing <see cref="IViewFor" /> /// can be supplied here. /// </param> /// <returns>A Disposable that deactivates this registration.</returns> public static IDisposable WhenActivated(this IActivatable @this, Func <IEnumerable <IDisposable> > block, IViewFor view) { var activationFetcher = activationFetcherCache.Get(@this.GetType()); if (activationFetcher == null) { const string msg = "Don't know how to detect when {0} is activated/deactivated, you may need to implement IActivationForViewFetcher"; throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, msg, @this.GetType().FullName)); } var activationEvents = activationFetcher.GetActivationForView(@this); var vmDisposable = Disposable.Empty; if ((view ?? @this) is IViewFor v) { vmDisposable = HandleViewModelActivation(v, activationEvents); } var viewDisposable = HandleViewActivation(block, activationEvents); return(new CompositeDisposable(vmDisposable, viewDisposable)); }
/// <summary> /// Attempts to return the current value of a property given a /// notification that it has changed. If any property in the /// property expression is null, false is returned. /// </summary> /// <param name="changeValue">The value of the property expression.</param> /// <returns>True if the entire expression was able to be followed, false otherwise</returns> public static bool TryGetValue <TSender, TValue>(this IObservedChange <TSender, TValue> This, out TValue changeValue) { if (!Equals(This.Value, default(TValue))) { changeValue = This.Value; return(true); } object current = This.Sender; string[] propNames = null; lock (propStringToNameCache) { propNames = propStringToNameCache.Get(This.PropertyName); } PropertyInfo pi; foreach (var propName in propNames.SkipLast(1)) { if (current == null) { changeValue = default(TValue); return(false); } pi = RxApp.getPropertyInfoOrThrow(current.GetType(), propName); current = pi.GetValue(current, null); } if (current == null) { changeValue = default(TValue); return(false); } pi = RxApp.getPropertyInfoOrThrow(current.GetType(), propNames.Last()); changeValue = (TValue)pi.GetValue(current, null); return(true); }
public int GetAffinityForObjects(Type lhs, Type rhs) { var converter = typeConverterCache.Get(Tuple.Create(lhs, rhs)); return(converter != null ? 10 : 0); }
IBindingTypeConverter getConverterForTypes(Type lhs, Type rhs) { return(typeConverterCache.Get(Tuple.Create(lhs, rhs))); }
/// <inheritdoc/> public int GetAffinityForObjects(Type fromType, Type toType) { var converter = _typeConverterCache.Get(Tuple.Create(fromType, toType)); return(converter != null ? 10 : 0); }