static ReactiveNotifyPropertyChangedMixin() { RxApp.EnsureInitialized(); }
/// <summary> /// RaisePropertyChanging is a helper method intended for test / mock /// scenarios to manually fake a property change. /// </summary> /// <param name="target">The ReactiveObject to invoke /// raisePropertyChanging on.</param> /// <param name="property">The property that will be faking a change.</param> public static void RaisePropertyChanging <TSender, TValue>(TSender target, Expression <Func <TSender, TValue> > property) where TSender : ReactiveObject { RaisePropertyChanging(target, RxApp.simpleExpressionToPropertyName(property)); }
/// <summary> /// Initializes static members of the <see cref="RoutingState"/> class. /// </summary> static RoutingState() { RxApp.EnsureInitialized(); }
static ViewForMixins() { RxApp.EnsureInitialized(); }
static PropertyBindingMixins() { RxApp.EnsureInitialized(); binderImplementation = new PropertyBinderImplementation(); }
static InteractionBindingMixins() { RxApp.EnsureInitialized(); _binderImplementation = new InteractionBinderImplementation(); }
static RxApp() { // Default name for the field backing the "Foo" property => "_Foo" // This is used for ReactiveObject's RaiseAndSetIfChanged mixin GetFieldNameForPropertyNameFunc = new Func <string, string>(x => "_" + x); #if WP7 TaskpoolScheduler = new EventLoopScheduler(); #elif WP8 //TaskpoolScheduler = Scheduler.TaskPool; TaskpoolScheduler = Scheduler.ThreadPool; #elif SILVERLIGHT || DOTNETISOLDANDSAD TaskpoolScheduler = Scheduler.ThreadPool; #elif WINRT TaskpoolScheduler = System.Reactive.Concurrency.ThreadPoolScheduler.Default; #else TaskpoolScheduler = Scheduler.TaskPool; #endif DefaultExceptionHandler = Observer.Create <Exception>(ex => { // NB: If you're seeing this, it means that an // ObservableAsPropertyHelper or the CanExecute of a // ReactiveCommand ended in an OnError. Instead of silently // breaking, ReactiveUI will halt here if a debugger is attached. if (Debugger.IsAttached) { Debugger.Break(); } RxApp.DeferredScheduler.Schedule(() => { throw new Exception( "An OnError occurred on an object (usually ObservableAsPropertyHelper) that would break a binding or command. To prevent this, Subscribe to the ThrownExceptions property of your objects", ex); }); }); MessageBus = new MessageBus(); LoggerFactory = t => new DebugLogger(); RxApp.Register(typeof(INPCObservableForProperty), typeof(ICreatesObservableForProperty)); RxApp.Register(typeof(IRNPCObservableForProperty), typeof(ICreatesObservableForProperty)); RxApp.Register(typeof(POCOObservableForProperty), typeof(ICreatesObservableForProperty)); RxApp.Register(typeof(PropertyBinderImplementation), typeof(IPropertyBinderImplementation)); RxApp.Register(typeof(NullDefaultPropertyBindingProvider), typeof(IDefaultPropertyBindingProvider)); RxApp.Register(typeof(EqualityTypeConverter), typeof(IBindingTypeConverter)); RxApp.Register(typeof(StringConverter), typeof(IBindingTypeConverter)); #if !SILVERLIGHT && !WINRT RxApp.Register(typeof(ComponentModelTypeConverter), typeof(IBindingTypeConverter)); #endif var namespaces = attemptToEarlyLoadReactiveUIDLLs(); namespaces.ForEach(ns => { #if WINRT var assm = typeof(RxApp).GetTypeInfo().Assembly; #else var assm = Assembly.GetExecutingAssembly(); #endif var fullName = typeof(RxApp).AssemblyQualifiedName; var targetType = ns + ".ServiceLocationRegistration"; fullName = fullName.Replace("ReactiveUI.RxApp", targetType); fullName = fullName.Replace(assm.FullName, assm.FullName.Replace("ReactiveUI", ns)); var registerTypeClass = Reflection.ReallyFindType(fullName, false); if (registerTypeClass != null) { var registerer = (IWantsToRegisterStuff)Activator.CreateInstance(registerTypeClass); registerer.Register(); } }); if (InUnitTestRunner()) { LogHost.Default.Warn("*** Detected Unit Test Runner, setting Scheduler to Immediate ***"); LogHost.Default.Warn("If we are not actually in a test runner, please file a bug\n"); DeferredScheduler = Scheduler.Immediate; } else { LogHost.Default.Info("Initializing to normal mode"); } if (DeferredScheduler == null) { LogHost.Default.Error("*** ReactiveUI.Xaml DLL reference not added - using Event Loop *** "); LogHost.Default.Error("Add a reference to ReactiveUI.Xaml if you're using WPF / SL5 / WP7 / WinRT"); LogHost.Default.Error("or consider explicitly setting RxApp.DeferredScheduler if not"); RxApp.DeferredScheduler = new EventLoopScheduler(); } }
static void subscribeToExpressionChain <TSender, TValue>( TSender origSource, string origPath, object source, LinkedListNode <string> propertyNames, LinkedListNode <IDisposable> subscriptions, bool beforeChange, Subject <IObservedChange <TSender, TValue> > subject ) { var current = propertyNames; var currentSub = subscriptions; object currentObj = source; PropertyInfo pi = null; ObservedChange <TSender, TValue> obsCh; while (current.Next != null) { pi = RxApp.getPropertyInfoForProperty(currentObj.GetType(), current.Value); if (pi == null) { subscriptions.List.Where(x => x != null).ForEach(x => x.Dispose()); throw new ArgumentException(String.Format("Property '{0}' does not exist in expression", current.Value)); } var notifyObj = wrapInpcObjectIfNeeded(currentObj); if (notifyObj != null) { var capture = new { current, currentObj, pi, currentSub }; var toDispose = new IDisposable[2]; var valGetter = new ObservedChange <object, TValue>() { Sender = capture.currentObj, PropertyName = buildPropPathFromNodePtr(capture.current), Value = default(TValue), }; TValue prevVal = default(TValue); bool prevValSet = valGetter.TryGetValue(out prevVal); toDispose[0] = notifyObj.Changing.Where(x => x.PropertyName == capture.current.Value).Subscribe(x => { prevValSet = valGetter.TryGetValue(out prevVal); }); toDispose[1] = notifyObj.Changed.Where(x => x.PropertyName == capture.current.Value).Subscribe(x => { subscribeToExpressionChain(origSource, origPath, capture.pi.GetValue(capture.currentObj, null), capture.current.Next, capture.currentSub.Next, beforeChange, subject); TValue newVal; if (!valGetter.TryGetValue(out newVal)) { return; } if (prevValSet && EqualityComparer <TValue> .Default.Equals(prevVal, newVal)) { return; } obsCh = new ObservedChange <TSender, TValue>() { Sender = origSource, PropertyName = origPath, Value = default(TValue), }; TValue obsChVal; if (obsCh.TryGetValue(out obsChVal)) { obsCh.Value = obsChVal; subject.OnNext(obsCh); } }); currentSub.Value = Disposable.Create(() => { toDispose[0].Dispose(); toDispose[1].Dispose(); }); } current = current.Next; currentSub = currentSub.Next; currentObj = pi.GetValue(currentObj, null); } var finalNotify = wrapInpcObjectIfNeeded(currentObj); if (currentSub.Value != null) { currentSub.Value.Dispose(); } if (finalNotify == null) { return; } var propName = current.Value; pi = RxApp.getPropertyInfoForProperty(currentObj.GetType(), current.Value); currentSub.Value = (beforeChange ? finalNotify.Changing : finalNotify.Changed).Where(x => x.PropertyName == propName).Subscribe(x => { obsCh = new ObservedChange <TSender, TValue>() { Sender = origSource, PropertyName = origPath, Value = (TValue)pi.GetValue(currentObj, null), }; subject.OnNext(obsCh); }); }
static DefaultPropertyBinding() { RxApp.EnsureInitialized(); }