From 5e9133e69c8e8831b8e1e49eba520d747d3868d0 Mon Sep 17 00:00:00 2001 From: khaled Date: Sat, 7 Oct 2023 01:33:48 +0200 Subject: [PATCH 01/14] Moved files in Caliburn.Micro.Core project. The hierarchy of root folders as following: * Framework main types: ----------------------- - Screen - ViewAware - Conductor - Coroutine - Result - EventAggregator * Framework services: --------------------- - PlatformProvider - IoC - Logging * Extended System Types - Types Types shared across The parts of the framework. - Extensions Extension Methods for system types. Inside each folder there maybe one or more of the following folders: - Contracts: The interfaces. - Base: abstract base implementation of the module. - DefaultImpl: Default implementation that can be overriding by Platform. - Impl: Multiple implementation of the contracts that can choosing from. - Models: POCO used as argument for methods. - Extensions: Extension methods for Contracts and main module file. - ExtensionPoints: Service as Static holder that can be opt-in. - EventArgs: POCO for events - EventHandlers: Event Handlers for modules. --- src/Caliburn.Micro.Core/{ => Conductor/Base}/ConductorBase.cs | 0 .../{ => Conductor/Base}/ConductorBaseWithActiveItem.cs | 0 src/Caliburn.Micro.Core/{ => Conductor}/Conductor.cs | 0 .../{ => Conductor}/ConductorWithCollectionAllActive.cs | 0 .../{ => Conductor}/ConductorWithCollectionOneActive.cs | 0 src/Caliburn.Micro.Core/{ => Conductor/Contracts}/ICloseResult.cs | 0 .../{ => Conductor/Contracts}/ICloseStrategy.cs | 0 src/Caliburn.Micro.Core/{ => Conductor/Contracts}/IConductor.cs | 0 .../{ => Conductor/Contracts}/IHaveActiveItem.cs | 0 src/Caliburn.Micro.Core/{ => Conductor/Contracts}/IParent.cs | 0 .../{ => Conductor/DefaultImpl}/CloseResult.cs | 0 .../{ => Conductor/DefaultImpl}/DefaultCloseStrategy.cs | 0 .../{ => Conductor/EventArgs}/ActivationProcessedEventArgs.cs | 0 .../{ => Conductor/Extensions}/ConductorExtensions.cs | 0 .../{ => Coroutine/ExtensionPoints}/Coroutine.cs | 0 .../{ => Coroutine/Models}/CoroutineExecutionContext.cs | 0 .../{ => EventAggregator/Contracts}/IEventAggregator.cs | 0 .../{ => EventAggregator/Contracts}/IHandle.cs | 0 src/Caliburn.Micro.Core/{ => EventAggregator}/EventAggregator.cs | 0 .../{ => EventAggregator/Extensions}/EventAggregatorExtensions.cs | 0 src/Caliburn.Micro.Core/{ => Extensions}/EnumerableExtensions.cs | 0 src/Caliburn.Micro.Core/{ => Extensions}/Execute.cs | 0 src/Caliburn.Micro.Core/{ => Extensions}/ExpressionExtensions.cs | 0 src/Caliburn.Micro.Core/{ => IoC/ExtensionPoints}/IoC.cs | 0 .../{ => IoC/Extensions}/ContainerExtensions.cs | 0 src/Caliburn.Micro.Core/{ => IoC}/SimpleContainer.cs | 0 src/Caliburn.Micro.Core/{ => Logging/Contracts}/ILog.cs | 0 .../{ => Logging/ExtensionPoints}/LogManager.cs | 0 src/Caliburn.Micro.Core/{ => Logging/Impl}/DebugLog.cs | 0 .../{ => PlatformProvider/Contracts}/IPlatformProvider.cs | 0 .../{ => PlatformProvider/DefaultImpl}/DefaultPlatformProvider.cs | 0 .../{ => PlatformProvider/ExtensionPoints}/PlatformProvider.cs | 0 src/Caliburn.Micro.Core/{ => Result/Contracts}/IResult.cs | 0 .../{ => Result/EventArgs}/ResultCompletionEventArgs.cs | 0 .../{ => Result/Extensions}/ResultExtensions.cs | 0 src/Caliburn.Micro.Core/{ => Result/Extensions}/TaskExtensions.cs | 0 .../{ => Result/Impl}/ContinueResultDecorator.cs | 0 src/Caliburn.Micro.Core/{ => Result/Impl}/DelegateResult.cs | 0 .../{ => Result/Impl}/OverrideCancelResultDecorator.cs | 0 .../{ => Result/Impl}/RescueResultDecorator.cs | 0 src/Caliburn.Micro.Core/{ => Result/Impl}/ResultDecoratorBase.cs | 0 src/Caliburn.Micro.Core/{ => Result/Impl}/SequentialResult.cs | 0 src/Caliburn.Micro.Core/{ => Result/Impl}/SimpleResult.cs | 0 src/Caliburn.Micro.Core/{ => Result/Impl}/TaskResult.cs | 0 src/Caliburn.Micro.Core/{ => Screen/Contracts}/IActivate.cs | 0 src/Caliburn.Micro.Core/{ => Screen/Contracts}/IChild.cs | 0 src/Caliburn.Micro.Core/{ => Screen/Contracts}/IClose.cs | 0 src/Caliburn.Micro.Core/{ => Screen/Contracts}/IDeactivate.cs | 0 src/Caliburn.Micro.Core/{ => Screen/Contracts}/IGuardClose.cs | 0 .../{ => Screen/Contracts}/IHaveDisplayName.cs | 0 src/Caliburn.Micro.Core/{ => Screen/Contracts}/IScreen.cs | 0 .../{ => Screen/EventArgs}/ActivationEventArgs.cs | 0 .../{ => Screen/EventArgs}/DeactivationEventArgs.cs | 0 .../{ => Screen/EventHandlers}/AsyncEventHandler.cs | 0 .../{ => Screen/Extensions}/ActivateExtensions.cs | 0 .../{ => Screen/Extensions}/AsyncEventHandlerExtensions.cs | 0 .../{ => Screen/Extensions}/DeactivateExtensions.cs | 0 .../{ => Screen/Extensions}/ScreenExtensions.cs | 0 src/Caliburn.Micro.Core/{ => Screen}/Screen.cs | 0 src/Caliburn.Micro.Core/{ => Types}/BindableCollection.cs | 0 src/Caliburn.Micro.Core/{ => Types}/INotifyPropertyChangedEx.cs | 0 src/Caliburn.Micro.Core/{ => Types}/IObservableCollection.cs | 0 src/Caliburn.Micro.Core/{ => Types}/PropertyChangedBase.cs | 0 src/Caliburn.Micro.Core/{ => Types}/WeakValueDictionary.cs | 0 src/Caliburn.Micro.Core/{ => ViewAware/Contracts}/IViewAware.cs | 0 .../{ => ViewAware/EventArgs}/ViewAttachedEventArgs.cs | 0 src/Caliburn.Micro.Core/{ => ViewAware}/ViewAware.cs | 0 67 files changed, 0 insertions(+), 0 deletions(-) rename src/Caliburn.Micro.Core/{ => Conductor/Base}/ConductorBase.cs (100%) rename src/Caliburn.Micro.Core/{ => Conductor/Base}/ConductorBaseWithActiveItem.cs (100%) rename src/Caliburn.Micro.Core/{ => Conductor}/Conductor.cs (100%) rename src/Caliburn.Micro.Core/{ => Conductor}/ConductorWithCollectionAllActive.cs (100%) rename src/Caliburn.Micro.Core/{ => Conductor}/ConductorWithCollectionOneActive.cs (100%) rename src/Caliburn.Micro.Core/{ => Conductor/Contracts}/ICloseResult.cs (100%) rename src/Caliburn.Micro.Core/{ => Conductor/Contracts}/ICloseStrategy.cs (100%) rename src/Caliburn.Micro.Core/{ => Conductor/Contracts}/IConductor.cs (100%) rename src/Caliburn.Micro.Core/{ => Conductor/Contracts}/IHaveActiveItem.cs (100%) rename src/Caliburn.Micro.Core/{ => Conductor/Contracts}/IParent.cs (100%) rename src/Caliburn.Micro.Core/{ => Conductor/DefaultImpl}/CloseResult.cs (100%) rename src/Caliburn.Micro.Core/{ => Conductor/DefaultImpl}/DefaultCloseStrategy.cs (100%) rename src/Caliburn.Micro.Core/{ => Conductor/EventArgs}/ActivationProcessedEventArgs.cs (100%) rename src/Caliburn.Micro.Core/{ => Conductor/Extensions}/ConductorExtensions.cs (100%) rename src/Caliburn.Micro.Core/{ => Coroutine/ExtensionPoints}/Coroutine.cs (100%) rename src/Caliburn.Micro.Core/{ => Coroutine/Models}/CoroutineExecutionContext.cs (100%) rename src/Caliburn.Micro.Core/{ => EventAggregator/Contracts}/IEventAggregator.cs (100%) rename src/Caliburn.Micro.Core/{ => EventAggregator/Contracts}/IHandle.cs (100%) rename src/Caliburn.Micro.Core/{ => EventAggregator}/EventAggregator.cs (100%) rename src/Caliburn.Micro.Core/{ => EventAggregator/Extensions}/EventAggregatorExtensions.cs (100%) rename src/Caliburn.Micro.Core/{ => Extensions}/EnumerableExtensions.cs (100%) rename src/Caliburn.Micro.Core/{ => Extensions}/Execute.cs (100%) rename src/Caliburn.Micro.Core/{ => Extensions}/ExpressionExtensions.cs (100%) rename src/Caliburn.Micro.Core/{ => IoC/ExtensionPoints}/IoC.cs (100%) rename src/Caliburn.Micro.Core/{ => IoC/Extensions}/ContainerExtensions.cs (100%) rename src/Caliburn.Micro.Core/{ => IoC}/SimpleContainer.cs (100%) rename src/Caliburn.Micro.Core/{ => Logging/Contracts}/ILog.cs (100%) rename src/Caliburn.Micro.Core/{ => Logging/ExtensionPoints}/LogManager.cs (100%) rename src/Caliburn.Micro.Core/{ => Logging/Impl}/DebugLog.cs (100%) rename src/Caliburn.Micro.Core/{ => PlatformProvider/Contracts}/IPlatformProvider.cs (100%) rename src/Caliburn.Micro.Core/{ => PlatformProvider/DefaultImpl}/DefaultPlatformProvider.cs (100%) rename src/Caliburn.Micro.Core/{ => PlatformProvider/ExtensionPoints}/PlatformProvider.cs (100%) rename src/Caliburn.Micro.Core/{ => Result/Contracts}/IResult.cs (100%) rename src/Caliburn.Micro.Core/{ => Result/EventArgs}/ResultCompletionEventArgs.cs (100%) rename src/Caliburn.Micro.Core/{ => Result/Extensions}/ResultExtensions.cs (100%) rename src/Caliburn.Micro.Core/{ => Result/Extensions}/TaskExtensions.cs (100%) rename src/Caliburn.Micro.Core/{ => Result/Impl}/ContinueResultDecorator.cs (100%) rename src/Caliburn.Micro.Core/{ => Result/Impl}/DelegateResult.cs (100%) rename src/Caliburn.Micro.Core/{ => Result/Impl}/OverrideCancelResultDecorator.cs (100%) rename src/Caliburn.Micro.Core/{ => Result/Impl}/RescueResultDecorator.cs (100%) rename src/Caliburn.Micro.Core/{ => Result/Impl}/ResultDecoratorBase.cs (100%) rename src/Caliburn.Micro.Core/{ => Result/Impl}/SequentialResult.cs (100%) rename src/Caliburn.Micro.Core/{ => Result/Impl}/SimpleResult.cs (100%) rename src/Caliburn.Micro.Core/{ => Result/Impl}/TaskResult.cs (100%) rename src/Caliburn.Micro.Core/{ => Screen/Contracts}/IActivate.cs (100%) rename src/Caliburn.Micro.Core/{ => Screen/Contracts}/IChild.cs (100%) rename src/Caliburn.Micro.Core/{ => Screen/Contracts}/IClose.cs (100%) rename src/Caliburn.Micro.Core/{ => Screen/Contracts}/IDeactivate.cs (100%) rename src/Caliburn.Micro.Core/{ => Screen/Contracts}/IGuardClose.cs (100%) rename src/Caliburn.Micro.Core/{ => Screen/Contracts}/IHaveDisplayName.cs (100%) rename src/Caliburn.Micro.Core/{ => Screen/Contracts}/IScreen.cs (100%) rename src/Caliburn.Micro.Core/{ => Screen/EventArgs}/ActivationEventArgs.cs (100%) rename src/Caliburn.Micro.Core/{ => Screen/EventArgs}/DeactivationEventArgs.cs (100%) rename src/Caliburn.Micro.Core/{ => Screen/EventHandlers}/AsyncEventHandler.cs (100%) rename src/Caliburn.Micro.Core/{ => Screen/Extensions}/ActivateExtensions.cs (100%) rename src/Caliburn.Micro.Core/{ => Screen/Extensions}/AsyncEventHandlerExtensions.cs (100%) rename src/Caliburn.Micro.Core/{ => Screen/Extensions}/DeactivateExtensions.cs (100%) rename src/Caliburn.Micro.Core/{ => Screen/Extensions}/ScreenExtensions.cs (100%) rename src/Caliburn.Micro.Core/{ => Screen}/Screen.cs (100%) rename src/Caliburn.Micro.Core/{ => Types}/BindableCollection.cs (100%) rename src/Caliburn.Micro.Core/{ => Types}/INotifyPropertyChangedEx.cs (100%) rename src/Caliburn.Micro.Core/{ => Types}/IObservableCollection.cs (100%) rename src/Caliburn.Micro.Core/{ => Types}/PropertyChangedBase.cs (100%) rename src/Caliburn.Micro.Core/{ => Types}/WeakValueDictionary.cs (100%) rename src/Caliburn.Micro.Core/{ => ViewAware/Contracts}/IViewAware.cs (100%) rename src/Caliburn.Micro.Core/{ => ViewAware/EventArgs}/ViewAttachedEventArgs.cs (100%) rename src/Caliburn.Micro.Core/{ => ViewAware}/ViewAware.cs (100%) diff --git a/src/Caliburn.Micro.Core/ConductorBase.cs b/src/Caliburn.Micro.Core/Conductor/Base/ConductorBase.cs similarity index 100% rename from src/Caliburn.Micro.Core/ConductorBase.cs rename to src/Caliburn.Micro.Core/Conductor/Base/ConductorBase.cs diff --git a/src/Caliburn.Micro.Core/ConductorBaseWithActiveItem.cs b/src/Caliburn.Micro.Core/Conductor/Base/ConductorBaseWithActiveItem.cs similarity index 100% rename from src/Caliburn.Micro.Core/ConductorBaseWithActiveItem.cs rename to src/Caliburn.Micro.Core/Conductor/Base/ConductorBaseWithActiveItem.cs diff --git a/src/Caliburn.Micro.Core/Conductor.cs b/src/Caliburn.Micro.Core/Conductor/Conductor.cs similarity index 100% rename from src/Caliburn.Micro.Core/Conductor.cs rename to src/Caliburn.Micro.Core/Conductor/Conductor.cs diff --git a/src/Caliburn.Micro.Core/ConductorWithCollectionAllActive.cs b/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionAllActive.cs similarity index 100% rename from src/Caliburn.Micro.Core/ConductorWithCollectionAllActive.cs rename to src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionAllActive.cs diff --git a/src/Caliburn.Micro.Core/ConductorWithCollectionOneActive.cs b/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionOneActive.cs similarity index 100% rename from src/Caliburn.Micro.Core/ConductorWithCollectionOneActive.cs rename to src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionOneActive.cs diff --git a/src/Caliburn.Micro.Core/ICloseResult.cs b/src/Caliburn.Micro.Core/Conductor/Contracts/ICloseResult.cs similarity index 100% rename from src/Caliburn.Micro.Core/ICloseResult.cs rename to src/Caliburn.Micro.Core/Conductor/Contracts/ICloseResult.cs diff --git a/src/Caliburn.Micro.Core/ICloseStrategy.cs b/src/Caliburn.Micro.Core/Conductor/Contracts/ICloseStrategy.cs similarity index 100% rename from src/Caliburn.Micro.Core/ICloseStrategy.cs rename to src/Caliburn.Micro.Core/Conductor/Contracts/ICloseStrategy.cs diff --git a/src/Caliburn.Micro.Core/IConductor.cs b/src/Caliburn.Micro.Core/Conductor/Contracts/IConductor.cs similarity index 100% rename from src/Caliburn.Micro.Core/IConductor.cs rename to src/Caliburn.Micro.Core/Conductor/Contracts/IConductor.cs diff --git a/src/Caliburn.Micro.Core/IHaveActiveItem.cs b/src/Caliburn.Micro.Core/Conductor/Contracts/IHaveActiveItem.cs similarity index 100% rename from src/Caliburn.Micro.Core/IHaveActiveItem.cs rename to src/Caliburn.Micro.Core/Conductor/Contracts/IHaveActiveItem.cs diff --git a/src/Caliburn.Micro.Core/IParent.cs b/src/Caliburn.Micro.Core/Conductor/Contracts/IParent.cs similarity index 100% rename from src/Caliburn.Micro.Core/IParent.cs rename to src/Caliburn.Micro.Core/Conductor/Contracts/IParent.cs diff --git a/src/Caliburn.Micro.Core/CloseResult.cs b/src/Caliburn.Micro.Core/Conductor/DefaultImpl/CloseResult.cs similarity index 100% rename from src/Caliburn.Micro.Core/CloseResult.cs rename to src/Caliburn.Micro.Core/Conductor/DefaultImpl/CloseResult.cs diff --git a/src/Caliburn.Micro.Core/DefaultCloseStrategy.cs b/src/Caliburn.Micro.Core/Conductor/DefaultImpl/DefaultCloseStrategy.cs similarity index 100% rename from src/Caliburn.Micro.Core/DefaultCloseStrategy.cs rename to src/Caliburn.Micro.Core/Conductor/DefaultImpl/DefaultCloseStrategy.cs diff --git a/src/Caliburn.Micro.Core/ActivationProcessedEventArgs.cs b/src/Caliburn.Micro.Core/Conductor/EventArgs/ActivationProcessedEventArgs.cs similarity index 100% rename from src/Caliburn.Micro.Core/ActivationProcessedEventArgs.cs rename to src/Caliburn.Micro.Core/Conductor/EventArgs/ActivationProcessedEventArgs.cs diff --git a/src/Caliburn.Micro.Core/ConductorExtensions.cs b/src/Caliburn.Micro.Core/Conductor/Extensions/ConductorExtensions.cs similarity index 100% rename from src/Caliburn.Micro.Core/ConductorExtensions.cs rename to src/Caliburn.Micro.Core/Conductor/Extensions/ConductorExtensions.cs diff --git a/src/Caliburn.Micro.Core/Coroutine.cs b/src/Caliburn.Micro.Core/Coroutine/ExtensionPoints/Coroutine.cs similarity index 100% rename from src/Caliburn.Micro.Core/Coroutine.cs rename to src/Caliburn.Micro.Core/Coroutine/ExtensionPoints/Coroutine.cs diff --git a/src/Caliburn.Micro.Core/CoroutineExecutionContext.cs b/src/Caliburn.Micro.Core/Coroutine/Models/CoroutineExecutionContext.cs similarity index 100% rename from src/Caliburn.Micro.Core/CoroutineExecutionContext.cs rename to src/Caliburn.Micro.Core/Coroutine/Models/CoroutineExecutionContext.cs diff --git a/src/Caliburn.Micro.Core/IEventAggregator.cs b/src/Caliburn.Micro.Core/EventAggregator/Contracts/IEventAggregator.cs similarity index 100% rename from src/Caliburn.Micro.Core/IEventAggregator.cs rename to src/Caliburn.Micro.Core/EventAggregator/Contracts/IEventAggregator.cs diff --git a/src/Caliburn.Micro.Core/IHandle.cs b/src/Caliburn.Micro.Core/EventAggregator/Contracts/IHandle.cs similarity index 100% rename from src/Caliburn.Micro.Core/IHandle.cs rename to src/Caliburn.Micro.Core/EventAggregator/Contracts/IHandle.cs diff --git a/src/Caliburn.Micro.Core/EventAggregator.cs b/src/Caliburn.Micro.Core/EventAggregator/EventAggregator.cs similarity index 100% rename from src/Caliburn.Micro.Core/EventAggregator.cs rename to src/Caliburn.Micro.Core/EventAggregator/EventAggregator.cs diff --git a/src/Caliburn.Micro.Core/EventAggregatorExtensions.cs b/src/Caliburn.Micro.Core/EventAggregator/Extensions/EventAggregatorExtensions.cs similarity index 100% rename from src/Caliburn.Micro.Core/EventAggregatorExtensions.cs rename to src/Caliburn.Micro.Core/EventAggregator/Extensions/EventAggregatorExtensions.cs diff --git a/src/Caliburn.Micro.Core/EnumerableExtensions.cs b/src/Caliburn.Micro.Core/Extensions/EnumerableExtensions.cs similarity index 100% rename from src/Caliburn.Micro.Core/EnumerableExtensions.cs rename to src/Caliburn.Micro.Core/Extensions/EnumerableExtensions.cs diff --git a/src/Caliburn.Micro.Core/Execute.cs b/src/Caliburn.Micro.Core/Extensions/Execute.cs similarity index 100% rename from src/Caliburn.Micro.Core/Execute.cs rename to src/Caliburn.Micro.Core/Extensions/Execute.cs diff --git a/src/Caliburn.Micro.Core/ExpressionExtensions.cs b/src/Caliburn.Micro.Core/Extensions/ExpressionExtensions.cs similarity index 100% rename from src/Caliburn.Micro.Core/ExpressionExtensions.cs rename to src/Caliburn.Micro.Core/Extensions/ExpressionExtensions.cs diff --git a/src/Caliburn.Micro.Core/IoC.cs b/src/Caliburn.Micro.Core/IoC/ExtensionPoints/IoC.cs similarity index 100% rename from src/Caliburn.Micro.Core/IoC.cs rename to src/Caliburn.Micro.Core/IoC/ExtensionPoints/IoC.cs diff --git a/src/Caliburn.Micro.Core/ContainerExtensions.cs b/src/Caliburn.Micro.Core/IoC/Extensions/ContainerExtensions.cs similarity index 100% rename from src/Caliburn.Micro.Core/ContainerExtensions.cs rename to src/Caliburn.Micro.Core/IoC/Extensions/ContainerExtensions.cs diff --git a/src/Caliburn.Micro.Core/SimpleContainer.cs b/src/Caliburn.Micro.Core/IoC/SimpleContainer.cs similarity index 100% rename from src/Caliburn.Micro.Core/SimpleContainer.cs rename to src/Caliburn.Micro.Core/IoC/SimpleContainer.cs diff --git a/src/Caliburn.Micro.Core/ILog.cs b/src/Caliburn.Micro.Core/Logging/Contracts/ILog.cs similarity index 100% rename from src/Caliburn.Micro.Core/ILog.cs rename to src/Caliburn.Micro.Core/Logging/Contracts/ILog.cs diff --git a/src/Caliburn.Micro.Core/LogManager.cs b/src/Caliburn.Micro.Core/Logging/ExtensionPoints/LogManager.cs similarity index 100% rename from src/Caliburn.Micro.Core/LogManager.cs rename to src/Caliburn.Micro.Core/Logging/ExtensionPoints/LogManager.cs diff --git a/src/Caliburn.Micro.Core/DebugLog.cs b/src/Caliburn.Micro.Core/Logging/Impl/DebugLog.cs similarity index 100% rename from src/Caliburn.Micro.Core/DebugLog.cs rename to src/Caliburn.Micro.Core/Logging/Impl/DebugLog.cs diff --git a/src/Caliburn.Micro.Core/IPlatformProvider.cs b/src/Caliburn.Micro.Core/PlatformProvider/Contracts/IPlatformProvider.cs similarity index 100% rename from src/Caliburn.Micro.Core/IPlatformProvider.cs rename to src/Caliburn.Micro.Core/PlatformProvider/Contracts/IPlatformProvider.cs diff --git a/src/Caliburn.Micro.Core/DefaultPlatformProvider.cs b/src/Caliburn.Micro.Core/PlatformProvider/DefaultImpl/DefaultPlatformProvider.cs similarity index 100% rename from src/Caliburn.Micro.Core/DefaultPlatformProvider.cs rename to src/Caliburn.Micro.Core/PlatformProvider/DefaultImpl/DefaultPlatformProvider.cs diff --git a/src/Caliburn.Micro.Core/PlatformProvider.cs b/src/Caliburn.Micro.Core/PlatformProvider/ExtensionPoints/PlatformProvider.cs similarity index 100% rename from src/Caliburn.Micro.Core/PlatformProvider.cs rename to src/Caliburn.Micro.Core/PlatformProvider/ExtensionPoints/PlatformProvider.cs diff --git a/src/Caliburn.Micro.Core/IResult.cs b/src/Caliburn.Micro.Core/Result/Contracts/IResult.cs similarity index 100% rename from src/Caliburn.Micro.Core/IResult.cs rename to src/Caliburn.Micro.Core/Result/Contracts/IResult.cs diff --git a/src/Caliburn.Micro.Core/ResultCompletionEventArgs.cs b/src/Caliburn.Micro.Core/Result/EventArgs/ResultCompletionEventArgs.cs similarity index 100% rename from src/Caliburn.Micro.Core/ResultCompletionEventArgs.cs rename to src/Caliburn.Micro.Core/Result/EventArgs/ResultCompletionEventArgs.cs diff --git a/src/Caliburn.Micro.Core/ResultExtensions.cs b/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs similarity index 100% rename from src/Caliburn.Micro.Core/ResultExtensions.cs rename to src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs diff --git a/src/Caliburn.Micro.Core/TaskExtensions.cs b/src/Caliburn.Micro.Core/Result/Extensions/TaskExtensions.cs similarity index 100% rename from src/Caliburn.Micro.Core/TaskExtensions.cs rename to src/Caliburn.Micro.Core/Result/Extensions/TaskExtensions.cs diff --git a/src/Caliburn.Micro.Core/ContinueResultDecorator.cs b/src/Caliburn.Micro.Core/Result/Impl/ContinueResultDecorator.cs similarity index 100% rename from src/Caliburn.Micro.Core/ContinueResultDecorator.cs rename to src/Caliburn.Micro.Core/Result/Impl/ContinueResultDecorator.cs diff --git a/src/Caliburn.Micro.Core/DelegateResult.cs b/src/Caliburn.Micro.Core/Result/Impl/DelegateResult.cs similarity index 100% rename from src/Caliburn.Micro.Core/DelegateResult.cs rename to src/Caliburn.Micro.Core/Result/Impl/DelegateResult.cs diff --git a/src/Caliburn.Micro.Core/OverrideCancelResultDecorator.cs b/src/Caliburn.Micro.Core/Result/Impl/OverrideCancelResultDecorator.cs similarity index 100% rename from src/Caliburn.Micro.Core/OverrideCancelResultDecorator.cs rename to src/Caliburn.Micro.Core/Result/Impl/OverrideCancelResultDecorator.cs diff --git a/src/Caliburn.Micro.Core/RescueResultDecorator.cs b/src/Caliburn.Micro.Core/Result/Impl/RescueResultDecorator.cs similarity index 100% rename from src/Caliburn.Micro.Core/RescueResultDecorator.cs rename to src/Caliburn.Micro.Core/Result/Impl/RescueResultDecorator.cs diff --git a/src/Caliburn.Micro.Core/ResultDecoratorBase.cs b/src/Caliburn.Micro.Core/Result/Impl/ResultDecoratorBase.cs similarity index 100% rename from src/Caliburn.Micro.Core/ResultDecoratorBase.cs rename to src/Caliburn.Micro.Core/Result/Impl/ResultDecoratorBase.cs diff --git a/src/Caliburn.Micro.Core/SequentialResult.cs b/src/Caliburn.Micro.Core/Result/Impl/SequentialResult.cs similarity index 100% rename from src/Caliburn.Micro.Core/SequentialResult.cs rename to src/Caliburn.Micro.Core/Result/Impl/SequentialResult.cs diff --git a/src/Caliburn.Micro.Core/SimpleResult.cs b/src/Caliburn.Micro.Core/Result/Impl/SimpleResult.cs similarity index 100% rename from src/Caliburn.Micro.Core/SimpleResult.cs rename to src/Caliburn.Micro.Core/Result/Impl/SimpleResult.cs diff --git a/src/Caliburn.Micro.Core/TaskResult.cs b/src/Caliburn.Micro.Core/Result/Impl/TaskResult.cs similarity index 100% rename from src/Caliburn.Micro.Core/TaskResult.cs rename to src/Caliburn.Micro.Core/Result/Impl/TaskResult.cs diff --git a/src/Caliburn.Micro.Core/IActivate.cs b/src/Caliburn.Micro.Core/Screen/Contracts/IActivate.cs similarity index 100% rename from src/Caliburn.Micro.Core/IActivate.cs rename to src/Caliburn.Micro.Core/Screen/Contracts/IActivate.cs diff --git a/src/Caliburn.Micro.Core/IChild.cs b/src/Caliburn.Micro.Core/Screen/Contracts/IChild.cs similarity index 100% rename from src/Caliburn.Micro.Core/IChild.cs rename to src/Caliburn.Micro.Core/Screen/Contracts/IChild.cs diff --git a/src/Caliburn.Micro.Core/IClose.cs b/src/Caliburn.Micro.Core/Screen/Contracts/IClose.cs similarity index 100% rename from src/Caliburn.Micro.Core/IClose.cs rename to src/Caliburn.Micro.Core/Screen/Contracts/IClose.cs diff --git a/src/Caliburn.Micro.Core/IDeactivate.cs b/src/Caliburn.Micro.Core/Screen/Contracts/IDeactivate.cs similarity index 100% rename from src/Caliburn.Micro.Core/IDeactivate.cs rename to src/Caliburn.Micro.Core/Screen/Contracts/IDeactivate.cs diff --git a/src/Caliburn.Micro.Core/IGuardClose.cs b/src/Caliburn.Micro.Core/Screen/Contracts/IGuardClose.cs similarity index 100% rename from src/Caliburn.Micro.Core/IGuardClose.cs rename to src/Caliburn.Micro.Core/Screen/Contracts/IGuardClose.cs diff --git a/src/Caliburn.Micro.Core/IHaveDisplayName.cs b/src/Caliburn.Micro.Core/Screen/Contracts/IHaveDisplayName.cs similarity index 100% rename from src/Caliburn.Micro.Core/IHaveDisplayName.cs rename to src/Caliburn.Micro.Core/Screen/Contracts/IHaveDisplayName.cs diff --git a/src/Caliburn.Micro.Core/IScreen.cs b/src/Caliburn.Micro.Core/Screen/Contracts/IScreen.cs similarity index 100% rename from src/Caliburn.Micro.Core/IScreen.cs rename to src/Caliburn.Micro.Core/Screen/Contracts/IScreen.cs diff --git a/src/Caliburn.Micro.Core/ActivationEventArgs.cs b/src/Caliburn.Micro.Core/Screen/EventArgs/ActivationEventArgs.cs similarity index 100% rename from src/Caliburn.Micro.Core/ActivationEventArgs.cs rename to src/Caliburn.Micro.Core/Screen/EventArgs/ActivationEventArgs.cs diff --git a/src/Caliburn.Micro.Core/DeactivationEventArgs.cs b/src/Caliburn.Micro.Core/Screen/EventArgs/DeactivationEventArgs.cs similarity index 100% rename from src/Caliburn.Micro.Core/DeactivationEventArgs.cs rename to src/Caliburn.Micro.Core/Screen/EventArgs/DeactivationEventArgs.cs diff --git a/src/Caliburn.Micro.Core/AsyncEventHandler.cs b/src/Caliburn.Micro.Core/Screen/EventHandlers/AsyncEventHandler.cs similarity index 100% rename from src/Caliburn.Micro.Core/AsyncEventHandler.cs rename to src/Caliburn.Micro.Core/Screen/EventHandlers/AsyncEventHandler.cs diff --git a/src/Caliburn.Micro.Core/ActivateExtensions.cs b/src/Caliburn.Micro.Core/Screen/Extensions/ActivateExtensions.cs similarity index 100% rename from src/Caliburn.Micro.Core/ActivateExtensions.cs rename to src/Caliburn.Micro.Core/Screen/Extensions/ActivateExtensions.cs diff --git a/src/Caliburn.Micro.Core/AsyncEventHandlerExtensions.cs b/src/Caliburn.Micro.Core/Screen/Extensions/AsyncEventHandlerExtensions.cs similarity index 100% rename from src/Caliburn.Micro.Core/AsyncEventHandlerExtensions.cs rename to src/Caliburn.Micro.Core/Screen/Extensions/AsyncEventHandlerExtensions.cs diff --git a/src/Caliburn.Micro.Core/DeactivateExtensions.cs b/src/Caliburn.Micro.Core/Screen/Extensions/DeactivateExtensions.cs similarity index 100% rename from src/Caliburn.Micro.Core/DeactivateExtensions.cs rename to src/Caliburn.Micro.Core/Screen/Extensions/DeactivateExtensions.cs diff --git a/src/Caliburn.Micro.Core/ScreenExtensions.cs b/src/Caliburn.Micro.Core/Screen/Extensions/ScreenExtensions.cs similarity index 100% rename from src/Caliburn.Micro.Core/ScreenExtensions.cs rename to src/Caliburn.Micro.Core/Screen/Extensions/ScreenExtensions.cs diff --git a/src/Caliburn.Micro.Core/Screen.cs b/src/Caliburn.Micro.Core/Screen/Screen.cs similarity index 100% rename from src/Caliburn.Micro.Core/Screen.cs rename to src/Caliburn.Micro.Core/Screen/Screen.cs diff --git a/src/Caliburn.Micro.Core/BindableCollection.cs b/src/Caliburn.Micro.Core/Types/BindableCollection.cs similarity index 100% rename from src/Caliburn.Micro.Core/BindableCollection.cs rename to src/Caliburn.Micro.Core/Types/BindableCollection.cs diff --git a/src/Caliburn.Micro.Core/INotifyPropertyChangedEx.cs b/src/Caliburn.Micro.Core/Types/INotifyPropertyChangedEx.cs similarity index 100% rename from src/Caliburn.Micro.Core/INotifyPropertyChangedEx.cs rename to src/Caliburn.Micro.Core/Types/INotifyPropertyChangedEx.cs diff --git a/src/Caliburn.Micro.Core/IObservableCollection.cs b/src/Caliburn.Micro.Core/Types/IObservableCollection.cs similarity index 100% rename from src/Caliburn.Micro.Core/IObservableCollection.cs rename to src/Caliburn.Micro.Core/Types/IObservableCollection.cs diff --git a/src/Caliburn.Micro.Core/PropertyChangedBase.cs b/src/Caliburn.Micro.Core/Types/PropertyChangedBase.cs similarity index 100% rename from src/Caliburn.Micro.Core/PropertyChangedBase.cs rename to src/Caliburn.Micro.Core/Types/PropertyChangedBase.cs diff --git a/src/Caliburn.Micro.Core/WeakValueDictionary.cs b/src/Caliburn.Micro.Core/Types/WeakValueDictionary.cs similarity index 100% rename from src/Caliburn.Micro.Core/WeakValueDictionary.cs rename to src/Caliburn.Micro.Core/Types/WeakValueDictionary.cs diff --git a/src/Caliburn.Micro.Core/IViewAware.cs b/src/Caliburn.Micro.Core/ViewAware/Contracts/IViewAware.cs similarity index 100% rename from src/Caliburn.Micro.Core/IViewAware.cs rename to src/Caliburn.Micro.Core/ViewAware/Contracts/IViewAware.cs diff --git a/src/Caliburn.Micro.Core/ViewAttachedEventArgs.cs b/src/Caliburn.Micro.Core/ViewAware/EventArgs/ViewAttachedEventArgs.cs similarity index 100% rename from src/Caliburn.Micro.Core/ViewAttachedEventArgs.cs rename to src/Caliburn.Micro.Core/ViewAware/EventArgs/ViewAttachedEventArgs.cs diff --git a/src/Caliburn.Micro.Core/ViewAware.cs b/src/Caliburn.Micro.Core/ViewAware/ViewAware.cs similarity index 100% rename from src/Caliburn.Micro.Core/ViewAware.cs rename to src/Caliburn.Micro.Core/ViewAware/ViewAware.cs From e0f727691e50d804feb3080611c0728ab4ca1e33 Mon Sep 17 00:00:00 2001 From: khaled Date: Sat, 7 Oct 2023 03:04:45 +0200 Subject: [PATCH 02/14] - Extracted types from files containing more than one type. - Moved contents of TaskExtensions.cs to ResultExtensions.cs, both dealing with IResult. - Deleted TaskExtensions.cs. * Note Nested types still exist in: - WeakValueDictionary contains ValueCollection as private type (OK). - LogManager conatins NullLog as private type [Null Pattern] (OK). - SimpleContainer contains (ContainerEntry and FactoryFactory) as private type (OK). - EventAggregator contains Handler as private type (OK). - Conductor partial class contains Collection as partial class which in turn contains (OneActive and AllActive) (Code Smell), We Should use namespaces. if we were enabling Code Analyzers right now with SDK 7.0.401, we will get CA1052 error among other errors. change global.json SDK version to 7.0.401 and add these properties to the project: 7 True True True latest-all --- .../Conductor/Contracts/IConductActiveItem.cs | 13 +++ .../Conductor/Contracts/IConductor.cs | 7 -- .../Conductor/Contracts/IParent.cs | 15 --- .../Conductor/Contracts/IParent{T}.cs | 20 ++++ .../Result/Contracts/IResult.cs | 12 --- .../Result/Contracts/IResult{TResult}.cs | 16 ++++ .../Result/Extensions/ResultExtensions.cs | 86 +++++++++++++++++ .../Result/Extensions/TaskExtensions.cs | 95 ------------------- .../Result/Impl/DelegateResult.cs | 48 ---------- .../Result/Impl/DelegateResult{TResult}.cs | 52 ++++++++++ .../Result/Impl/TaskResult.cs | 35 ------- .../Result/Impl/TaskResult{TResult}.cs | 40 ++++++++ .../Screen/Contracts/IChild.cs | 12 --- .../Screen/Contracts/IChild{TParent}.cs | 14 +++ 14 files changed, 241 insertions(+), 224 deletions(-) create mode 100644 src/Caliburn.Micro.Core/Conductor/Contracts/IConductActiveItem.cs create mode 100644 src/Caliburn.Micro.Core/Conductor/Contracts/IParent{T}.cs create mode 100644 src/Caliburn.Micro.Core/Result/Contracts/IResult{TResult}.cs delete mode 100644 src/Caliburn.Micro.Core/Result/Extensions/TaskExtensions.cs create mode 100644 src/Caliburn.Micro.Core/Result/Impl/DelegateResult{TResult}.cs create mode 100644 src/Caliburn.Micro.Core/Result/Impl/TaskResult{TResult}.cs create mode 100644 src/Caliburn.Micro.Core/Screen/Contracts/IChild{TParent}.cs diff --git a/src/Caliburn.Micro.Core/Conductor/Contracts/IConductActiveItem.cs b/src/Caliburn.Micro.Core/Conductor/Contracts/IConductActiveItem.cs new file mode 100644 index 000000000..8b3f6d40d --- /dev/null +++ b/src/Caliburn.Micro.Core/Conductor/Contracts/IConductActiveItem.cs @@ -0,0 +1,13 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Caliburn.Micro +{ + /// + /// An that also implements . + /// + public interface IConductActiveItem : IConductor, IHaveActiveItem + { + } +} diff --git a/src/Caliburn.Micro.Core/Conductor/Contracts/IConductor.cs b/src/Caliburn.Micro.Core/Conductor/Contracts/IConductor.cs index ce0c7666e..356ecc534 100644 --- a/src/Caliburn.Micro.Core/Conductor/Contracts/IConductor.cs +++ b/src/Caliburn.Micro.Core/Conductor/Contracts/IConductor.cs @@ -31,11 +31,4 @@ public interface IConductor : IParent, INotifyPropertyChangedEx /// event EventHandler ActivationProcessed; } - - /// - /// An that also implements . - /// - public interface IConductActiveItem : IConductor, IHaveActiveItem - { - } } diff --git a/src/Caliburn.Micro.Core/Conductor/Contracts/IParent.cs b/src/Caliburn.Micro.Core/Conductor/Contracts/IParent.cs index a4f997ad5..9c2af28ac 100644 --- a/src/Caliburn.Micro.Core/Conductor/Contracts/IParent.cs +++ b/src/Caliburn.Micro.Core/Conductor/Contracts/IParent.cs @@ -16,19 +16,4 @@ public interface IParent /// IEnumerable GetChildren(); } - - /// - /// Interface used to define a specialized parent. - /// - /// The type of children. - public interface IParent : IParent - { - /// - /// Gets the children. - /// - /// - /// The collection of children. - /// - new IEnumerable GetChildren(); - } } diff --git a/src/Caliburn.Micro.Core/Conductor/Contracts/IParent{T}.cs b/src/Caliburn.Micro.Core/Conductor/Contracts/IParent{T}.cs new file mode 100644 index 000000000..0ce0ce5a1 --- /dev/null +++ b/src/Caliburn.Micro.Core/Conductor/Contracts/IParent{T}.cs @@ -0,0 +1,20 @@ +using System.Collections; +using System.Collections.Generic; + +namespace Caliburn.Micro +{ + /// + /// Interface used to define a specialized parent. + /// + /// The type of children. + public interface IParent : IParent + { + /// + /// Gets the children. + /// + /// + /// The collection of children. + /// + new IEnumerable GetChildren(); + } +} diff --git a/src/Caliburn.Micro.Core/Result/Contracts/IResult.cs b/src/Caliburn.Micro.Core/Result/Contracts/IResult.cs index 421aefa0f..3294ca9b4 100644 --- a/src/Caliburn.Micro.Core/Result/Contracts/IResult.cs +++ b/src/Caliburn.Micro.Core/Result/Contracts/IResult.cs @@ -18,16 +18,4 @@ public interface IResult /// event EventHandler Completed; } - - /// - /// Allows custom code to execute after the return of a action. - /// - /// The type of the result. - public interface IResult : IResult - { - /// - /// Gets the result of the asynchronous operation. - /// - TResult Result { get; } - } } diff --git a/src/Caliburn.Micro.Core/Result/Contracts/IResult{TResult}.cs b/src/Caliburn.Micro.Core/Result/Contracts/IResult{TResult}.cs new file mode 100644 index 000000000..1a00c9c75 --- /dev/null +++ b/src/Caliburn.Micro.Core/Result/Contracts/IResult{TResult}.cs @@ -0,0 +1,16 @@ +using System; + +namespace Caliburn.Micro +{ + /// + /// Allows custom code to execute after the return of a action. + /// + /// The type of the result. + public interface IResult : IResult + { + /// + /// Gets the result of the asynchronous operation. + /// + TResult Result { get; } + } +} diff --git a/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs b/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs index 4c1c05f57..dedd6efa5 100644 --- a/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs +++ b/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; namespace Caliburn.Micro { @@ -55,5 +56,90 @@ public static IResult Rescue(this IResult result, Func rescu { return Rescue(result, rescue, cancelResult); } + + /// + /// Executes an asynchronous. + /// + /// The coroutine to execute. + /// The context to execute the coroutine within. + /// A task that represents the asynchronous coroutine. + public static Task ExecuteAsync(this IResult result, CoroutineExecutionContext context = null) + { + return InternalExecuteAsync(result, context); + } + + /// + /// Executes an asynchronous. + /// + /// The type of the result. + /// The coroutine to execute. + /// The context to execute the coroutine within. + /// A task that represents the asynchronous coroutine. + public static Task ExecuteAsync(this IResult result, + CoroutineExecutionContext context = null) + { + return InternalExecuteAsync(result, context); + } + + + /// + /// Encapsulates a task inside a couroutine. + /// + /// The task. + /// The coroutine that encapsulates the task. + public static TaskResult AsResult(this Task task) + { + return new TaskResult(task); + } + + /// + /// Encapsulates a task inside a couroutine. + /// + /// The type of the result. + /// The task. + /// The coroutine that encapsulates the task. + public static TaskResult AsResult(this Task task) + { + return new TaskResult(task); + } + + private static Task InternalExecuteAsync(IResult result, CoroutineExecutionContext context) + { + var taskSource = new TaskCompletionSource(); + + EventHandler completed = null; + completed = (s, e) => + { + result.Completed -= completed; + + if (e.Error != null) + { + taskSource.SetException(e.Error); + } + else if (e.WasCancelled) + { + taskSource.SetCanceled(); + } + else + { + var rr = result as IResult; + taskSource.SetResult(rr != null ? rr.Result : default(TResult)); + } + }; + + try + { + IoC.BuildUp(result); + result.Completed += completed; + result.Execute(context ?? new CoroutineExecutionContext()); + } + catch (Exception ex) + { + result.Completed -= completed; + taskSource.SetException(ex); + } + + return taskSource.Task; + } } } diff --git a/src/Caliburn.Micro.Core/Result/Extensions/TaskExtensions.cs b/src/Caliburn.Micro.Core/Result/Extensions/TaskExtensions.cs deleted file mode 100644 index 0e3bf182f..000000000 --- a/src/Caliburn.Micro.Core/Result/Extensions/TaskExtensions.cs +++ /dev/null @@ -1,95 +0,0 @@ -namespace Caliburn.Micro -{ - using System; - using System.Threading.Tasks; - - /// - /// Extension methods to bring and together. - /// - public static class TaskExtensions - { - /// - /// Executes an asynchronous. - /// - /// The coroutine to execute. - /// The context to execute the coroutine within. - /// A task that represents the asynchronous coroutine. - public static Task ExecuteAsync(this IResult result, CoroutineExecutionContext context = null) - { - return InternalExecuteAsync(result, context); - } - - /// - /// Executes an asynchronous. - /// - /// The type of the result. - /// The coroutine to execute. - /// The context to execute the coroutine within. - /// A task that represents the asynchronous coroutine. - public static Task ExecuteAsync(this IResult result, - CoroutineExecutionContext context = null) - { - return InternalExecuteAsync(result, context); - } - - private static Task InternalExecuteAsync(IResult result, CoroutineExecutionContext context) - { - var taskSource = new TaskCompletionSource(); - - EventHandler completed = null; - completed = (s, e) => - { - result.Completed -= completed; - - if (e.Error != null) - { - taskSource.SetException(e.Error); - } - else if (e.WasCancelled) - { - taskSource.SetCanceled(); - } - else - { - var rr = result as IResult; - taskSource.SetResult(rr != null ? rr.Result : default(TResult)); - } - }; - - try - { - IoC.BuildUp(result); - result.Completed += completed; - result.Execute(context ?? new CoroutineExecutionContext()); - } - catch (Exception ex) - { - result.Completed -= completed; - taskSource.SetException(ex); - } - - return taskSource.Task; - } - - /// - /// Encapsulates a task inside a couroutine. - /// - /// The task. - /// The coroutine that encapsulates the task. - public static TaskResult AsResult(this Task task) - { - return new TaskResult(task); - } - - /// - /// Encapsulates a task inside a couroutine. - /// - /// The type of the result. - /// The task. - /// The coroutine that encapsulates the task. - public static TaskResult AsResult(this Task task) - { - return new TaskResult(task); - } - } -} diff --git a/src/Caliburn.Micro.Core/Result/Impl/DelegateResult.cs b/src/Caliburn.Micro.Core/Result/Impl/DelegateResult.cs index cc7781995..682ce2b79 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/DelegateResult.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/DelegateResult.cs @@ -43,52 +43,4 @@ public void Execute(CoroutineExecutionContext context) /// public event EventHandler Completed = delegate { }; } - - /// - /// A result that executes a - /// - /// The type of the result. - public class DelegateResult : IResult - { - private readonly Func toExecute; - - /// - /// Initializes a new instance of the class. - /// - /// The action. - public DelegateResult(Func action) - { - toExecute = action; - } - - /// - /// Executes the result using the specified context. - /// - /// The context. - public void Execute(CoroutineExecutionContext context) - { - var eventArgs = new ResultCompletionEventArgs(); - - try - { - Result = toExecute(); - } - catch (Exception ex) - { - eventArgs.Error = ex; - } - - Completed(this, eventArgs); - } - - /// - /// Gets the result. - /// - public TResult Result { get; private set; } - - /// - /// Occurs when execution has completed. - /// - public event EventHandler Completed = delegate { }; - } } diff --git a/src/Caliburn.Micro.Core/Result/Impl/DelegateResult{TResult}.cs b/src/Caliburn.Micro.Core/Result/Impl/DelegateResult{TResult}.cs new file mode 100644 index 000000000..2d4034495 --- /dev/null +++ b/src/Caliburn.Micro.Core/Result/Impl/DelegateResult{TResult}.cs @@ -0,0 +1,52 @@ +using System; + +namespace Caliburn.Micro +{ + /// + /// A result that executes a + /// + /// The type of the result. + public class DelegateResult : IResult + { + private readonly Func toExecute; + + /// + /// Initializes a new instance of the class. + /// + /// The action. + public DelegateResult(Func action) + { + toExecute = action; + } + + /// + /// Executes the result using the specified context. + /// + /// The context. + public void Execute(CoroutineExecutionContext context) + { + var eventArgs = new ResultCompletionEventArgs(); + + try + { + Result = toExecute(); + } + catch (Exception ex) + { + eventArgs.Error = ex; + } + + Completed(this, eventArgs); + } + + /// + /// Gets the result. + /// + public TResult Result { get; private set; } + + /// + /// Occurs when execution has completed. + /// + public event EventHandler Completed = delegate { }; + } +} diff --git a/src/Caliburn.Micro.Core/Result/Impl/TaskResult.cs b/src/Caliburn.Micro.Core/Result/Impl/TaskResult.cs index 8266bafe5..f1c1378ca 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/TaskResult.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/TaskResult.cs @@ -52,39 +52,4 @@ protected virtual void OnCompleted(Task task) /// public event EventHandler Completed = delegate { }; } - - /// - /// A couroutine that encapsulates an . - /// - /// The type of the result. - public class TaskResult : TaskResult, IResult - { - /// - /// Initializes a new instance of the class. - /// - /// The task. - public TaskResult(Task task) - : base(task) - { - } - - /// - /// Gets the result of the asynchronous operation. - /// - public TResult Result { get; private set; } - - /// - /// Called when the asynchronous task has completed. - /// - /// The completed task. - protected override void OnCompleted(Task task) - { - if (!task.IsFaulted && !task.IsCanceled) - { - Result = ((Task)task).Result; - } - - base.OnCompleted(task); - } - } } diff --git a/src/Caliburn.Micro.Core/Result/Impl/TaskResult{TResult}.cs b/src/Caliburn.Micro.Core/Result/Impl/TaskResult{TResult}.cs new file mode 100644 index 000000000..9cd1ad175 --- /dev/null +++ b/src/Caliburn.Micro.Core/Result/Impl/TaskResult{TResult}.cs @@ -0,0 +1,40 @@ +using System; +using System.Threading.Tasks; + +namespace Caliburn.Micro +{ + /// + /// A couroutine that encapsulates an . + /// + /// The type of the result. + public class TaskResult : TaskResult, IResult + { + /// + /// Initializes a new instance of the class. + /// + /// The task. + public TaskResult(Task task) + : base(task) + { + } + + /// + /// Gets the result of the asynchronous operation. + /// + public TResult Result { get; private set; } + + /// + /// Called when the asynchronous task has completed. + /// + /// The completed task. + protected override void OnCompleted(Task task) + { + if (!task.IsFaulted && !task.IsCanceled) + { + Result = ((Task)task).Result; + } + + base.OnCompleted(task); + } + } +} diff --git a/src/Caliburn.Micro.Core/Screen/Contracts/IChild.cs b/src/Caliburn.Micro.Core/Screen/Contracts/IChild.cs index 8081dab0b..a28c88127 100644 --- a/src/Caliburn.Micro.Core/Screen/Contracts/IChild.cs +++ b/src/Caliburn.Micro.Core/Screen/Contracts/IChild.cs @@ -10,16 +10,4 @@ public interface IChild /// object Parent { get; set; } } - - /// - /// Denotes a node within a parent/child hierarchy. - /// - /// The type of parent. - public interface IChild : IChild - { - /// - /// Gets or Sets the Parent - /// - new TParent Parent { get; set; } - } } diff --git a/src/Caliburn.Micro.Core/Screen/Contracts/IChild{TParent}.cs b/src/Caliburn.Micro.Core/Screen/Contracts/IChild{TParent}.cs new file mode 100644 index 000000000..70b62c079 --- /dev/null +++ b/src/Caliburn.Micro.Core/Screen/Contracts/IChild{TParent}.cs @@ -0,0 +1,14 @@ +namespace Caliburn.Micro +{ + /// + /// Denotes a node within a parent/child hierarchy. + /// + /// The type of parent. + public interface IChild : IChild + { + /// + /// Gets or Sets the Parent + /// + new TParent Parent { get; set; } + } +} From 81214f5e4abb9ef77f9c6ec74c2d3ec18d9d7288 Mon Sep 17 00:00:00 2001 From: khaled Date: Sat, 7 Oct 2023 03:50:25 +0200 Subject: [PATCH 03/14] - Removed region from WeakValueDictionary.cs. - Code Refactoring applied for : * Use expression body for constructor. * Use expression body for methods. * Use expression body for property. * Use local function. * Use pattern matching * Inline variable declaration. * Inline temporary variable. * Fixing IDE1006 Naming rule violation: Missing prefix:'_'. * Fixing IDE0008 Use explicit type instead of 'var'. * Fixing IDE0059 Unnecessary assignment of value, Use discard * Fixing IDE0003 Name can be simplified, Remove 'this' qualification. * Fixing IDE0016 Null check can be simplified, Use 'throw' expression. * Fixing IDE0034 'default' expression can be simplified. * Fixing IDE0090 'new' expression can be simplified. * Fixing IDE0074 Use compound assignment. * Fixing IDE0044 Make field readonly. --- .../Conductor/Base/ConductorBase.cs | 17 +- .../Conductor/Conductor.cs | 23 +-- .../ConductorWithCollectionAllActive.cs | 66 ++++---- .../ConductorWithCollectionOneActive.cs | 68 ++++---- .../DefaultImpl/DefaultCloseStrategy.cs | 11 +- .../Coroutine/ExtensionPoints/Coroutine.cs | 12 +- .../EventAggregator/EventAggregator.cs | 28 ++-- .../Extensions/EventAggregatorExtensions.cs | 146 +++++++---------- .../Extensions/EnumerableExtensions.cs | 2 +- src/Caliburn.Micro.Core/Extensions/Execute.cs | 23 +-- .../Extensions/ExpressionExtensions.cs | 3 +- .../IoC/ExtensionPoints/IoC.cs | 10 +- .../IoC/Extensions/ContainerExtensions.cs | 41 ++--- .../IoC/SimpleContainer.cs | 99 +++++------- .../Logging/Impl/DebugLog.cs | 22 +-- .../DefaultImpl/DefaultPlatformProvider.cs | 40 +---- .../Result/Extensions/ResultExtensions.cs | 54 ++----- .../Result/Impl/ContinueResultDecorator.cs | 15 +- .../Result/Impl/DelegateResult.cs | 9 +- .../Result/Impl/DelegateResult{TResult}.cs | 9 +- .../Result/Impl/RescueResultDecorator.cs | 15 +- .../Result/Impl/ResultDecoratorBase.cs | 30 ++-- .../Result/Impl/SequentialResult.cs | 22 ++- .../Result/Impl/SimpleResult.cs | 28 +--- .../Result/Impl/TaskResult.cs | 18 +-- .../Screen/Extensions/ScreenExtensions.cs | 40 +---- src/Caliburn.Micro.Core/Screen/Screen.cs | 32 +--- .../Types/BindableCollection.cs | 39 ++--- .../Types/PropertyChangedBase.cs | 20 +-- .../Types/WeakValueDictionary.cs | 149 +++++------------- .../ViewAware/ViewAware.cs | 30 ++-- 31 files changed, 362 insertions(+), 759 deletions(-) diff --git a/src/Caliburn.Micro.Core/Conductor/Base/ConductorBase.cs b/src/Caliburn.Micro.Core/Conductor/Base/ConductorBase.cs index aa7443907..8622fe9b7 100644 --- a/src/Caliburn.Micro.Core/Conductor/Base/ConductorBase.cs +++ b/src/Caliburn.Micro.Core/Conductor/Base/ConductorBase.cs @@ -20,19 +20,13 @@ public abstract class ConductorBase : Screen, IConductor, IParent where T /// The close strategy. public ICloseStrategy CloseStrategy { - get => _closeStrategy ?? (_closeStrategy = new DefaultCloseStrategy()); + get => _closeStrategy ??= new DefaultCloseStrategy(); set => _closeStrategy = value; } - Task IConductor.DeactivateItemAsync(object item, bool close, CancellationToken cancellationToken) - { - return DeactivateItemAsync((T)item, close, cancellationToken); - } + Task IConductor.DeactivateItemAsync(object item, bool close, CancellationToken cancellationToken) => DeactivateItemAsync((T)item, close, cancellationToken); - IEnumerable IParent.GetChildren() - { - return GetChildren(); - } + IEnumerable IParent.GetChildren() => GetChildren(); /// /// Occurs when an activation request is processed. @@ -45,10 +39,7 @@ IEnumerable IParent.GetChildren() /// The collection of children. public abstract IEnumerable GetChildren(); - Task IConductor.ActivateItemAsync(object item, CancellationToken cancellationToken) - { - return ActivateItemAsync((T)item, cancellationToken); - } + Task IConductor.ActivateItemAsync(object item, CancellationToken cancellationToken) => ActivateItemAsync((T)item, cancellationToken); /// /// Activates the specified item. diff --git a/src/Caliburn.Micro.Core/Conductor/Conductor.cs b/src/Caliburn.Micro.Core/Conductor/Conductor.cs index c95033128..9421ebc7d 100644 --- a/src/Caliburn.Micro.Core/Conductor/Conductor.cs +++ b/src/Caliburn.Micro.Core/Conductor/Conductor.cs @@ -22,7 +22,7 @@ public override async Task ActivateItemAsync(T item, CancellationToken cancellat return; } - var closeResult = await CloseStrategy.ExecuteAsync(new[] { ActiveItem }, cancellationToken); + ICloseResult closeResult = await CloseStrategy.ExecuteAsync(new[] { ActiveItem }, cancellationToken); if (closeResult.CloseCanOccur) { @@ -48,11 +48,11 @@ public override async Task DeactivateItemAsync(T item, bool close, CancellationT return; } - var closeResult = await CloseStrategy.ExecuteAsync(new[] { ActiveItem }, CancellationToken.None); + ICloseResult closeResult = await CloseStrategy.ExecuteAsync(new[] { ActiveItem }, CancellationToken.None); if (closeResult.CloseCanOccur) { - await ChangeActiveItemAsync(default(T), close); + await ChangeActiveItemAsync(default, close); } } @@ -63,7 +63,7 @@ public override async Task DeactivateItemAsync(T item, bool close, CancellationT /// A task that represents the asynchronous operation. public override async Task CanCloseAsync(CancellationToken cancellationToken = default ) { - var closeResult = await CloseStrategy.ExecuteAsync(new[] { ActiveItem }, cancellationToken); + ICloseResult closeResult = await CloseStrategy.ExecuteAsync(new[] { ActiveItem }, cancellationToken); return closeResult.CloseCanOccur; } @@ -72,10 +72,7 @@ public override async Task DeactivateItemAsync(T item, bool close, CancellationT /// Called when activating. /// /// A task that represents the asynchronous operation. - protected override Task OnActivateAsync(CancellationToken cancellationToken) - { - return ScreenExtensions.TryActivateAsync(ActiveItem, cancellationToken); - } + protected override Task OnActivateAsync(CancellationToken cancellationToken) => ScreenExtensions.TryActivateAsync(ActiveItem, cancellationToken); /// /// Called when deactivating. @@ -83,18 +80,12 @@ protected override Task OnActivateAsync(CancellationToken cancellationToken) /// Indicates whether this instance will be closed. /// The cancellation token to cancel operation. /// A task that represents the asynchronous operation. - protected override Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) - { - return ScreenExtensions.TryDeactivateAsync(ActiveItem, close, cancellationToken); - } + protected override Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) => ScreenExtensions.TryDeactivateAsync(ActiveItem, close, cancellationToken); /// /// Gets the children. /// /// The collection of children. - public override IEnumerable GetChildren() - { - return new[] { ActiveItem }; - } + public override IEnumerable GetChildren() => new[] { ActiveItem }; } } diff --git a/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionAllActive.cs b/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionAllActive.cs index 610dcbea9..14b8ae93f 100644 --- a/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionAllActive.cs +++ b/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionAllActive.cs @@ -20,7 +20,7 @@ public partial class Collection /// public class AllActive : ConductorBase { - private readonly BindableCollection _items = new BindableCollection(); + private readonly BindableCollection _items = new(); private readonly bool _openPublicItems; /// @@ -28,36 +28,30 @@ public class AllActive : ConductorBase /// /// if set to true opens public items that are properties of this class. public AllActive(bool openPublicItems) - : this() - { - _openPublicItems = openPublicItems; - } + : this() => _openPublicItems = openPublicItems; /// /// Initializes a new instance of the class. /// - public AllActive() - { - _items.CollectionChanged += (s, e) => - { - switch (e.Action) - { - case NotifyCollectionChangedAction.Add: - e.NewItems.OfType().Apply(x => x.Parent = this); - break; - case NotifyCollectionChangedAction.Remove: - e.OldItems.OfType().Apply(x => x.Parent = null); - break; - case NotifyCollectionChangedAction.Replace: - e.NewItems.OfType().Apply(x => x.Parent = this); - e.OldItems.OfType().Apply(x => x.Parent = null); - break; - case NotifyCollectionChangedAction.Reset: - _items.OfType().Apply(x => x.Parent = this); - break; - } - }; - } + public AllActive() => _items.CollectionChanged += (s, e) => + { + switch (e.Action) + { + case NotifyCollectionChangedAction.Add: + e.NewItems.OfType().Apply(x => x.Parent = this); + break; + case NotifyCollectionChangedAction.Remove: + e.OldItems.OfType().Apply(x => x.Parent = null); + break; + case NotifyCollectionChangedAction.Replace: + e.NewItems.OfType().Apply(x => x.Parent = this); + e.OldItems.OfType().Apply(x => x.Parent = null); + break; + case NotifyCollectionChangedAction.Reset: + _items.OfType().Apply(x => x.Parent = this); + break; + } + }; /// /// Gets the items that are currently being conducted. @@ -67,10 +61,7 @@ public AllActive() /// /// Called when activating. /// - protected override Task OnActivateAsync(CancellationToken cancellationToken) - { - return Task.WhenAll(_items.OfType().Select(x => x.ActivateAsync(cancellationToken))); - } + protected override Task OnActivateAsync(CancellationToken cancellationToken) => Task.WhenAll(_items.OfType().Select(x => x.ActivateAsync(cancellationToken))); /// /// Called when deactivating. @@ -80,7 +71,7 @@ protected override Task OnActivateAsync(CancellationToken cancellationToken) /// A task that represents the asynchronous operation. protected override async Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) { - foreach(var deactivate in _items.OfType()) + foreach(IDeactivate deactivate in _items.OfType()) { await deactivate.DeactivateAsync(close, cancellationToken); } @@ -96,11 +87,11 @@ protected override async Task OnDeactivateAsync(bool close, CancellationToken ca /// A task that represents the asynchronous operation. public override async Task CanCloseAsync(CancellationToken cancellationToken = default) { - var closeResult = await CloseStrategy.ExecuteAsync(_items.ToList(), cancellationToken); + ICloseResult closeResult = await CloseStrategy.ExecuteAsync(_items.ToList(), cancellationToken); if (!closeResult.CloseCanOccur && closeResult.Children.Any()) { - foreach (var deactivate in closeResult.Children.OfType()) + foreach (IDeactivate deactivate in closeResult.Children.OfType()) { await deactivate.DeactivateAsync(true, cancellationToken); } @@ -157,7 +148,7 @@ public override async Task DeactivateItemAsync(T item, bool close, CancellationT if (close) { - var closeResult = await CloseStrategy.ExecuteAsync(new[] { item }, CancellationToken.None); + ICloseResult closeResult = await CloseStrategy.ExecuteAsync(new[] { item }, CancellationToken.None); if (closeResult.CloseCanOccur) await CloseItemCoreAsync(item, cancellationToken); @@ -170,10 +161,7 @@ public override async Task DeactivateItemAsync(T item, bool close, CancellationT /// Gets the children. /// /// The collection of children. - public override IEnumerable GetChildren() - { - return _items; - } + public override IEnumerable GetChildren() => _items; private async Task CloseItemCoreAsync(T item, CancellationToken cancellationToken = default) { diff --git a/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionOneActive.cs b/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionOneActive.cs index e871e216b..5039f2762 100644 --- a/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionOneActive.cs +++ b/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionOneActive.cs @@ -18,33 +18,30 @@ public partial class Collection /// public class OneActive : ConductorBaseWithActiveItem { - private readonly BindableCollection _items = new BindableCollection(); + private readonly BindableCollection _items = new(); /// /// Initializes a new instance of the class. /// - public OneActive() - { - _items.CollectionChanged += (s, e) => - { - switch (e.Action) - { - case NotifyCollectionChangedAction.Add: - e.NewItems.OfType().Apply(x => x.Parent = this); - break; - case NotifyCollectionChangedAction.Remove: - e.OldItems.OfType().Apply(x => x.Parent = null); - break; - case NotifyCollectionChangedAction.Replace: - e.NewItems.OfType().Apply(x => x.Parent = this); - e.OldItems.OfType().Apply(x => x.Parent = null); - break; - case NotifyCollectionChangedAction.Reset: - _items.OfType().Apply(x => x.Parent = this); - break; - } - }; - } + public OneActive() => _items.CollectionChanged += (s, e) => + { + switch (e.Action) + { + case NotifyCollectionChangedAction.Add: + e.NewItems.OfType().Apply(x => x.Parent = this); + break; + case NotifyCollectionChangedAction.Remove: + e.OldItems.OfType().Apply(x => x.Parent = null); + break; + case NotifyCollectionChangedAction.Replace: + e.NewItems.OfType().Apply(x => x.Parent = this); + e.OldItems.OfType().Apply(x => x.Parent = null); + break; + case NotifyCollectionChangedAction.Reset: + _items.OfType().Apply(x => x.Parent = this); + break; + } + }; /// /// Gets the items that are currently being conducted. @@ -95,7 +92,7 @@ public override async Task DeactivateItemAsync(T item, bool close, CancellationT await ScreenExtensions.TryDeactivateAsync(item, false, cancellationToken); else { - var closeResult = await CloseStrategy.ExecuteAsync(new[] { item }, CancellationToken.None); + ICloseResult closeResult = await CloseStrategy.ExecuteAsync(new[] { item }, CancellationToken.None); if (closeResult.CloseCanOccur) await CloseItemCoreAsync(item, cancellationToken); @@ -107,7 +104,7 @@ private async Task CloseItemCoreAsync(T item, CancellationToken cancellationToke if (item.Equals(ActiveItem)) { var index = _items.IndexOf(item); - var next = DetermineNextItemToActivate(_items, index); + T next = DetermineNextItemToActivate(_items, index); await ChangeActiveItemAsync(next, true); } @@ -136,7 +133,7 @@ protected virtual T DetermineNextItemToActivate(IList list, int lastIndex) if (toRemoveAt > -1 && toRemoveAt < list.Count - 1) return list[toRemoveAt]; - return default(T); + return default; } /// @@ -146,24 +143,24 @@ protected virtual T DetermineNextItemToActivate(IList list, int lastIndex) /// A task that represents the asynchronous operation. public override async Task CanCloseAsync(CancellationToken cancellationToken = default) { - var closeResult = await CloseStrategy.ExecuteAsync(_items.ToList(), cancellationToken); + ICloseResult closeResult = await CloseStrategy.ExecuteAsync(_items.ToList(), cancellationToken); if (!closeResult.CloseCanOccur && closeResult.Children.Any()) { - var closable = closeResult.Children; + IEnumerable closable = closeResult.Children; if (closable.Contains(ActiveItem)) { var list = _items.ToList(); - var next = ActiveItem; + T next = ActiveItem; do { - var previous = next; + T previous = next; next = DetermineNextItemToActivate(list, list.IndexOf(previous)); list.Remove(previous); } while (closable.Contains(next)); - var previousActive = ActiveItem; + T previousActive = ActiveItem; await ChangeActiveItemAsync(next, true); _items.Remove(previousActive); @@ -172,7 +169,7 @@ public override async Task CanCloseAsync(CancellationToken cancellationTok closable = stillToClose; } - foreach(var deactivate in closable.OfType()) + foreach(IDeactivate deactivate in closable.OfType()) { await deactivate.DeactivateAsync(true, cancellationToken); } @@ -188,10 +185,7 @@ public override async Task CanCloseAsync(CancellationToken cancellationTok /// /// The cancellation token to cancel operation. /// A task that represents the asynchronous operation. - protected override Task OnActivateAsync(CancellationToken cancellationToken) - { - return ScreenExtensions.TryActivateAsync(ActiveItem, cancellationToken); - } + protected override Task OnActivateAsync(CancellationToken cancellationToken) => ScreenExtensions.TryActivateAsync(ActiveItem, cancellationToken); /// /// Called when deactivating. @@ -203,7 +197,7 @@ protected override async Task OnDeactivateAsync(bool close, CancellationToken ca { if (close) { - foreach (var deactivate in _items.OfType()) + foreach (IDeactivate deactivate in _items.OfType()) { await deactivate.DeactivateAsync(true, cancellationToken); } diff --git a/src/Caliburn.Micro.Core/Conductor/DefaultImpl/DefaultCloseStrategy.cs b/src/Caliburn.Micro.Core/Conductor/DefaultImpl/DefaultCloseStrategy.cs index e5d7263f9..df918e2a0 100644 --- a/src/Caliburn.Micro.Core/Conductor/DefaultImpl/DefaultCloseStrategy.cs +++ b/src/Caliburn.Micro.Core/Conductor/DefaultImpl/DefaultCloseStrategy.cs @@ -10,16 +10,13 @@ namespace Caliburn.Micro /// The type of child element. public class DefaultCloseStrategy : ICloseStrategy { - readonly bool closeConductedItemsWhenConductorCannotClose; + readonly bool _closeConductedItemsWhenConductorCannotClose; /// /// Creates an instance of the class. /// /// Indicates that even if all conducted items are not closable, those that are should be closed. The default is FALSE. - public DefaultCloseStrategy(bool closeConductedItemsWhenConductorCannotClose = false) - { - this.closeConductedItemsWhenConductorCannotClose = closeConductedItemsWhenConductorCannotClose; - } + public DefaultCloseStrategy(bool closeConductedItemsWhenConductorCannotClose = false) => _closeConductedItemsWhenConductorCannotClose = closeConductedItemsWhenConductorCannotClose; /// public async Task> ExecuteAsync(IEnumerable toClose, CancellationToken cancellationToken = default) @@ -27,7 +24,7 @@ public async Task> ExecuteAsync(IEnumerable toClose, Cancella var closeable = new List(); var closeCanOccur = true; - foreach(var child in toClose) + foreach(T child in toClose) { if (child is IGuardClose guard) { @@ -46,7 +43,7 @@ public async Task> ExecuteAsync(IEnumerable toClose, Cancella } } - if (!this.closeConductedItemsWhenConductorCannotClose && !closeCanOccur) + if (!_closeConductedItemsWhenConductorCannotClose && !closeCanOccur) { closeable.Clear(); } diff --git a/src/Caliburn.Micro.Core/Coroutine/ExtensionPoints/Coroutine.cs b/src/Caliburn.Micro.Core/Coroutine/ExtensionPoints/Coroutine.cs index 2b357960c..90fce9420 100644 --- a/src/Caliburn.Micro.Core/Coroutine/ExtensionPoints/Coroutine.cs +++ b/src/Caliburn.Micro.Core/Coroutine/ExtensionPoints/Coroutine.cs @@ -26,7 +26,7 @@ public static void BeginExecute(IEnumerator coroutine, CoroutineExecuti { Log.Info("Executing coroutine."); - var enumerator = CreateParentEnumerator(coroutine); + IResult enumerator = CreateParentEnumerator(coroutine); IoC.BuildUp(enumerator); if (callback != null) @@ -69,13 +69,13 @@ public static Task ExecuteAsync(IEnumerator coroutine, CoroutineExecuti private static void ExecuteOnCompleted(IResult result, EventHandler handler) { - EventHandler onCompledted = null; - onCompledted = (s, e) => + void OnCompledted(object s, ResultCompletionEventArgs e) { - result.Completed -= onCompledted; + result.Completed -= OnCompledted; handler(s, e); - }; - result.Completed += onCompledted; + } + + result.Completed += OnCompledted; } /// diff --git a/src/Caliburn.Micro.Core/EventAggregator/EventAggregator.cs b/src/Caliburn.Micro.Core/EventAggregator/EventAggregator.cs index 2143c074a..cf8176e3e 100644 --- a/src/Caliburn.Micro.Core/EventAggregator/EventAggregator.cs +++ b/src/Caliburn.Micro.Core/EventAggregator/EventAggregator.cs @@ -10,7 +10,7 @@ namespace Caliburn.Micro /// public class EventAggregator : IEventAggregator { - private readonly List _handlers = new List(); + private readonly List _handlers = new(); /// public virtual bool HandlerExistsFor(Type messageType) @@ -55,7 +55,7 @@ public virtual void Unsubscribe(object subscriber) lock (_handlers) { - var found = _handlers.FirstOrDefault(x => x.Matches(subscriber)); + Handler found = _handlers.FirstOrDefault(x => x.Matches(subscriber)); if (found != null) { @@ -86,9 +86,9 @@ public virtual Task PublishAsync(object message, Func, Task> marshal, return marshal(async () => { - var messageType = message.GetType(); + Type messageType = message.GetType(); - var tasks = toNotify.Select(h => h.Handle(messageType, message, cancellationToken)); + IEnumerable tasks = toNotify.Select(h => h.Handle(messageType, message, cancellationToken)); await Task.WhenAll(tasks); @@ -108,7 +108,7 @@ private class Handler { private readonly Func, Task> _marshal; private readonly WeakReference _reference; - private readonly Dictionary _supportedHandlers = new Dictionary(); + private readonly Dictionary _supportedHandlers = new(); public Handler(object handler, Func, Task> marshal) { @@ -118,13 +118,13 @@ public Handler(object handler, Func, Task> marshal) //var interfaces = handler.GetType().GetTypeInfo().ImplementedInterfaces // .Where(x => typeof(IHandle).GetTypeInfo().IsAssignableFrom(x.GetTypeInfo()) && x.GetTypeInfo().IsGenericType); - var interfaces = handler.GetType().GetTypeInfo().ImplementedInterfaces + IEnumerable interfaces = handler.GetType().GetTypeInfo().ImplementedInterfaces .Where(x => x.GetTypeInfo().IsGenericType && x.GetGenericTypeDefinition() == typeof(IHandle<>)); - foreach (var @interface in interfaces) + foreach (Type @interface in interfaces) { - var type = @interface.GetTypeInfo().GenericTypeArguments[0]; - var method = @interface.GetRuntimeMethod("HandleAsync", new[] { type, typeof(CancellationToken) }); + Type type = @interface.GetTypeInfo().GenericTypeArguments[0]; + MethodInfo method = @interface.GetRuntimeMethod("HandleAsync", new[] { type, typeof(CancellationToken) }); if (method != null) { @@ -135,10 +135,7 @@ public Handler(object handler, Func, Task> marshal) public bool IsDead => _reference.Target == null; - public bool Matches(object instance) - { - return _reference.Target == instance; - } + public bool Matches(object instance) => _reference.Target == instance; public Task Handle(Type messageType, object message, CancellationToken cancellationToken) { @@ -161,10 +158,7 @@ public Task Handle(Type messageType, object message, CancellationToken cancellat }); } - public bool Handles(Type messageType) - { - return _supportedHandlers.Any(pair => pair.Key.GetTypeInfo().IsAssignableFrom(messageType.GetTypeInfo())); - } + public bool Handles(Type messageType) => _supportedHandlers.Any(pair => pair.Key.GetTypeInfo().IsAssignableFrom(messageType.GetTypeInfo())); } } } diff --git a/src/Caliburn.Micro.Core/EventAggregator/Extensions/EventAggregatorExtensions.cs b/src/Caliburn.Micro.Core/EventAggregator/Extensions/EventAggregatorExtensions.cs index f920275ed..075ca5dbc 100644 --- a/src/Caliburn.Micro.Core/EventAggregator/Extensions/EventAggregatorExtensions.cs +++ b/src/Caliburn.Micro.Core/EventAggregator/Extensions/EventAggregatorExtensions.cs @@ -15,10 +15,7 @@ public static class EventAggregatorExtensions /// The subscription is invoked on the thread chosen by the publisher. /// /// The instance to subscribe for event publication. - public static void SubscribeOnPublishedThread(this IEventAggregator eventAggregator, object subscriber) - { - eventAggregator.Subscribe(subscriber, f => f()); - } + public static void SubscribeOnPublishedThread(this IEventAggregator eventAggregator, object subscriber) => eventAggregator.Subscribe(subscriber, f => f()); /// /// Subscribes an instance to all events declared through implementations of . @@ -27,10 +24,7 @@ public static void SubscribeOnPublishedThread(this IEventAggregator eventAggrega /// /// The instance to subscribe for event publication. [Obsolete("Use SubscribeOnPublishedThread")] - public static void Subscribe(this IEventAggregator eventAggregator, object subscriber) - { - eventAggregator.SubscribeOnPublishedThread(subscriber); - } + public static void Subscribe(this IEventAggregator eventAggregator, object subscriber) => eventAggregator.SubscribeOnPublishedThread(subscriber); /// /// Subscribes an instance to all events declared through implementations of . @@ -38,10 +32,7 @@ public static void Subscribe(this IEventAggregator eventAggregator, object subsc /// The subscription is invoked on a new background thread. /// /// The instance to subscribe for event publication. - public static void SubscribeOnBackgroundThread(this IEventAggregator eventAggregator, object subscriber) - { - eventAggregator.Subscribe(subscriber, f => Task.Factory.StartNew(f, default, TaskCreationOptions.None, TaskScheduler.Default)); - } + public static void SubscribeOnBackgroundThread(this IEventAggregator eventAggregator, object subscriber) => eventAggregator.Subscribe(subscriber, f => Task.Factory.StartNew(f, default, TaskCreationOptions.None, TaskScheduler.Default)); /// /// Subscribes an instance to all events declared through implementations of . @@ -49,34 +40,31 @@ public static void SubscribeOnBackgroundThread(this IEventAggregator eventAggreg /// The subscription is invoked on the UI thread. /// /// The instance to subscribe for event publication. - public static void SubscribeOnUIThread(this IEventAggregator eventAggregator, object subscriber) - { - eventAggregator.Subscribe(subscriber, f => - { - var taskCompletionSource = new TaskCompletionSource(); - - Execute.BeginOnUIThread(async () => - { - try - { - await f(); - - taskCompletionSource.SetResult(true); - } - catch (OperationCanceledException) - { - taskCompletionSource.SetCanceled(); - } - catch (Exception ex) - { - taskCompletionSource.SetException(ex); - } - }); - - return taskCompletionSource.Task; - - }); - } + public static void SubscribeOnUIThread(this IEventAggregator eventAggregator, object subscriber) => eventAggregator.Subscribe(subscriber, f => + { + var taskCompletionSource = new TaskCompletionSource(); + + Execute.BeginOnUIThread(async () => + { + try + { + await f(); + + taskCompletionSource.SetResult(true); + } + catch (OperationCanceledException) + { + taskCompletionSource.SetCanceled(); + } + catch (Exception ex) + { + taskCompletionSource.SetException(ex); + } + }); + + return taskCompletionSource.Task; + + }); /// /// Publishes a message on the current thread (synchrone). @@ -85,10 +73,7 @@ public static void SubscribeOnUIThread(this IEventAggregator eventAggregator, ob /// The message instance. /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// A task that represents the asynchronous operation. - public static Task PublishOnCurrentThreadAsync(this IEventAggregator eventAggregator, object message, CancellationToken cancellationToken) - { - return eventAggregator.PublishAsync(message, f => f(), cancellationToken); - } + public static Task PublishOnCurrentThreadAsync(this IEventAggregator eventAggregator, object message, CancellationToken cancellationToken) => eventAggregator.PublishAsync(message, f => f(), cancellationToken); /// /// Publishes a message on the current thread (synchrone). @@ -96,10 +81,7 @@ public static Task PublishOnCurrentThreadAsync(this IEventAggregator eventAggreg /// The event aggregator. /// The message instance. /// A task that represents the asynchronous operation. - public static Task PublishOnCurrentThreadAsync(this IEventAggregator eventAggregator, object message) - { - return eventAggregator.PublishOnCurrentThreadAsync(message, default); - } + public static Task PublishOnCurrentThreadAsync(this IEventAggregator eventAggregator, object message) => eventAggregator.PublishOnCurrentThreadAsync(message, default); /// /// Publishes a message on a background thread (async). @@ -108,10 +90,7 @@ public static Task PublishOnCurrentThreadAsync(this IEventAggregator eventAggreg /// The message instance. /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// A task that represents the asynchronous operation. - public static Task PublishOnBackgroundThreadAsync(this IEventAggregator eventAggregator, object message, CancellationToken cancellationToken) - { - return eventAggregator.PublishAsync(message, f => Task.Factory.StartNew(f, default, TaskCreationOptions.None, TaskScheduler.Default), cancellationToken); - } + public static Task PublishOnBackgroundThreadAsync(this IEventAggregator eventAggregator, object message, CancellationToken cancellationToken) => eventAggregator.PublishAsync(message, f => Task.Factory.StartNew(f, default, TaskCreationOptions.None, TaskScheduler.Default), cancellationToken); /// /// Publishes a message on a background thread (async). @@ -119,10 +98,7 @@ public static Task PublishOnBackgroundThreadAsync(this IEventAggregator eventAgg /// The event aggregator. /// The message instance. /// A task that represents the asynchronous operation. - public static Task PublishOnBackgroundThreadAsync(this IEventAggregator eventAggregator, object message) - { - return eventAggregator.PublishOnBackgroundThreadAsync(message, default); - } + public static Task PublishOnBackgroundThreadAsync(this IEventAggregator eventAggregator, object message) => eventAggregator.PublishOnBackgroundThreadAsync(message, default); /// /// Publishes a message on the UI thread. @@ -131,34 +107,31 @@ public static Task PublishOnBackgroundThreadAsync(this IEventAggregator eventAgg /// The message instance. /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// A task that represents the asynchronous operation. - public static Task PublishOnUIThreadAsync(this IEventAggregator eventAggregator, object message, CancellationToken cancellationToken) - { - return eventAggregator.PublishAsync(message, f => - { - var taskCompletionSource = new TaskCompletionSource(); - - Execute.BeginOnUIThread(async () => - { - try - { - await f(); - - taskCompletionSource.SetResult(true); - } - catch (OperationCanceledException) - { - taskCompletionSource.SetCanceled(); - } - catch (Exception ex) - { - taskCompletionSource.SetException(ex); - } - }); - - return taskCompletionSource.Task; - - }, cancellationToken); - } + public static Task PublishOnUIThreadAsync(this IEventAggregator eventAggregator, object message, CancellationToken cancellationToken) => eventAggregator.PublishAsync(message, f => + { + var taskCompletionSource = new TaskCompletionSource(); + + Execute.BeginOnUIThread(async () => + { + try + { + await f(); + + taskCompletionSource.SetResult(true); + } + catch (OperationCanceledException) + { + taskCompletionSource.SetCanceled(); + } + catch (Exception ex) + { + taskCompletionSource.SetException(ex); + } + }); + + return taskCompletionSource.Task; + + }, cancellationToken); /// /// Publishes a message on the UI thread. @@ -166,9 +139,6 @@ public static Task PublishOnUIThreadAsync(this IEventAggregator eventAggregator, /// The event aggregator. /// The message instance. /// A task that represents the asynchronous operation. - public static Task PublishOnUIThreadAsync(this IEventAggregator eventAggregator, object message) - { - return eventAggregator.PublishOnUIThreadAsync(message, default); - } + public static Task PublishOnUIThreadAsync(this IEventAggregator eventAggregator, object message) => eventAggregator.PublishOnUIThreadAsync(message, default); } } diff --git a/src/Caliburn.Micro.Core/Extensions/EnumerableExtensions.cs b/src/Caliburn.Micro.Core/Extensions/EnumerableExtensions.cs index da03243ce..727f3d34b 100644 --- a/src/Caliburn.Micro.Core/Extensions/EnumerableExtensions.cs +++ b/src/Caliburn.Micro.Core/Extensions/EnumerableExtensions.cs @@ -16,7 +16,7 @@ public static class EnumerableExtensions /// The action to apply to each item in the list. public static void Apply(this IEnumerable enumerable, Action action) { - foreach (var item in enumerable) + foreach (T item in enumerable) { action(item); } diff --git a/src/Caliburn.Micro.Core/Extensions/Execute.cs b/src/Caliburn.Micro.Core/Extensions/Execute.cs index 8aec3a143..4a232b117 100644 --- a/src/Caliburn.Micro.Core/Extensions/Execute.cs +++ b/src/Caliburn.Micro.Core/Extensions/Execute.cs @@ -11,39 +11,24 @@ public static class Execute /// /// Indicates whether or not the framework is in design-time mode. /// - public static bool InDesignMode - { - get - { - return PlatformProvider.Current.InDesignMode; - } - } + public static bool InDesignMode => PlatformProvider.Current.InDesignMode; /// /// Executes the action on the UI thread asynchronously. /// /// The action to execute. - public static void BeginOnUIThread(this Action action) - { - PlatformProvider.Current.BeginOnUIThread(action); - } + public static void BeginOnUIThread(this Action action) => PlatformProvider.Current.BeginOnUIThread(action); /// /// Executes the action on the UI thread asynchronously. /// /// The action to execute. - public static Task OnUIThreadAsync(this Func action) - { - return PlatformProvider.Current.OnUIThreadAsync(action); - } + public static Task OnUIThreadAsync(this Func action) => PlatformProvider.Current.OnUIThreadAsync(action); /// /// Executes the action on the UI thread. /// /// The action to execute. - public static void OnUIThread(this Action action) - { - PlatformProvider.Current.OnUIThread(action); - } + public static void OnUIThread(this Action action) => PlatformProvider.Current.OnUIThread(action); } } diff --git a/src/Caliburn.Micro.Core/Extensions/ExpressionExtensions.cs b/src/Caliburn.Micro.Core/Extensions/ExpressionExtensions.cs index 047202d9e..8ef0e5b95 100644 --- a/src/Caliburn.Micro.Core/Extensions/ExpressionExtensions.cs +++ b/src/Caliburn.Micro.Core/Extensions/ExpressionExtensions.cs @@ -18,9 +18,8 @@ public static MemberInfo GetMemberInfo(this Expression expression) var lambda = (LambdaExpression)expression; MemberExpression memberExpression; - if (lambda.Body is UnaryExpression) + if (lambda.Body is UnaryExpression unaryExpression) { - var unaryExpression = (UnaryExpression)lambda.Body; memberExpression = (MemberExpression)unaryExpression.Operand; } else diff --git a/src/Caliburn.Micro.Core/IoC/ExtensionPoints/IoC.cs b/src/Caliburn.Micro.Core/IoC/ExtensionPoints/IoC.cs index a060db170..fa91dd05b 100644 --- a/src/Caliburn.Micro.Core/IoC/ExtensionPoints/IoC.cs +++ b/src/Caliburn.Micro.Core/IoC/ExtensionPoints/IoC.cs @@ -30,19 +30,13 @@ public static class IoC /// The type to resolve. /// The key to look up. /// The resolved instance. - public static T Get(string key = null) - { - return (T)GetInstance(typeof(T), key); - } + public static T Get(string key = null) => (T)GetInstance(typeof(T), key); /// /// Gets all instances of a particular type. /// /// The type to resolve. /// The resolved instances. - public static IEnumerable GetAll() - { - return GetAllInstances(typeof(T)).Cast(); - } + public static IEnumerable GetAll() => GetAllInstances(typeof(T)).Cast(); } } diff --git a/src/Caliburn.Micro.Core/IoC/Extensions/ContainerExtensions.cs b/src/Caliburn.Micro.Core/IoC/Extensions/ContainerExtensions.cs index bd8140d15..d35c00fb8 100644 --- a/src/Caliburn.Micro.Core/IoC/Extensions/ContainerExtensions.cs +++ b/src/Caliburn.Micro.Core/IoC/Extensions/ContainerExtensions.cs @@ -17,10 +17,7 @@ public static class ContainerExtensions /// The container. /// The key. /// The container. - public static SimpleContainer Singleton(this SimpleContainer container, string key = null) - { - return Singleton(container, key); - } + public static SimpleContainer Singleton(this SimpleContainer container, string key = null) => Singleton(container, key); /// /// Registers a singleton. @@ -44,10 +41,7 @@ public static SimpleContainer Singleton(this SimpleCo /// The container. /// The key. /// The container. - public static SimpleContainer PerRequest(this SimpleContainer container, string key = null) - { - return PerRequest(container, key); - } + public static SimpleContainer PerRequest(this SimpleContainer container, string key = null) => PerRequest(container, key); /// /// Registers an service to be created on each request. @@ -102,20 +96,17 @@ public static SimpleContainer Handler(this SimpleContainer container, public static SimpleContainer AllTypesOf(this SimpleContainer container, Assembly assembly, Func filter = null) { - if (filter == null) - { - filter = type => true; - } + filter ??= type => true; - var serviceType = typeof(TService); - var types = from type in assembly.DefinedTypes + Type serviceType = typeof(TService); + IEnumerable types = from type in assembly.DefinedTypes where serviceType.GetTypeInfo().IsAssignableFrom(type) && !type.IsAbstract && !type.IsInterface && filter(type.AsType()) select type; - foreach (var type in types) + foreach (TypeInfo type in types) { container.RegisterSingleton(typeof(TService), null, type.AsType()); } @@ -130,10 +121,7 @@ where serviceType.GetTypeInfo().IsAssignableFrom(type) /// The container. /// The key. /// The instance. - public static TService GetInstance(this SimpleContainer container, string key = null) - { - return (TService)container.GetInstance(typeof(TService), key); - } + public static TService GetInstance(this SimpleContainer container, string key = null) => (TService)container.GetInstance(typeof(TService), key); /// /// Gets all instances of a particular type and the given key (default null). @@ -142,10 +130,7 @@ public static TService GetInstance(this SimpleContainer container, str /// The container. /// The key shared by those instances /// The resolved instances. - public static IEnumerable GetAllInstances(this SimpleContainer container, string key = null) - { - return container.GetAllInstances(typeof(TService), key).Cast(); - } + public static IEnumerable GetAllInstances(this SimpleContainer container, string key = null) => container.GetAllInstances(typeof(TService), key).Cast(); /// /// Determines if a handler for the service/key has previously been registered. @@ -154,10 +139,7 @@ public static IEnumerable GetAllInstances(this SimpleContain /// The container. /// The key. /// True if a handler is registere; false otherwise. - public static bool HasHandler(this SimpleContainer container, string key = null) - { - return container.HasHandler(typeof(TService), key); - } + public static bool HasHandler(this SimpleContainer container, string key = null) => container.HasHandler(typeof(TService), key); /// /// Unregisters any handlers for the service/key that have previously been registered. @@ -165,9 +147,6 @@ public static bool HasHandler(this SimpleContainer container, string k /// The service type. /// The container. /// The key. - public static void UnregisterHandler(this SimpleContainer container, string key = null) - { - container.UnregisterHandler(typeof(TService), key); - } + public static void UnregisterHandler(this SimpleContainer container, string key = null) => container.UnregisterHandler(typeof(TService), key); } } diff --git a/src/Caliburn.Micro.Core/IoC/SimpleContainer.cs b/src/Caliburn.Micro.Core/IoC/SimpleContainer.cs index f9a948a8b..f239de855 100644 --- a/src/Caliburn.Micro.Core/IoC/SimpleContainer.cs +++ b/src/Caliburn.Micro.Core/IoC/SimpleContainer.cs @@ -11,25 +11,19 @@ namespace Caliburn.Micro /// public class SimpleContainer { - private static readonly Type delegateType = typeof(Delegate); - private static readonly Type enumerableType = typeof(IEnumerable); - private static readonly TypeInfo enumerableTypeInfo = enumerableType.GetTypeInfo(); - private static readonly TypeInfo delegateTypeInfo = delegateType.GetTypeInfo(); - private Type simpleContainerType = typeof(SimpleContainer); - private readonly List entries; + private static readonly Type DelegateType = typeof(Delegate); + private static readonly Type EnumerableType = typeof(IEnumerable); + private static readonly TypeInfo EnumerableTypeInfo = EnumerableType.GetTypeInfo(); + private static readonly TypeInfo DelegateTypeInfo = DelegateType.GetTypeInfo(); + private readonly Type _simpleContainerType = typeof(SimpleContainer); + private readonly List _entries; /// /// Initializes a new instance of the class. /// - public SimpleContainer() - { - entries = new List(); - } + public SimpleContainer() => _entries = new List(); - private SimpleContainer(IEnumerable entries) - { - this.entries = new List(entries); - } + private SimpleContainer(IEnumerable entries) => _entries = new List(entries); /// /// Whether to enable recursive property injection for all resolutions. @@ -42,10 +36,7 @@ private SimpleContainer(IEnumerable entries) /// The service. /// The key. /// The implementation. - public void RegisterInstance(Type service, string key, object implementation) - { - RegisterHandler(service, key, container => implementation); - } + public void RegisterInstance(Type service, string key, object implementation) => RegisterHandler(service, key, container => implementation); /// /// Registers the class so that a new instance is created on every request. @@ -53,10 +44,7 @@ public void RegisterInstance(Type service, string key, object implementation) /// The service. /// The key. /// The implementation. - public void RegisterPerRequest(Type service, string key, Type implementation) - { - RegisterHandler(service, key, container => container.BuildInstance(implementation)); - } + public void RegisterPerRequest(Type service, string key, Type implementation) => RegisterHandler(service, key, container => container.BuildInstance(implementation)); /// /// Registers the class so that it is created once, on first request, and the same instance is returned to all requestors thereafter. @@ -67,7 +55,7 @@ public void RegisterPerRequest(Type service, string key, Type implementation) public void RegisterSingleton(Type service, string key, Type implementation) { object singleton = null; - RegisterHandler(service, key, container => singleton ?? (singleton = container.BuildInstance(implementation))); + RegisterHandler(service, key, container => (singleton ??= container.BuildInstance(implementation))); } /// @@ -76,10 +64,7 @@ public void RegisterSingleton(Type service, string key, Type implementation) /// The service. /// The key. /// The handler. - public void RegisterHandler(Type service, string key, Func handler) - { - GetOrCreateEntry(service, key).Add(handler); - } + public void RegisterHandler(Type service, string key, Func handler) => GetOrCreateEntry(service, key).Add(handler); /// /// Unregisters any handlers for the service/key that have previously been registered. @@ -88,10 +73,10 @@ public void RegisterHandler(Type service, string key, FuncThe key. public void UnregisterHandler(Type service, string key) { - var entry = GetEntry(service, key); + ContainerEntry entry = GetEntry(service, key); if (entry != null) { - entries.Remove(entry); + _entries.Remove(entry); } } @@ -103,7 +88,7 @@ public void UnregisterHandler(Type service, string key) /// The instance, or null if a handler is not found. public object GetInstance(Type service, string key) { - var entry = GetEntry(service, key); + ContainerEntry entry = GetEntry(service, key); if (entry != null) { var instance = entry.Single()(this); @@ -122,18 +107,18 @@ public object GetInstance(Type service, string key) } TypeInfo serviceTypeInfo = service.GetTypeInfo(); - if (delegateTypeInfo.IsAssignableFrom(serviceTypeInfo)) + if (DelegateTypeInfo.IsAssignableFrom(serviceTypeInfo)) { - var typeToCreate = serviceTypeInfo.GenericTypeArguments[0]; - var factoryFactoryType = typeof(FactoryFactory<>).MakeGenericType(typeToCreate); + Type typeToCreate = serviceTypeInfo.GenericTypeArguments[0]; + Type factoryFactoryType = typeof(FactoryFactory<>).MakeGenericType(typeToCreate); var factoryFactoryHost = Activator.CreateInstance(factoryFactoryType); - var factoryFactoryMethod = factoryFactoryType.GetRuntimeMethod("Create", new Type[] { simpleContainerType }); + MethodInfo factoryFactoryMethod = factoryFactoryType.GetRuntimeMethod("Create", new Type[] { _simpleContainerType }); return factoryFactoryMethod.Invoke(factoryFactoryHost, new object[] { this }); } - if (enumerableTypeInfo.IsAssignableFrom(serviceTypeInfo) && serviceTypeInfo.IsGenericType) + if (EnumerableTypeInfo.IsAssignableFrom(serviceTypeInfo) && serviceTypeInfo.IsGenericType) { - var listType = serviceTypeInfo.GenericTypeArguments[0]; + Type listType = serviceTypeInfo.GenericTypeArguments[0]; var instances = GetAllInstances(listType).ToList(); var array = Array.CreateInstance(listType, instances.Count); @@ -159,10 +144,7 @@ public object GetInstance(Type service, string key) /// The service. /// The key. /// True if a handler is registere; false otherwise. - public bool HasHandler(Type service, string key) - { - return GetEntry(service, key) != null; - } + public bool HasHandler(Type service, string key) => GetEntry(service, key) != null; /// /// Requests all instances of a given type and the given key (default null). @@ -172,14 +154,14 @@ public bool HasHandler(Type service, string key) /// All the instances or an empty enumerable if none are found. public IEnumerable GetAllInstances(Type service, string key = null) { - var entries = GetEntry(service, key); + ContainerEntry entries = GetEntry(service, key); if (entries == null) { return new object[0]; } - var instances = entries.Select(e => e(this)); + IEnumerable instances = entries.Select(e => e(this)); foreach (var instance in instances) { @@ -198,12 +180,12 @@ public IEnumerable GetAllInstances(Type service, string key = null) /// The instance. public void BuildUp(object instance) { - var properties = instance + IEnumerable properties = instance .GetType() .GetRuntimeProperties() .Where(p => p.CanRead && p.CanWrite && p.PropertyType.GetTypeInfo().IsInterface); - foreach (var property in properties) + foreach (PropertyInfo property in properties) { var value = GetInstance(property.PropertyType, null); @@ -218,18 +200,15 @@ public void BuildUp(object instance) /// Creates a child container. /// /// A new container. - public SimpleContainer CreateChildContainer() - { - return new SimpleContainer(entries); - } + public SimpleContainer CreateChildContainer() => new(_entries); private ContainerEntry GetOrCreateEntry(Type service, string key) { - var entry = GetEntry(service, key); + ContainerEntry entry = GetEntry(service, key); if (entry == null) { entry = new ContainerEntry { Service = service, Key = key }; - entries.Add(entry); + _entries.Add(entry); } return entry; @@ -239,16 +218,16 @@ private ContainerEntry GetEntry(Type service, string key) { if (service == null) { - return entries.FirstOrDefault(x => x.Key == key); + return _entries.FirstOrDefault(x => x.Key == key); } if (key == null) { - return entries.FirstOrDefault(x => x.Service == service && string.IsNullOrEmpty(x.Key)) - ?? entries.FirstOrDefault(x => x.Service == service); + return _entries.FirstOrDefault(x => x.Service == service && string.IsNullOrEmpty(x.Key)) + ?? _entries.FirstOrDefault(x => x.Service == service); } - return entries.FirstOrDefault(x => x.Service == service && x.Key == key); + return _entries.FirstOrDefault(x => x.Service == service && x.Key == key); } /// @@ -283,7 +262,7 @@ protected virtual object ActivateInstance(Type type, object[] args) private object[] DetermineConstructorArgs(Type implementation) { var args = new List(); - var constructor = SelectEligibleConstructor(implementation); + ConstructorInfo constructor = SelectEligibleConstructor(implementation); if (constructor != null) { @@ -293,9 +272,7 @@ private object[] DetermineConstructorArgs(Type implementation) return args.ToArray(); } - private ConstructorInfo SelectEligibleConstructor(Type type) - { - return type.GetTypeInfo().DeclaredConstructors + private ConstructorInfo SelectEligibleConstructor(Type type) => type.GetTypeInfo().DeclaredConstructors .Where(c => c.IsPublic) .Select(c => new { @@ -305,7 +282,6 @@ private ConstructorInfo SelectEligibleConstructor(Type type) .OrderByDescending(c => c.HandledParamters) .Select(c => c.Constructor) .FirstOrDefault(); - } private class ContainerEntry : List> { @@ -315,10 +291,7 @@ private class ContainerEntry : List> private class FactoryFactory { - public Func Create(SimpleContainer container) - { - return () => (T)container.GetInstance(typeof(T), null); - } + public Func Create(SimpleContainer container) => () => (T)container.GetInstance(typeof(T), null); } } } diff --git a/src/Caliburn.Micro.Core/Logging/Impl/DebugLog.cs b/src/Caliburn.Micro.Core/Logging/Impl/DebugLog.cs index a7f8867f6..1e42604cf 100644 --- a/src/Caliburn.Micro.Core/Logging/Impl/DebugLog.cs +++ b/src/Caliburn.Micro.Core/Logging/Impl/DebugLog.cs @@ -10,44 +10,32 @@ namespace Caliburn.Micro /// public class DebugLog : ILog { - private readonly string typeName; + private readonly string _typeName; /// /// Initializes a new instance of the class. /// /// The type. - public DebugLog(Type type) - { - typeName = type.FullName; - } + public DebugLog(Type type) => _typeName = type.FullName; /// /// Logs the message as info. /// /// A formatted message. /// Parameters to be injected into the formatted message. - public void Info(string format, params object[] args) - { - Debug.WriteLine("[{1}] INFO: {0}", string.Format(format, args), typeName); - } + public void Info(string format, params object[] args) => Debug.WriteLine("[{1}] INFO: {0}", string.Format(format, args), _typeName); /// /// Logs the message as a warning. /// /// A formatted message. /// Parameters to be injected into the formatted message. - public void Warn(string format, params object[] args) - { - Debug.WriteLine("[{1}] WARN: {0}", string.Format(format, args), typeName); - } + public void Warn(string format, params object[] args) => Debug.WriteLine("[{1}] WARN: {0}", string.Format(format, args), _typeName); /// /// Logs the exception. /// /// The exception. - public void Error(Exception exception) - { - Debug.WriteLine("[{1}] ERROR: {0}", exception, typeName); - } + public void Error(Exception exception) => Debug.WriteLine("[{1}] ERROR: {0}", exception, _typeName); } } diff --git a/src/Caliburn.Micro.Core/PlatformProvider/DefaultImpl/DefaultPlatformProvider.cs b/src/Caliburn.Micro.Core/PlatformProvider/DefaultImpl/DefaultPlatformProvider.cs index de6d215a8..91af7c6bf 100644 --- a/src/Caliburn.Micro.Core/PlatformProvider/DefaultImpl/DefaultPlatformProvider.cs +++ b/src/Caliburn.Micro.Core/PlatformProvider/DefaultImpl/DefaultPlatformProvider.cs @@ -13,38 +13,26 @@ public class DefaultPlatformProvider : IPlatformProvider /// /// Indicates whether or not the framework is in design-time mode. /// - public virtual bool InDesignMode - { - get { return true; } - } + public virtual bool InDesignMode => true; /// /// Executes the action on the UI thread asynchronously. /// /// The action to execute. - public virtual void BeginOnUIThread(Action action) - { - action(); - } + public virtual void BeginOnUIThread(Action action) => action(); /// /// Executes the action on the UI thread asynchronously. /// /// The action to execute. /// - public virtual Task OnUIThreadAsync(Func action) - { - return Task.Factory.StartNew(action); - } + public virtual Task OnUIThreadAsync(Func action) => Task.Factory.StartNew(action); /// /// Executes the action on the UI thread. /// /// The action to execute. - public virtual void OnUIThread(Action action) - { - action(); - } + public virtual void OnUIThread(Action action) => action(); /// /// Whether or not classes should execute property change notications on the UI thread. @@ -64,10 +52,7 @@ public virtual void OnUIThread(Action action) /// The WindowManager marks that element as a framework-created element so that it can determine what it created vs. what was intended by the developer. /// Calling GetFirstNonGeneratedView allows the framework to discover what the original element was. /// - public virtual object GetFirstNonGeneratedView(object view) - { - return view; - } + public virtual object GetFirstNonGeneratedView(object view) => view; /// /// Executes the handler the fist time the view is loaded. @@ -75,20 +60,14 @@ public virtual object GetFirstNonGeneratedView(object view) /// The view. /// The handler. /// true if the handler was executed immediately; false otherwise - public virtual void ExecuteOnFirstLoad(object view, Action handler) - { - handler(view); - } + public virtual void ExecuteOnFirstLoad(object view, Action handler) => handler(view); /// /// Executes the handler the next time the view's LayoutUpdated event fires. /// /// The view. /// The handler. - public virtual void ExecuteOnLayoutUpdated(object view, Action handler) - { - handler(view); - } + public virtual void ExecuteOnLayoutUpdated(object view, Action handler) => handler(view); /// /// Get the close action for the specified view model. @@ -99,9 +78,6 @@ public virtual void ExecuteOnLayoutUpdated(object view, Action handler) /// /// An to close the view model. /// - public virtual Func GetViewCloseAction(object viewModel, ICollection views, bool? dialogResult) - { - return ct => Task.FromResult(true); - } + public virtual Func GetViewCloseAction(object viewModel, ICollection views, bool? dialogResult) => ct => Task.FromResult(true); } } diff --git a/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs b/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs index dedd6efa5..f9187e49e 100644 --- a/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs +++ b/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs @@ -14,20 +14,14 @@ public static class ResultExtensions /// The result to decorate. /// The coroutine to execute when was canceled. /// - public static IResult WhenCancelled(this IResult result, Func coroutine) - { - return new ContinueResultDecorator(result, coroutine); - } + public static IResult WhenCancelled(this IResult result, Func coroutine) => new ContinueResultDecorator(result, coroutine); /// /// Overrides of the decorated instance. /// /// The result to decorate. /// - public static IResult OverrideCancel(this IResult result) - { - return new OverrideCancelResultDecorator(result); - } + public static IResult OverrideCancel(this IResult result) => new OverrideCancelResultDecorator(result); /// /// Rescues from the decorated by executing a coroutine. @@ -39,10 +33,7 @@ public static IResult OverrideCancel(this IResult result) /// public static IResult Rescue(this IResult result, Func rescue, bool cancelResult = true) - where TException : Exception - { - return new RescueResultDecorator(result, rescue, cancelResult); - } + where TException : Exception => new RescueResultDecorator(result, rescue, cancelResult); /// /// Rescues any exception from the decorated by executing a coroutine. @@ -52,10 +43,7 @@ public static IResult Rescue(this IResult result, FuncSet to true to cancel the result after executing rescue. /// public static IResult Rescue(this IResult result, Func rescue, - bool cancelResult = true) - { - return Rescue(result, rescue, cancelResult); - } + bool cancelResult = true) => Rescue(result, rescue, cancelResult); /// /// Executes an asynchronous. @@ -63,10 +51,7 @@ public static IResult Rescue(this IResult result, Func rescu /// The coroutine to execute. /// The context to execute the coroutine within. /// A task that represents the asynchronous coroutine. - public static Task ExecuteAsync(this IResult result, CoroutineExecutionContext context = null) - { - return InternalExecuteAsync(result, context); - } + public static Task ExecuteAsync(this IResult result, CoroutineExecutionContext context = null) => InternalExecuteAsync(result, context); /// /// Executes an asynchronous. @@ -76,10 +61,7 @@ public static Task ExecuteAsync(this IResult result, CoroutineExecutionContext c /// The context to execute the coroutine within. /// A task that represents the asynchronous coroutine. public static Task ExecuteAsync(this IResult result, - CoroutineExecutionContext context = null) - { - return InternalExecuteAsync(result, context); - } + CoroutineExecutionContext context = null) => InternalExecuteAsync(result, context); /// @@ -87,10 +69,7 @@ public static Task ExecuteAsync(this IResult result, /// /// The task. /// The coroutine that encapsulates the task. - public static TaskResult AsResult(this Task task) - { - return new TaskResult(task); - } + public static TaskResult AsResult(this Task task) => new(task); /// /// Encapsulates a task inside a couroutine. @@ -98,19 +77,15 @@ public static TaskResult AsResult(this Task task) /// The type of the result. /// The task. /// The coroutine that encapsulates the task. - public static TaskResult AsResult(this Task task) - { - return new TaskResult(task); - } + public static TaskResult AsResult(this Task task) => new(task); private static Task InternalExecuteAsync(IResult result, CoroutineExecutionContext context) { var taskSource = new TaskCompletionSource(); - EventHandler completed = null; - completed = (s, e) => + void OnCompleted(object s, ResultCompletionEventArgs e) { - result.Completed -= completed; + result.Completed -= OnCompleted; if (e.Error != null) { @@ -122,20 +97,19 @@ private static Task InternalExecuteAsync(IResult result, Corou } else { - var rr = result as IResult; - taskSource.SetResult(rr != null ? rr.Result : default(TResult)); + taskSource.SetResult(result is IResult rr ? rr.Result : default); } - }; + } try { IoC.BuildUp(result); - result.Completed += completed; + result.Completed += OnCompleted; result.Execute(context ?? new CoroutineExecutionContext()); } catch (Exception ex) { - result.Completed -= completed; + result.Completed -= OnCompleted; taskSource.SetException(ex); } diff --git a/src/Caliburn.Micro.Core/Result/Impl/ContinueResultDecorator.cs b/src/Caliburn.Micro.Core/Result/Impl/ContinueResultDecorator.cs index 815b58a9e..758a996fe 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/ContinueResultDecorator.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/ContinueResultDecorator.cs @@ -8,7 +8,7 @@ namespace Caliburn.Micro public class ContinueResultDecorator : ResultDecoratorBase { private static readonly ILog Log = LogManager.GetLog(typeof(ContinueResultDecorator)); - private readonly Func coroutine; + private readonly Func _coroutine; /// /// Initializes a new instance of the class. @@ -16,15 +16,8 @@ public class ContinueResultDecorator : ResultDecoratorBase /// The result to decorate. /// The coroutine to execute when was canceled. public ContinueResultDecorator(IResult result, Func coroutine) - : base(result) - { - if (coroutine == null) - { - throw new ArgumentNullException("coroutine"); - } - - this.coroutine = coroutine; - } + : base(result) + => _coroutine = coroutine ?? throw new ArgumentNullException("coroutine"); /// /// Called when the execution of the decorated result has completed. @@ -50,7 +43,7 @@ private void Continue(CoroutineExecutionContext context) IResult continueResult; try { - continueResult = coroutine(); + continueResult = _coroutine(); } catch (Exception ex) { diff --git a/src/Caliburn.Micro.Core/Result/Impl/DelegateResult.cs b/src/Caliburn.Micro.Core/Result/Impl/DelegateResult.cs index 682ce2b79..8ac540963 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/DelegateResult.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/DelegateResult.cs @@ -7,16 +7,13 @@ namespace Caliburn.Micro /// public class DelegateResult : IResult { - private readonly Action toExecute; + private readonly Action _toExecute; /// /// Initializes a new instance of the class. /// /// The action. - public DelegateResult(Action action) - { - toExecute = action; - } + public DelegateResult(Action action) => _toExecute = action; /// /// Executes the result using the specified context. @@ -28,7 +25,7 @@ public void Execute(CoroutineExecutionContext context) try { - toExecute(); + _toExecute(); } catch (Exception ex) { diff --git a/src/Caliburn.Micro.Core/Result/Impl/DelegateResult{TResult}.cs b/src/Caliburn.Micro.Core/Result/Impl/DelegateResult{TResult}.cs index 2d4034495..6d96cb505 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/DelegateResult{TResult}.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/DelegateResult{TResult}.cs @@ -8,16 +8,13 @@ namespace Caliburn.Micro /// The type of the result. public class DelegateResult : IResult { - private readonly Func toExecute; + private readonly Func _toExecute; /// /// Initializes a new instance of the class. /// /// The action. - public DelegateResult(Func action) - { - toExecute = action; - } + public DelegateResult(Func action) => _toExecute = action; /// /// Executes the result using the specified context. @@ -29,7 +26,7 @@ public void Execute(CoroutineExecutionContext context) try { - Result = toExecute(); + Result = _toExecute(); } catch (Exception ex) { diff --git a/src/Caliburn.Micro.Core/Result/Impl/RescueResultDecorator.cs b/src/Caliburn.Micro.Core/Result/Impl/RescueResultDecorator.cs index 6314dc4dd..4b6d90407 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/RescueResultDecorator.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/RescueResultDecorator.cs @@ -9,8 +9,8 @@ namespace Caliburn.Micro public class RescueResultDecorator : ResultDecoratorBase where TException : Exception { private static readonly ILog Log = LogManager.GetLog(typeof(RescueResultDecorator<>)); - private readonly bool cancelResult; - private readonly Func coroutine; + private readonly bool _cancelResult; + private readonly Func _coroutine; /// /// Initializes a new instance of the class. @@ -20,8 +20,8 @@ public class RescueResultDecorator : ResultDecoratorBase where TExce /// Set to true to cancel the result after executing rescue. public RescueResultDecorator(IResult result, Func coroutine, bool cancelResult = true) : base(result) { - this.coroutine = coroutine ?? throw new ArgumentNullException("coroutine"); - this.cancelResult = cancelResult; + _coroutine = coroutine ?? throw new ArgumentNullException("coroutine"); + _cancelResult = cancelResult; } /// @@ -32,8 +32,7 @@ public RescueResultDecorator(IResult result, Func coroutine /// The instance containing the event data. protected override void OnInnerResultCompleted(CoroutineExecutionContext context, IResult innerResult, ResultCompletionEventArgs args) { - var error = args.Error as TException; - if (error == null) + if (args.Error is not TException error) { OnCompleted(args); } @@ -50,7 +49,7 @@ private void Rescue(CoroutineExecutionContext context, TException exception) IResult rescueResult; try { - rescueResult = coroutine(exception); + rescueResult = _coroutine(exception); } catch (Exception ex) { @@ -76,7 +75,7 @@ private void RescueCompleted(object sender, ResultCompletionEventArgs args) OnCompleted(new ResultCompletionEventArgs { Error = args.Error, - WasCancelled = (args.Error == null && (args.WasCancelled || cancelResult)) + WasCancelled = (args.Error == null && (args.WasCancelled || _cancelResult)) }); } } diff --git a/src/Caliburn.Micro.Core/Result/Impl/ResultDecoratorBase.cs b/src/Caliburn.Micro.Core/Result/Impl/ResultDecoratorBase.cs index 00b17e79a..852d5cba9 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/ResultDecoratorBase.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/ResultDecoratorBase.cs @@ -7,17 +7,14 @@ namespace Caliburn.Micro /// public abstract class ResultDecoratorBase : IResult { - private readonly IResult innerResult; - private CoroutineExecutionContext context; + private readonly IResult _innerResult; + private CoroutineExecutionContext _context; /// /// Initializes a new instance of the class. /// /// The result to decorate. - protected ResultDecoratorBase(IResult result) - { - innerResult = result ?? throw new ArgumentNullException("result"); - } + protected ResultDecoratorBase(IResult result) => _innerResult = result ?? throw new ArgumentNullException("result"); /// /// Executes the result using the specified context. @@ -25,25 +22,25 @@ protected ResultDecoratorBase(IResult result) /// The context. public void Execute(CoroutineExecutionContext context) { - this.context = context; + _context = context; try { - innerResult.Completed += InnerResultCompleted; - IoC.BuildUp(innerResult); - innerResult.Execute(this.context); + _innerResult.Completed += InnerResultCompleted; + IoC.BuildUp(_innerResult); + _innerResult.Execute(_context); } catch (Exception ex) { - InnerResultCompleted(innerResult, new ResultCompletionEventArgs { Error = ex }); + InnerResultCompleted(_innerResult, new ResultCompletionEventArgs { Error = ex }); } } private void InnerResultCompleted(object sender, ResultCompletionEventArgs args) { - innerResult.Completed -= InnerResultCompleted; - OnInnerResultCompleted(context, innerResult, args); - context = null; + _innerResult.Completed -= InnerResultCompleted; + OnInnerResultCompleted(_context, _innerResult, args); + _context = null; } /// @@ -63,9 +60,6 @@ private void InnerResultCompleted(object sender, ResultCompletionEventArgs args) /// Raises the event. /// /// The instance containing the event data. - protected void OnCompleted(ResultCompletionEventArgs args) - { - Completed(this, args); - } + protected void OnCompleted(ResultCompletionEventArgs args) => Completed(this, args); } } diff --git a/src/Caliburn.Micro.Core/Result/Impl/SequentialResult.cs b/src/Caliburn.Micro.Core/Result/Impl/SequentialResult.cs index e6858a087..0d6157efc 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/SequentialResult.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/SequentialResult.cs @@ -8,17 +8,14 @@ namespace Caliburn.Micro /// public class SequentialResult : IResult { - private readonly IEnumerator enumerator; - private CoroutineExecutionContext context; + private readonly IEnumerator _enumerator; + private CoroutineExecutionContext _context; /// /// Initializes a new instance of the class. /// /// The enumerator. - public SequentialResult(IEnumerator enumerator) - { - this.enumerator = enumerator; - } + public SequentialResult(IEnumerator enumerator) => _enumerator = enumerator; /// /// Occurs when execution has completed. @@ -31,14 +28,13 @@ public SequentialResult(IEnumerator enumerator) /// The context. public void Execute(CoroutineExecutionContext context) { - this.context = context; + _context = context; ChildCompleted(null, new ResultCompletionEventArgs()); } private void ChildCompleted(object sender, ResultCompletionEventArgs args) { - var previous = sender as IResult; - if (previous != null) + if (sender is IResult previous) { previous.Completed -= ChildCompleted; } @@ -52,7 +48,7 @@ private void ChildCompleted(object sender, ResultCompletionEventArgs args) var moveNextSucceeded = false; try { - moveNextSucceeded = enumerator.MoveNext(); + moveNextSucceeded = _enumerator.MoveNext(); } catch (Exception ex) { @@ -64,10 +60,10 @@ private void ChildCompleted(object sender, ResultCompletionEventArgs args) { try { - var next = enumerator.Current; + IResult next = _enumerator.Current; IoC.BuildUp(next); next.Completed += ChildCompleted; - next.Execute(context); + next.Execute(_context); } catch (Exception ex) { @@ -83,7 +79,7 @@ private void ChildCompleted(object sender, ResultCompletionEventArgs args) private void OnComplete(Exception error, bool wasCancelled) { - enumerator.Dispose(); + _enumerator.Dispose(); Completed(this, new ResultCompletionEventArgs { Error = error, WasCancelled = wasCancelled }); } } diff --git a/src/Caliburn.Micro.Core/Result/Impl/SimpleResult.cs b/src/Caliburn.Micro.Core/Result/Impl/SimpleResult.cs index fcaace455..e26cf721f 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/SimpleResult.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/SimpleResult.cs @@ -7,48 +7,36 @@ namespace Caliburn.Micro /// public sealed class SimpleResult : IResult { - private readonly bool wasCancelled; - private readonly Exception error; + private readonly bool _wasCancelled; + private readonly Exception _error; private SimpleResult(bool wasCancelled, Exception error) { - this.wasCancelled = wasCancelled; - this.error = error; + _wasCancelled = wasCancelled; + _error = error; } /// /// A result that is always succeeded. /// - public static IResult Succeeded() - { - return new SimpleResult(false, null); - } + public static IResult Succeeded() => new SimpleResult(false, null); /// /// A result that is always canceled. /// /// The result. - public static IResult Cancelled() - { - return new SimpleResult(true, null); - } + public static IResult Cancelled() => new SimpleResult(true, null); /// /// A result that is always failed. /// - public static IResult Failed(Exception error) - { - return new SimpleResult(false, error); - } + public static IResult Failed(Exception error) => new SimpleResult(false, error); /// /// Executes the result using the specified context. /// /// The context. - public void Execute(CoroutineExecutionContext context) - { - Completed(this, new ResultCompletionEventArgs { WasCancelled = wasCancelled, Error = error }); - } + public void Execute(CoroutineExecutionContext context) => Completed(this, new ResultCompletionEventArgs { WasCancelled = _wasCancelled, Error = _error }); /// /// Occurs when execution has completed. diff --git a/src/Caliburn.Micro.Core/Result/Impl/TaskResult.cs b/src/Caliburn.Micro.Core/Result/Impl/TaskResult.cs index f1c1378ca..66df04578 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/TaskResult.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/TaskResult.cs @@ -8,16 +8,13 @@ namespace Caliburn.Micro /// public class TaskResult : IResult { - private readonly Task innerTask; + private readonly Task _innerTask; /// /// Initializes a new instance of the class. /// /// The task. - public TaskResult(Task task) - { - innerTask = task; - } + public TaskResult(Task task) => _innerTask = task; /// /// Executes the result using the specified context. @@ -25,13 +22,13 @@ public TaskResult(Task task) /// The context. public void Execute(CoroutineExecutionContext context) { - if (innerTask.IsCompleted) + if (_innerTask.IsCompleted) { - OnCompleted(innerTask); + OnCompleted(_innerTask); } else { - innerTask.ContinueWith(OnCompleted, + _innerTask.ContinueWith(OnCompleted, System.Threading.SynchronizationContext.Current != null ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Current); @@ -42,10 +39,7 @@ public void Execute(CoroutineExecutionContext context) /// Called when the asynchronous task has completed. /// /// The completed task. - protected virtual void OnCompleted(Task task) - { - Completed(this, new ResultCompletionEventArgs { WasCancelled = task.IsCanceled, Error = task.Exception }); - } + protected virtual void OnCompleted(Task task) => Completed(this, new ResultCompletionEventArgs { WasCancelled = task.IsCanceled, Error = task.Exception }); /// /// Occurs when execution has completed. diff --git a/src/Caliburn.Micro.Core/Screen/Extensions/ScreenExtensions.cs b/src/Caliburn.Micro.Core/Screen/Extensions/ScreenExtensions.cs index f0956f78f..39bf464f7 100644 --- a/src/Caliburn.Micro.Core/Screen/Extensions/ScreenExtensions.cs +++ b/src/Caliburn.Micro.Core/Screen/Extensions/ScreenExtensions.cs @@ -13,10 +13,7 @@ public static class ScreenExtensions /// Activates the item if it implements , otherwise does nothing. /// /// The potential activatable. - public static Task TryActivateAsync(object potentialActivatable) - { - return potentialActivatable is IActivate activator ? activator.ActivateAsync(CancellationToken.None) : Task.FromResult(true); - } + public static Task TryActivateAsync(object potentialActivatable) => potentialActivatable is IActivate activator ? activator.ActivateAsync(CancellationToken.None) : Task.FromResult(true); /// /// Activates the item if it implements , otherwise does nothing. @@ -24,10 +21,7 @@ public static Task TryActivateAsync(object potentialActivatable) /// The potential activatable. /// The cancellation token to cancel operation. /// A task that represents the asynchronous operation. - public static Task TryActivateAsync(object potentialActivatable, CancellationToken cancellationToken) - { - return potentialActivatable is IActivate activator ? activator.ActivateAsync(cancellationToken) : Task.FromResult(true); - } + public static Task TryActivateAsync(object potentialActivatable, CancellationToken cancellationToken) => potentialActivatable is IActivate activator ? activator.ActivateAsync(cancellationToken) : Task.FromResult(true); /// /// Deactivates the item if it implements , otherwise does nothing. @@ -35,10 +29,7 @@ public static Task TryActivateAsync(object potentialActivatable, CancellationTok /// The potential deactivatable. /// Indicates whether or not to close the item after deactivating it. /// A task that represents the asynchronous operation. - public static Task TryDeactivateAsync(object potentialDeactivatable, bool close) - { - return potentialDeactivatable is IDeactivate deactivator ? deactivator.DeactivateAsync(close, CancellationToken.None) : Task.FromResult(true); - } + public static Task TryDeactivateAsync(object potentialDeactivatable, bool close) => potentialDeactivatable is IDeactivate deactivator ? deactivator.DeactivateAsync(close, CancellationToken.None) : Task.FromResult(true); /// /// Deactivates the item if it implements , otherwise does nothing. @@ -47,10 +38,7 @@ public static Task TryDeactivateAsync(object potentialDeactivatable, bool close) /// Indicates whether or not to close the item after deactivating it. /// The cancellation token to cancel operation. /// A task that represents the asynchronous operation. - public static Task TryDeactivateAsync(object potentialDeactivatable, bool close, CancellationToken cancellationToken) - { - return potentialDeactivatable is IDeactivate deactivator ? deactivator.DeactivateAsync(close, cancellationToken): Task.FromResult(true); - } + public static Task TryDeactivateAsync(object potentialDeactivatable, bool close, CancellationToken cancellationToken) => potentialDeactivatable is IDeactivate deactivator ? deactivator.DeactivateAsync(close, cancellationToken) : Task.FromResult(true); /// /// Closes the specified item. @@ -58,10 +46,7 @@ public static Task TryDeactivateAsync(object potentialDeactivatable, bool close, /// The conductor. /// The item to close. /// A task that represents the asynchronous operation. - public static Task CloseItemAsync(this IConductor conductor, object item) - { - return conductor.DeactivateItemAsync(item, true, CancellationToken.None); - } + public static Task CloseItemAsync(this IConductor conductor, object item) => conductor.DeactivateItemAsync(item, true, CancellationToken.None); /// /// Closes the specified item. @@ -70,10 +55,7 @@ public static Task CloseItemAsync(this IConductor conductor, object item) /// The item to close. /// The cancellation token to cancel operation. /// A task that represents the asynchronous operation. - public static Task CloseItemAsync(this IConductor conductor, object item, CancellationToken cancellationToken) - { - return conductor.DeactivateItemAsync(item, true, cancellationToken); - } + public static Task CloseItemAsync(this IConductor conductor, object item, CancellationToken cancellationToken) => conductor.DeactivateItemAsync(item, true, cancellationToken); /// /// Closes the specified item. @@ -81,10 +63,7 @@ public static Task CloseItemAsync(this IConductor conductor, object item, Cancel /// The conductor. /// The item to close. /// A task that represents the asynchronous operation. - public static Task CloseItemAsync(this ConductorBase conductor, T item) where T : class - { - return conductor.DeactivateItemAsync(item, true, CancellationToken.None); - } + public static Task CloseItemAsync(this ConductorBase conductor, T item) where T : class => conductor.DeactivateItemAsync(item, true, CancellationToken.None); /// /// Closes the specified item. @@ -93,10 +72,7 @@ public static Task CloseItemAsync(this ConductorBase conductor, T item) wh /// The item to close. /// The cancellation token to cancel operation. /// A task that represents the asynchronous operation. - public static Task CloseItemAsync(this ConductorBase conductor, T item, CancellationToken cancellationToken) where T : class - { - return conductor.DeactivateItemAsync(item, true, cancellationToken); - } + public static Task CloseItemAsync(this ConductorBase conductor, T item, CancellationToken cancellationToken) where T : class => conductor.DeactivateItemAsync(item, true, cancellationToken); /// /// Activates a child whenever the specified parent is activated. diff --git a/src/Caliburn.Micro.Core/Screen/Screen.cs b/src/Caliburn.Micro.Core/Screen/Screen.cs index 5175e64f3..583da8cf1 100644 --- a/src/Caliburn.Micro.Core/Screen/Screen.cs +++ b/src/Caliburn.Micro.Core/Screen/Screen.cs @@ -19,10 +19,7 @@ public class Screen : ViewAware, IScreen, IChild /// /// Creates an instance of the screen. /// - public Screen() - { - _displayName = GetType().FullName; - } + public Screen() => _displayName = GetType().FullName; /// /// Indicates whether or not this instance is currently initialized. @@ -148,10 +145,7 @@ async Task IDeactivate.DeactivateAsync(bool close, CancellationToken cancellatio /// /// The cancellation token to cancel operation. /// A task that represents the asynchronous operation and holds the value of the close check.. - public virtual Task CanCloseAsync(CancellationToken cancellationToken = default) - { - return Task.FromResult(true); - } + public virtual Task CanCloseAsync(CancellationToken cancellationToken = default) => Task.FromResult(true); /// /// Tries to close this instance by asking its Parent to initiate shutdown or by asking its corresponding view to close. @@ -165,7 +159,7 @@ public virtual async Task TryCloseAsync(bool? dialogResult = null) await conductor.CloseItemAsync(this, CancellationToken.None); } - var closeAction = PlatformProvider.Current.GetViewCloseAction(this, Views.Values, dialogResult); + Func closeAction = PlatformProvider.Current.GetViewCloseAction(this, Views.Values, dialogResult); await Execute.OnUIThreadAsync(async () => await closeAction(CancellationToken.None)); } @@ -173,27 +167,18 @@ public virtual async Task TryCloseAsync(bool? dialogResult = null) /// /// Called when initializing. /// - protected virtual Task OnInitializeAsync(CancellationToken cancellationToken) - { - return Task.FromResult(true); - } + protected virtual Task OnInitializeAsync(CancellationToken cancellationToken) => Task.FromResult(true); /// /// Called when activating. /// - protected virtual Task OnActivateAsync(CancellationToken cancellationToken) - { - return Task.FromResult(true); - } + protected virtual Task OnActivateAsync(CancellationToken cancellationToken) => Task.FromResult(true); /// /// Called when view has been activated. /// - protected virtual Task OnActivatedAsync(CancellationToken cancellationToken) - { - return Task.FromResult(true); - } + protected virtual Task OnActivatedAsync(CancellationToken cancellationToken) => Task.FromResult(true); /// /// Called when deactivating. @@ -201,9 +186,6 @@ protected virtual Task OnActivatedAsync(CancellationToken cancellationToken) /// Indicates whether this instance will be closed. /// The cancellation token to cancel operation. /// A task that represents the asynchronous operation. - protected virtual Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) - { - return Task.FromResult(true); - } + protected virtual Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) => Task.FromResult(true); } } diff --git a/src/Caliburn.Micro.Core/Types/BindableCollection.cs b/src/Caliburn.Micro.Core/Types/BindableCollection.cs index 0a43719fb..9f4b5aba7 100644 --- a/src/Caliburn.Micro.Core/Types/BindableCollection.cs +++ b/src/Caliburn.Micro.Core/Types/BindableCollection.cs @@ -15,20 +15,14 @@ public class BindableCollection : ObservableCollection, IObservableCollect /// /// Initializes a new instance of the class. /// - public BindableCollection() - { - IsNotifying = true; - } + public BindableCollection() => IsNotifying = true; /// /// Initializes a new instance of the class. /// /// The collection from which the elements are copied. public BindableCollection(IEnumerable collection) - : base(collection) - { - IsNotifying = true; - } + : base(collection) => IsNotifying = true; /// /// Enables/Disables property change notification. @@ -101,10 +95,7 @@ protected override sealed void InsertItem(int index, T item) /// /// Used to avoid compiler warning regarding unverifiable code. /// - protected virtual void InsertItemBase(int index, T item) - { - base.InsertItem(index, item); - } + protected virtual void InsertItemBase(int index, T item) => base.InsertItem(index, item); /// /// Sets the item at the specified position. @@ -131,10 +122,7 @@ protected override sealed void SetItem(int index, T item) /// /// Used to avoid compiler warning regarding unverifiable code. /// - protected virtual void SetItemBase(int index, T item) - { - base.SetItem(index, item); - } + protected virtual void SetItemBase(int index, T item) => base.SetItem(index, item); /// /// Removes the item at the specified position. @@ -159,18 +147,12 @@ protected override sealed void RemoveItem(int index) /// /// Used to avoid compiler warning regarding unverifiable code. /// - protected virtual void RemoveItemBase(int index) - { - base.RemoveItem(index); - } + protected virtual void RemoveItemBase(int index) => base.RemoveItem(index); /// /// Clears the items contained by the collection. /// - protected override sealed void ClearItems() - { - OnUIThread(ClearItemsBase); - } + protected override sealed void ClearItems() => OnUIThread(ClearItemsBase); /// /// Exposes the base implementation of the function. @@ -178,10 +160,7 @@ protected override sealed void ClearItems() /// /// Used to avoid compiler warning regarding unverifiable code. /// - protected virtual void ClearItemsBase() - { - base.ClearItems(); - } + protected virtual void ClearItemsBase() => base.ClearItems(); /// /// Raises the event with the provided arguments. @@ -218,7 +197,7 @@ void AddRange() var previousNotificationSetting = IsNotifying; IsNotifying = false; var index = Count; - foreach (var item in items) + foreach (T item in items) { InsertItemBase(index, item); index++; @@ -250,7 +229,7 @@ void RemoveRange() { var previousNotificationSetting = IsNotifying; IsNotifying = false; - foreach (var item in items) + foreach (T item in items) { var index = IndexOf(item); if (index >= 0) diff --git a/src/Caliburn.Micro.Core/Types/PropertyChangedBase.cs b/src/Caliburn.Micro.Core/Types/PropertyChangedBase.cs index 78d4c530c..a32ed86eb 100644 --- a/src/Caliburn.Micro.Core/Types/PropertyChangedBase.cs +++ b/src/Caliburn.Micro.Core/Types/PropertyChangedBase.cs @@ -15,10 +15,7 @@ public class PropertyChangedBase : INotifyPropertyChangedEx /// /// Creates an instance of . /// - public PropertyChangedBase() - { - IsNotifying = true; - } + public PropertyChangedBase() => IsNotifying = true; /// /// Occurs when a property value changes. @@ -34,10 +31,7 @@ public PropertyChangedBase() /// /// Raises a change notification indicating that all bindings should be refreshed. /// - public virtual void Refresh() - { - NotifyOfPropertyChange(string.Empty); - } + public virtual void Refresh() => NotifyOfPropertyChange(string.Empty); /// /// Notifies subscribers of the property change. @@ -63,20 +57,14 @@ public virtual void NotifyOfPropertyChange([System.Runtime.CompilerServices.Call /// /// The type of the property. /// The property expression. - public void NotifyOfPropertyChange(Expression> property) - { - NotifyOfPropertyChange(property.GetMemberInfo().Name); - } + public void NotifyOfPropertyChange(Expression> property) => NotifyOfPropertyChange(property.GetMemberInfo().Name); /// /// Raises the event directly. /// /// The instance containing the event data. [EditorBrowsable(EditorBrowsableState.Never)] - protected void OnPropertyChanged(PropertyChangedEventArgs e) - { - PropertyChanged?.Invoke(this, e); - } + protected void OnPropertyChanged(PropertyChangedEventArgs e) => PropertyChanged?.Invoke(this, e); /// /// Executes the given action on the UI thread diff --git a/src/Caliburn.Micro.Core/Types/WeakValueDictionary.cs b/src/Caliburn.Micro.Core/Types/WeakValueDictionary.cs index 2b550c366..18887e391 100644 --- a/src/Caliburn.Micro.Core/Types/WeakValueDictionary.cs +++ b/src/Caliburn.Micro.Core/Types/WeakValueDictionary.cs @@ -13,16 +13,16 @@ namespace Caliburn.Micro internal class WeakValueDictionary : IDictionary where TValue : class { - private readonly Dictionary inner; - private readonly WeakReference gcSentinel = new WeakReference(new object()); + private readonly Dictionary _inner; + private readonly WeakReference _gcSentinel = new(new object()); #region Cleanup handling private bool IsCleanupNeeded() { - if (gcSentinel.Target == null) + if (_gcSentinel.Target == null) { - gcSentinel.Target = new object(); + _gcSentinel.Target = new object(); return true; } @@ -31,11 +31,11 @@ private bool IsCleanupNeeded() private void CleanAbandonedItems() { - var keysToRemove = inner.Where(pair => !pair.Value.IsAlive) + var keysToRemove = _inner.Where(pair => !pair.Value.IsAlive) .Select(pair => pair.Key) .ToList(); - keysToRemove.Apply(key => inner.Remove(key)); + keysToRemove.Apply(key => _inner.Remove(key)); } private void CleanIfNeeded() @@ -53,10 +53,7 @@ private void CleanIfNeeded() /// /// Initializes a new instance of the class that is empty, has the default initial capacity, and uses the default equality comparer for the key type. /// - public WeakValueDictionary() - { - inner = new Dictionary(); - } + public WeakValueDictionary() => _inner = new Dictionary(); /// /// Initializes a new instance of the class that contains elements copied from the specified and uses the default equality comparer for the key type. @@ -64,8 +61,8 @@ public WeakValueDictionary() /// The whose elements are copied to the new . public WeakValueDictionary(IDictionary dictionary) { - inner = new Dictionary(); - dictionary.Apply(item => inner.Add(item.Key, new WeakReference(item.Value))); + _inner = new Dictionary(); + dictionary.Apply(item => _inner.Add(item.Key, new WeakReference(item.Value))); } /// @@ -75,37 +72,28 @@ public WeakValueDictionary(IDictionary dictionary) /// The implementation to use when comparing keys, or null to use the default for the type of the key. public WeakValueDictionary(IDictionary dictionary, IEqualityComparer comparer) { - inner = new Dictionary(comparer); - dictionary.Apply(item => inner.Add(item.Key, new WeakReference(item.Value))); + _inner = new Dictionary(comparer); + dictionary.Apply(item => _inner.Add(item.Key, new WeakReference(item.Value))); } /// /// Initializes a new instance of the class that is empty, has the default initial capacity, and uses the specified . /// /// The implementation to use when comparing keys, or null to use the default for the type of the key. - public WeakValueDictionary(IEqualityComparer comparer) - { - inner = new Dictionary(comparer); - } + public WeakValueDictionary(IEqualityComparer comparer) => _inner = new Dictionary(comparer); /// /// Initializes a new instance of the class that is empty, has the specified initial capacity, and uses the default equality comparer for the key type. /// /// The initial number of elements that the can contain. - public WeakValueDictionary(int capacity) - { - inner = new Dictionary(capacity); - } + public WeakValueDictionary(int capacity) => _inner = new Dictionary(capacity); /// /// Initializes a new instance of the class that is empty, has the specified initial capacity, and uses the specified . /// /// The initial number of elements that the can contain. /// The implementation to use when comparing keys, or null to use the default for the type of the key. - public WeakValueDictionary(int capacity, IEqualityComparer comparer) - { - inner = new Dictionary(capacity, comparer); - } + public WeakValueDictionary(int capacity, IEqualityComparer comparer) => _inner = new Dictionary(capacity, comparer); #endregion @@ -116,33 +104,23 @@ public WeakValueDictionary(int capacity, IEqualityComparer comparer) public IEnumerator> GetEnumerator() { CleanIfNeeded(); - var enumerable = inner.Select(pair => new KeyValuePair(pair.Key, (TValue)pair.Value.Target)) + IEnumerable> enumerable = _inner.Select(pair => new KeyValuePair(pair.Key, (TValue)pair.Value.Target)) .Where(pair => pair.Value != null); return enumerable.GetEnumerator(); } - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - void ICollection>.Add(KeyValuePair item) - { - Add(item.Key, item.Value); - } + void ICollection>.Add(KeyValuePair item) => Add(item.Key, item.Value); /// /// Removes all keys and values from the . /// - public void Clear() - { - inner.Clear(); - } + public void Clear() => _inner.Clear(); bool ICollection>.Contains(KeyValuePair item) { - TValue value; - if (!TryGetValue(item.Key, out value)) + if (!TryGetValue(item.Key, out TValue value)) { return false; } @@ -173,8 +151,7 @@ void ICollection>.CopyTo(KeyValuePair[] bool ICollection>.Remove(KeyValuePair item) { - TValue value; - if (!TryGetValue(item.Key, out value)) + if (!TryGetValue(item.Key, out TValue value)) { return false; } @@ -184,7 +161,7 @@ bool ICollection>.Remove(KeyValuePair i return false; } - return inner.Remove(item.Key); + return _inner.Remove(item.Key); } /// @@ -200,14 +177,11 @@ public int Count get { CleanIfNeeded(); - return inner.Count; + return _inner.Count; } } - bool ICollection>.IsReadOnly - { - get { return false; } - } + bool ICollection>.IsReadOnly => false; /// /// Adds the specified key and value to the dictionary. @@ -217,7 +191,7 @@ bool ICollection>.IsReadOnly public void Add(TKey key, TValue value) { CleanIfNeeded(); - inner.Add(key, new WeakReference(value)); + _inner.Add(key, new WeakReference(value)); } /// @@ -225,11 +199,7 @@ public void Add(TKey key, TValue value) /// /// The key to locate in the . /// - public bool ContainsKey(TKey key) - { - TValue dummy; - return TryGetValue(key, out dummy); - } + public bool ContainsKey(TKey key) => TryGetValue(key, out _); /// /// Removes the value with the specified key from the . @@ -239,7 +209,7 @@ public bool ContainsKey(TKey key) public bool Remove(TKey key) { CleanIfNeeded(); - return inner.Remove(key); + return _inner.Remove(key); } /// @@ -255,8 +225,7 @@ public bool TryGetValue(TKey key, out TValue value) { CleanIfNeeded(); - WeakReference wr; - if (!inner.TryGetValue(key, out wr)) + if (!_inner.TryGetValue(key, out WeakReference wr)) { value = null; return false; @@ -265,7 +234,7 @@ public bool TryGetValue(TKey key, out TValue value) var result = (TValue)wr.Target; if (result == null) { - inner.Remove(key); + _inner.Remove(key); value = null; return false; } @@ -286,8 +255,7 @@ public TValue this[TKey key] { get { - TValue result; - if (!TryGetValue(key, out result)) + if (!TryGetValue(key, out TValue result)) { throw new KeyNotFoundException(); } @@ -297,61 +265,37 @@ public TValue this[TKey key] set { CleanIfNeeded(); - inner[key] = new WeakReference(value); + _inner[key] = new WeakReference(value); } } /// /// Gets a collection containing the keys in the . /// - public ICollection Keys - { - get { return inner.Keys; } - } + public ICollection Keys => _inner.Keys; /// /// Gets a collection containing the values in the . /// - public ICollection Values - { - get { return new ValueCollection(this); } - } + public ICollection Values => new ValueCollection(this); #region Inner Types private sealed class ValueCollection : ICollection { - private readonly WeakValueDictionary inner; + private readonly WeakValueDictionary _inner; - public ValueCollection(WeakValueDictionary dictionary) - { - inner = dictionary; - } + public ValueCollection(WeakValueDictionary dictionary) => _inner = dictionary; - public IEnumerator GetEnumerator() - { - return inner.Select(pair => pair.Value).GetEnumerator(); - } + public IEnumerator GetEnumerator() => _inner.Select(pair => pair.Value).GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - void ICollection.Add(TValue item) - { - throw new NotSupportedException(); - } + void ICollection.Add(TValue item) => throw new NotSupportedException(); - void ICollection.Clear() - { - throw new NotSupportedException(); - } + void ICollection.Clear() => throw new NotSupportedException(); - bool ICollection.Contains(TValue item) - { - return inner.Any(pair => pair.Value == item); - } + bool ICollection.Contains(TValue item) => _inner.Any(pair => pair.Value == item); public void CopyTo(TValue[] array, int arrayIndex) { @@ -374,20 +318,11 @@ public void CopyTo(TValue[] array, int arrayIndex) this.ToArray().CopyTo(array, arrayIndex); } - bool ICollection.Remove(TValue item) - { - throw new NotSupportedException(); - } + bool ICollection.Remove(TValue item) => throw new NotSupportedException(); - public int Count - { - get { return inner.Count; } - } + public int Count => _inner.Count; - bool ICollection.IsReadOnly - { - get { return true; } - } + bool ICollection.IsReadOnly => true; } #endregion diff --git a/src/Caliburn.Micro.Core/ViewAware/ViewAware.cs b/src/Caliburn.Micro.Core/ViewAware/ViewAware.cs index ef6623dcd..02aa6036c 100644 --- a/src/Caliburn.Micro.Core/ViewAware/ViewAware.cs +++ b/src/Caliburn.Micro.Core/ViewAware/ViewAware.cs @@ -9,28 +9,22 @@ namespace Caliburn.Micro /// public class ViewAware : PropertyChangedBase, IViewAware { - private readonly IDictionary views; + private readonly IDictionary _views; /// /// The default view context. /// - public static readonly object DefaultContext = new object(); + public static readonly object DefaultContext = new(); /// /// The view chache for this instance. /// - protected IDictionary Views - { - get { return views; } - } + protected IDictionary Views => _views; /// /// Creates an instance of . /// - public ViewAware() - { - views = new WeakValueDictionary(); - } + public ViewAware() => _views = new WeakValueDictionary(); /// /// Raised when a view is attached. @@ -46,8 +40,7 @@ void IViewAware.AttachView(object view, object context) OnViewAttached(nonGeneratedView, context); ViewAttached(this, new ViewAttachedEventArgs { View = nonGeneratedView, Context = context }); - var activatable = this as IActivate; - if (activatable == null || activatable.IsActive) + if (this is not IActivate activatable || activatable.IsActive) { PlatformProvider.Current.ExecuteOnLayoutUpdated(nonGeneratedView, OnViewReady); } @@ -60,10 +53,9 @@ void IViewAware.AttachView(object view, object context) private static void AttachViewReadyOnActivated(IActivate activatable, object nonGeneratedView) { var viewReference = new WeakReference(nonGeneratedView); - AsyncEventHandler handler = null; - handler = (s, e) => + Task OnActivated(object s, ActivationEventArgs e) { - ((IActivate)s).Activated -= handler; + ((IActivate)s).Activated -= OnActivated; var view = viewReference.Target; if (view != null) { @@ -71,8 +63,9 @@ private static void AttachViewReadyOnActivated(IActivate activatable, object non } return Task.CompletedTask; - }; - activatable.Activated += handler; + } + + activatable.Activated += OnActivated; } /// @@ -107,8 +100,7 @@ protected virtual void OnViewReady(object view) /// The view. public virtual object GetView(object context = null) { - object view; - Views.TryGetValue(context ?? DefaultContext, out view); + Views.TryGetValue(context ?? DefaultContext, out object view); return view; } } From df3a593118b5eff0b68f2210fc766ca1713c3426 Mon Sep 17 00:00:00 2001 From: khaled Date: Sat, 7 Oct 2023 04:21:20 +0200 Subject: [PATCH 04/14] - Formatted arrow expression. - Splitted long lines for easy read. - Use expression body for lambda expression. --- .../Conductor/Base/ConductorBase.cs | 9 +- .../Base/ConductorBaseWithActiveItem.cs | 3 +- .../Conductor/Conductor.cs | 9 +- .../ConductorWithCollectionAllActive.cs | 54 ++++---- .../ConductorWithCollectionOneActive.cs | 51 +++---- .../DefaultImpl/DefaultCloseStrategy.cs | 3 +- .../Extensions/ConductorExtensions.cs | 3 +- .../Coroutine/ExtensionPoints/Coroutine.cs | 79 ++++++----- .../EventAggregator/EventAggregator.cs | 9 +- .../Extensions/EventAggregatorExtensions.cs | 130 ++++++++++-------- src/Caliburn.Micro.Core/Extensions/Execute.cs | 12 +- .../IoC/ExtensionPoints/IoC.cs | 15 +- .../IoC/Extensions/ContainerExtensions.cs | 28 ++-- .../IoC/SimpleContainer.cs | 45 +++--- .../Logging/ExtensionPoints/LogManager.cs | 3 +- .../Logging/Impl/DebugLog.cs | 12 +- .../DefaultImpl/DefaultPlatformProvider.cs | 27 ++-- .../ExtensionPoints/PlatformProvider.cs | 3 +- .../Result/Extensions/ResultExtensions.cs | 29 ++-- .../Result/Impl/DelegateResult.cs | 3 +- .../Result/Impl/DelegateResult{TResult}.cs | 3 +- .../Impl/OverrideCancelResultDecorator.cs | 7 +- .../Result/Impl/ResultDecoratorBase.cs | 6 +- .../Result/Impl/SequentialResult.cs | 3 +- .../Result/Impl/SimpleResult.cs | 18 ++- .../Result/Impl/TaskResult.cs | 12 +- .../Screen/EventHandlers/AsyncEventHandler.cs | 4 +- .../Screen/Extensions/ActivateExtensions.cs | 3 +- .../Extensions/AsyncEventHandlerExtensions.cs | 8 +- .../Screen/Extensions/DeactivateExtensions.cs | 3 +- .../Screen/Extensions/ScreenExtensions.cs | 26 ++-- src/Caliburn.Micro.Core/Screen/Screen.cs | 18 ++- .../Types/BindableCollection.cs | 24 ++-- .../Types/PropertyChangedBase.cs | 15 +- .../Types/WeakValueDictionary.cs | 87 +++++++----- .../ViewAware/ViewAware.cs | 13 +- 36 files changed, 471 insertions(+), 306 deletions(-) diff --git a/src/Caliburn.Micro.Core/Conductor/Base/ConductorBase.cs b/src/Caliburn.Micro.Core/Conductor/Base/ConductorBase.cs index 8622fe9b7..a68735a4f 100644 --- a/src/Caliburn.Micro.Core/Conductor/Base/ConductorBase.cs +++ b/src/Caliburn.Micro.Core/Conductor/Base/ConductorBase.cs @@ -24,9 +24,11 @@ public ICloseStrategy CloseStrategy set => _closeStrategy = value; } - Task IConductor.DeactivateItemAsync(object item, bool close, CancellationToken cancellationToken) => DeactivateItemAsync((T)item, close, cancellationToken); + Task IConductor.DeactivateItemAsync(object item, bool close, CancellationToken cancellationToken) + => DeactivateItemAsync((T)item, close, cancellationToken); - IEnumerable IParent.GetChildren() => GetChildren(); + IEnumerable IParent.GetChildren() + => GetChildren(); /// /// Occurs when an activation request is processed. @@ -39,7 +41,8 @@ public ICloseStrategy CloseStrategy /// The collection of children. public abstract IEnumerable GetChildren(); - Task IConductor.ActivateItemAsync(object item, CancellationToken cancellationToken) => ActivateItemAsync((T)item, cancellationToken); + Task IConductor.ActivateItemAsync(object item, CancellationToken cancellationToken) + => ActivateItemAsync((T)item, cancellationToken); /// /// Activates the specified item. diff --git a/src/Caliburn.Micro.Core/Conductor/Base/ConductorBaseWithActiveItem.cs b/src/Caliburn.Micro.Core/Conductor/Base/ConductorBaseWithActiveItem.cs index 1249eac40..01fc47635 100644 --- a/src/Caliburn.Micro.Core/Conductor/Base/ConductorBaseWithActiveItem.cs +++ b/src/Caliburn.Micro.Core/Conductor/Base/ConductorBaseWithActiveItem.cs @@ -57,6 +57,7 @@ protected virtual async Task ChangeActiveItemAsync(T newItem, bool closePrevious /// The new item to activate. /// Indicates whether or not to close the previous active item. /// A task that represents the asynchronous operation. - protected Task ChangeActiveItemAsync(T newItem, bool closePrevious) => ChangeActiveItemAsync(newItem, closePrevious, default); + protected Task ChangeActiveItemAsync(T newItem, bool closePrevious) + => ChangeActiveItemAsync(newItem, closePrevious, default); } } diff --git a/src/Caliburn.Micro.Core/Conductor/Conductor.cs b/src/Caliburn.Micro.Core/Conductor/Conductor.cs index 9421ebc7d..9324fc566 100644 --- a/src/Caliburn.Micro.Core/Conductor/Conductor.cs +++ b/src/Caliburn.Micro.Core/Conductor/Conductor.cs @@ -72,7 +72,8 @@ public override async Task DeactivateItemAsync(T item, bool close, CancellationT /// Called when activating. /// /// A task that represents the asynchronous operation. - protected override Task OnActivateAsync(CancellationToken cancellationToken) => ScreenExtensions.TryActivateAsync(ActiveItem, cancellationToken); + protected override Task OnActivateAsync(CancellationToken cancellationToken) + => ScreenExtensions.TryActivateAsync(ActiveItem, cancellationToken); /// /// Called when deactivating. @@ -80,12 +81,14 @@ public override async Task DeactivateItemAsync(T item, bool close, CancellationT /// Indicates whether this instance will be closed. /// The cancellation token to cancel operation. /// A task that represents the asynchronous operation. - protected override Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) => ScreenExtensions.TryDeactivateAsync(ActiveItem, close, cancellationToken); + protected override Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) + => ScreenExtensions.TryDeactivateAsync(ActiveItem, close, cancellationToken); /// /// Gets the children. /// /// The collection of children. - public override IEnumerable GetChildren() => new[] { ActiveItem }; + public override IEnumerable GetChildren() + => new[] { ActiveItem }; } } diff --git a/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionAllActive.cs b/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionAllActive.cs index 14b8ae93f..808ceeaf9 100644 --- a/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionAllActive.cs +++ b/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionAllActive.cs @@ -28,40 +28,45 @@ public class AllActive : ConductorBase /// /// if set to true opens public items that are properties of this class. public AllActive(bool openPublicItems) - : this() => _openPublicItems = openPublicItems; + : this() + => _openPublicItems = openPublicItems; /// /// Initializes a new instance of the class. /// - public AllActive() => _items.CollectionChanged += (s, e) => - { - switch (e.Action) - { - case NotifyCollectionChangedAction.Add: - e.NewItems.OfType().Apply(x => x.Parent = this); - break; - case NotifyCollectionChangedAction.Remove: - e.OldItems.OfType().Apply(x => x.Parent = null); - break; - case NotifyCollectionChangedAction.Replace: - e.NewItems.OfType().Apply(x => x.Parent = this); - e.OldItems.OfType().Apply(x => x.Parent = null); - break; - case NotifyCollectionChangedAction.Reset: - _items.OfType().Apply(x => x.Parent = this); - break; - } - }; + public AllActive() + => _items.CollectionChanged += + (s, e) => + { + switch (e.Action) + { + case NotifyCollectionChangedAction.Add: + e.NewItems.OfType().Apply(x => x.Parent = this); + break; + case NotifyCollectionChangedAction.Remove: + e.OldItems.OfType().Apply(x => x.Parent = null); + break; + case NotifyCollectionChangedAction.Replace: + e.NewItems.OfType().Apply(x => x.Parent = this); + e.OldItems.OfType().Apply(x => x.Parent = null); + break; + case NotifyCollectionChangedAction.Reset: + _items.OfType().Apply(x => x.Parent = this); + break; + } + }; /// /// Gets the items that are currently being conducted. /// - public IObservableCollection Items => _items; + public IObservableCollection Items + => _items; /// /// Called when activating. /// - protected override Task OnActivateAsync(CancellationToken cancellationToken) => Task.WhenAll(_items.OfType().Select(x => x.ActivateAsync(cancellationToken))); + protected override Task OnActivateAsync(CancellationToken cancellationToken) + => Task.WhenAll(_items.OfType().Select(x => x.ActivateAsync(cancellationToken))); /// /// Called when deactivating. @@ -71,7 +76,7 @@ public AllActive() => _items.CollectionChanged += (s, e) => /// A task that represents the asynchronous operation. protected override async Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) { - foreach(IDeactivate deactivate in _items.OfType()) + foreach (IDeactivate deactivate in _items.OfType()) { await deactivate.DeactivateAsync(close, cancellationToken); } @@ -161,7 +166,8 @@ public override async Task DeactivateItemAsync(T item, bool close, CancellationT /// Gets the children. /// /// The collection of children. - public override IEnumerable GetChildren() => _items; + public override IEnumerable GetChildren() + => _items; private async Task CloseItemCoreAsync(T item, CancellationToken cancellationToken = default) { diff --git a/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionOneActive.cs b/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionOneActive.cs index 5039f2762..6a56753f2 100644 --- a/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionOneActive.cs +++ b/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionOneActive.cs @@ -23,36 +23,40 @@ public class OneActive : ConductorBaseWithActiveItem /// /// Initializes a new instance of the class. /// - public OneActive() => _items.CollectionChanged += (s, e) => - { - switch (e.Action) - { - case NotifyCollectionChangedAction.Add: - e.NewItems.OfType().Apply(x => x.Parent = this); - break; - case NotifyCollectionChangedAction.Remove: - e.OldItems.OfType().Apply(x => x.Parent = null); - break; - case NotifyCollectionChangedAction.Replace: - e.NewItems.OfType().Apply(x => x.Parent = this); - e.OldItems.OfType().Apply(x => x.Parent = null); - break; - case NotifyCollectionChangedAction.Reset: - _items.OfType().Apply(x => x.Parent = this); - break; - } - }; + public OneActive() + => _items.CollectionChanged += + (s, e) => + { + switch (e.Action) + { + case NotifyCollectionChangedAction.Add: + e.NewItems.OfType().Apply(x => x.Parent = this); + break; + case NotifyCollectionChangedAction.Remove: + e.OldItems.OfType().Apply(x => x.Parent = null); + break; + case NotifyCollectionChangedAction.Replace: + e.NewItems.OfType().Apply(x => x.Parent = this); + e.OldItems.OfType().Apply(x => x.Parent = null); + break; + case NotifyCollectionChangedAction.Reset: + _items.OfType().Apply(x => x.Parent = this); + break; + } + }; /// /// Gets the items that are currently being conducted. /// - public IObservableCollection Items => _items; + public IObservableCollection Items + => _items; /// /// Gets the children. /// /// The collection of children. - public override IEnumerable GetChildren() => _items; + public override IEnumerable GetChildren() + => _items; /// /// Activates the specified item. @@ -169,7 +173,7 @@ public override async Task CanCloseAsync(CancellationToken cancellationTok closable = stillToClose; } - foreach(IDeactivate deactivate in closable.OfType()) + foreach (IDeactivate deactivate in closable.OfType()) { await deactivate.DeactivateAsync(true, cancellationToken); } @@ -185,7 +189,8 @@ public override async Task CanCloseAsync(CancellationToken cancellationTok /// /// The cancellation token to cancel operation. /// A task that represents the asynchronous operation. - protected override Task OnActivateAsync(CancellationToken cancellationToken) => ScreenExtensions.TryActivateAsync(ActiveItem, cancellationToken); + protected override Task OnActivateAsync(CancellationToken cancellationToken) + => ScreenExtensions.TryActivateAsync(ActiveItem, cancellationToken); /// /// Called when deactivating. diff --git a/src/Caliburn.Micro.Core/Conductor/DefaultImpl/DefaultCloseStrategy.cs b/src/Caliburn.Micro.Core/Conductor/DefaultImpl/DefaultCloseStrategy.cs index df918e2a0..6b738b46e 100644 --- a/src/Caliburn.Micro.Core/Conductor/DefaultImpl/DefaultCloseStrategy.cs +++ b/src/Caliburn.Micro.Core/Conductor/DefaultImpl/DefaultCloseStrategy.cs @@ -16,7 +16,8 @@ public class DefaultCloseStrategy : ICloseStrategy /// Creates an instance of the class. /// /// Indicates that even if all conducted items are not closable, those that are should be closed. The default is FALSE. - public DefaultCloseStrategy(bool closeConductedItemsWhenConductorCannotClose = false) => _closeConductedItemsWhenConductorCannotClose = closeConductedItemsWhenConductorCannotClose; + public DefaultCloseStrategy(bool closeConductedItemsWhenConductorCannotClose = false) + => _closeConductedItemsWhenConductorCannotClose = closeConductedItemsWhenConductorCannotClose; /// public async Task> ExecuteAsync(IEnumerable toClose, CancellationToken cancellationToken = default) diff --git a/src/Caliburn.Micro.Core/Conductor/Extensions/ConductorExtensions.cs b/src/Caliburn.Micro.Core/Conductor/Extensions/ConductorExtensions.cs index 283df14a8..2e439b482 100644 --- a/src/Caliburn.Micro.Core/Conductor/Extensions/ConductorExtensions.cs +++ b/src/Caliburn.Micro.Core/Conductor/Extensions/ConductorExtensions.cs @@ -14,6 +14,7 @@ public static class ConductorExtensions /// The conductor to activate the item with. /// The item to activate. /// A task that represents the asynchronous operation. - public static Task ActivateItemAsync(this IConductor conductor, object item) => conductor.ActivateItemAsync(item, default); + public static Task ActivateItemAsync(this IConductor conductor, object item) + => conductor.ActivateItemAsync(item, default); } } diff --git a/src/Caliburn.Micro.Core/Coroutine/ExtensionPoints/Coroutine.cs b/src/Caliburn.Micro.Core/Coroutine/ExtensionPoints/Coroutine.cs index 90fce9420..9adab9c9d 100644 --- a/src/Caliburn.Micro.Core/Coroutine/ExtensionPoints/Coroutine.cs +++ b/src/Caliburn.Micro.Core/Coroutine/ExtensionPoints/Coroutine.cs @@ -9,12 +9,14 @@ namespace Caliburn.Micro /// public static class Coroutine { - private static readonly ILog Log = LogManager.GetLog(typeof(Coroutine)); + private static readonly ILog Log + = LogManager.GetLog(typeof(Coroutine)); /// /// Creates the parent enumerator. /// - public static Func, IResult> CreateParentEnumerator = inner => new SequentialResult(inner); + public static Func, IResult> CreateParentEnumerator + = inner => new SequentialResult(inner); /// /// Executes a coroutine. @@ -22,7 +24,10 @@ public static class Coroutine /// The coroutine to execute. /// The context to execute the coroutine within. /// /// The completion callback for the coroutine. - public static void BeginExecute(IEnumerator coroutine, CoroutineExecutionContext context = null, EventHandler callback = null) + public static void BeginExecute( + IEnumerator coroutine, + CoroutineExecutionContext context = null, + EventHandler callback = null) { Log.Info("Executing coroutine."); @@ -44,30 +49,37 @@ public static void BeginExecute(IEnumerator coroutine, CoroutineExecuti /// The coroutine to execute. /// The context to execute the coroutine within. /// A task that represents the asynchronous coroutine. - public static Task ExecuteAsync(IEnumerator coroutine, CoroutineExecutionContext context = null) + public static Task ExecuteAsync( + IEnumerator coroutine, + CoroutineExecutionContext context = null) { var taskSource = new TaskCompletionSource(); - BeginExecute(coroutine, context, (s, e) => - { - if (e.Error != null) - { - taskSource.SetException(e.Error); - } - else if (e.WasCancelled) - { - taskSource.SetCanceled(); - } - else + BeginExecute( + coroutine, + context, + (s, e) => { - taskSource.SetResult(null); - } - }); + if (e.Error != null) + { + taskSource.SetException(e.Error); + } + else if (e.WasCancelled) + { + taskSource.SetCanceled(); + } + else + { + taskSource.SetResult(null); + } + }); return taskSource.Task; } - private static void ExecuteOnCompleted(IResult result, EventHandler handler) + private static void ExecuteOnCompleted( + IResult result, + EventHandler handler) { void OnCompledted(object s, ResultCompletionEventArgs e) { @@ -81,20 +93,21 @@ void OnCompledted(object s, ResultCompletionEventArgs e) /// /// Called upon completion of a coroutine. /// - public static event EventHandler Completed = (s, e) => - { - if (e.Error != null) - { - Log.Error(e.Error); - } - else if (e.WasCancelled) + public static event EventHandler Completed + = (s, e) => { - Log.Info("Coroutine execution cancelled."); - } - else - { - Log.Info("Coroutine execution completed."); - } - }; + if (e.Error != null) + { + Log.Error(e.Error); + } + else if (e.WasCancelled) + { + Log.Info("Coroutine execution cancelled."); + } + else + { + Log.Info("Coroutine execution completed."); + } + }; } } diff --git a/src/Caliburn.Micro.Core/EventAggregator/EventAggregator.cs b/src/Caliburn.Micro.Core/EventAggregator/EventAggregator.cs index cf8176e3e..eb3e9f24c 100644 --- a/src/Caliburn.Micro.Core/EventAggregator/EventAggregator.cs +++ b/src/Caliburn.Micro.Core/EventAggregator/EventAggregator.cs @@ -133,9 +133,11 @@ public Handler(object handler, Func, Task> marshal) } } - public bool IsDead => _reference.Target == null; + public bool IsDead + => _reference.Target == null; - public bool Matches(object instance) => _reference.Target == instance; + public bool Matches(object instance) + => _reference.Target == instance; public Task Handle(Type messageType, object message, CancellationToken cancellationToken) { @@ -158,7 +160,8 @@ public Task Handle(Type messageType, object message, CancellationToken cancellat }); } - public bool Handles(Type messageType) => _supportedHandlers.Any(pair => pair.Key.GetTypeInfo().IsAssignableFrom(messageType.GetTypeInfo())); + public bool Handles(Type messageType) + => _supportedHandlers.Any(pair => pair.Key.GetTypeInfo().IsAssignableFrom(messageType.GetTypeInfo())); } } } diff --git a/src/Caliburn.Micro.Core/EventAggregator/Extensions/EventAggregatorExtensions.cs b/src/Caliburn.Micro.Core/EventAggregator/Extensions/EventAggregatorExtensions.cs index 075ca5dbc..1fa836216 100644 --- a/src/Caliburn.Micro.Core/EventAggregator/Extensions/EventAggregatorExtensions.cs +++ b/src/Caliburn.Micro.Core/EventAggregator/Extensions/EventAggregatorExtensions.cs @@ -15,7 +15,8 @@ public static class EventAggregatorExtensions /// The subscription is invoked on the thread chosen by the publisher. /// /// The instance to subscribe for event publication. - public static void SubscribeOnPublishedThread(this IEventAggregator eventAggregator, object subscriber) => eventAggregator.Subscribe(subscriber, f => f()); + public static void SubscribeOnPublishedThread(this IEventAggregator eventAggregator, object subscriber) + => eventAggregator.Subscribe(subscriber, f => f()); /// /// Subscribes an instance to all events declared through implementations of . @@ -24,7 +25,8 @@ public static class EventAggregatorExtensions /// /// The instance to subscribe for event publication. [Obsolete("Use SubscribeOnPublishedThread")] - public static void Subscribe(this IEventAggregator eventAggregator, object subscriber) => eventAggregator.SubscribeOnPublishedThread(subscriber); + public static void Subscribe(this IEventAggregator eventAggregator, object subscriber) + => eventAggregator.SubscribeOnPublishedThread(subscriber); /// /// Subscribes an instance to all events declared through implementations of . @@ -32,7 +34,8 @@ public static class EventAggregatorExtensions /// The subscription is invoked on a new background thread. /// /// The instance to subscribe for event publication. - public static void SubscribeOnBackgroundThread(this IEventAggregator eventAggregator, object subscriber) => eventAggregator.Subscribe(subscriber, f => Task.Factory.StartNew(f, default, TaskCreationOptions.None, TaskScheduler.Default)); + public static void SubscribeOnBackgroundThread(this IEventAggregator eventAggregator, object subscriber) + => eventAggregator.Subscribe(subscriber, f => Task.Factory.StartNew(f, default, TaskCreationOptions.None, TaskScheduler.Default)); /// /// Subscribes an instance to all events declared through implementations of . @@ -40,31 +43,34 @@ public static class EventAggregatorExtensions /// The subscription is invoked on the UI thread. /// /// The instance to subscribe for event publication. - public static void SubscribeOnUIThread(this IEventAggregator eventAggregator, object subscriber) => eventAggregator.Subscribe(subscriber, f => - { - var taskCompletionSource = new TaskCompletionSource(); - - Execute.BeginOnUIThread(async () => - { - try - { - await f(); - - taskCompletionSource.SetResult(true); - } - catch (OperationCanceledException) - { - taskCompletionSource.SetCanceled(); - } - catch (Exception ex) - { - taskCompletionSource.SetException(ex); - } - }); - - return taskCompletionSource.Task; - - }); + public static void SubscribeOnUIThread(this IEventAggregator eventAggregator, object subscriber) + => eventAggregator.Subscribe( + subscriber, + f => + { + var taskCompletionSource = new TaskCompletionSource(); + + Execute.BeginOnUIThread(async () => + { + try + { + await f(); + + taskCompletionSource.SetResult(true); + } + catch (OperationCanceledException) + { + taskCompletionSource.SetCanceled(); + } + catch (Exception ex) + { + taskCompletionSource.SetException(ex); + } + }); + + return taskCompletionSource.Task; + + }); /// /// Publishes a message on the current thread (synchrone). @@ -73,7 +79,8 @@ public static void SubscribeOnUIThread(this IEventAggregator eventAggregator, ob /// The message instance. /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// A task that represents the asynchronous operation. - public static Task PublishOnCurrentThreadAsync(this IEventAggregator eventAggregator, object message, CancellationToken cancellationToken) => eventAggregator.PublishAsync(message, f => f(), cancellationToken); + public static Task PublishOnCurrentThreadAsync(this IEventAggregator eventAggregator, object message, CancellationToken cancellationToken) + => eventAggregator.PublishAsync(message, f => f(), cancellationToken); /// /// Publishes a message on the current thread (synchrone). @@ -81,7 +88,8 @@ public static void SubscribeOnUIThread(this IEventAggregator eventAggregator, ob /// The event aggregator. /// The message instance. /// A task that represents the asynchronous operation. - public static Task PublishOnCurrentThreadAsync(this IEventAggregator eventAggregator, object message) => eventAggregator.PublishOnCurrentThreadAsync(message, default); + public static Task PublishOnCurrentThreadAsync(this IEventAggregator eventAggregator, object message) + => eventAggregator.PublishOnCurrentThreadAsync(message, default); /// /// Publishes a message on a background thread (async). @@ -90,7 +98,8 @@ public static void SubscribeOnUIThread(this IEventAggregator eventAggregator, ob /// The message instance. /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// A task that represents the asynchronous operation. - public static Task PublishOnBackgroundThreadAsync(this IEventAggregator eventAggregator, object message, CancellationToken cancellationToken) => eventAggregator.PublishAsync(message, f => Task.Factory.StartNew(f, default, TaskCreationOptions.None, TaskScheduler.Default), cancellationToken); + public static Task PublishOnBackgroundThreadAsync(this IEventAggregator eventAggregator, object message, CancellationToken cancellationToken) + => eventAggregator.PublishAsync(message, f => Task.Factory.StartNew(f, default, TaskCreationOptions.None, TaskScheduler.Default), cancellationToken); /// /// Publishes a message on a background thread (async). @@ -98,7 +107,8 @@ public static void SubscribeOnUIThread(this IEventAggregator eventAggregator, ob /// The event aggregator. /// The message instance. /// A task that represents the asynchronous operation. - public static Task PublishOnBackgroundThreadAsync(this IEventAggregator eventAggregator, object message) => eventAggregator.PublishOnBackgroundThreadAsync(message, default); + public static Task PublishOnBackgroundThreadAsync(this IEventAggregator eventAggregator, object message) + => eventAggregator.PublishOnBackgroundThreadAsync(message, default); /// /// Publishes a message on the UI thread. @@ -107,31 +117,34 @@ public static void SubscribeOnUIThread(this IEventAggregator eventAggregator, ob /// The message instance. /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// A task that represents the asynchronous operation. - public static Task PublishOnUIThreadAsync(this IEventAggregator eventAggregator, object message, CancellationToken cancellationToken) => eventAggregator.PublishAsync(message, f => - { - var taskCompletionSource = new TaskCompletionSource(); - - Execute.BeginOnUIThread(async () => - { - try - { - await f(); - - taskCompletionSource.SetResult(true); - } - catch (OperationCanceledException) - { - taskCompletionSource.SetCanceled(); - } - catch (Exception ex) - { - taskCompletionSource.SetException(ex); - } - }); - - return taskCompletionSource.Task; - - }, cancellationToken); + public static Task PublishOnUIThreadAsync(this IEventAggregator eventAggregator, object message, CancellationToken cancellationToken) + => eventAggregator.PublishAsync( + message, + f => + { + var taskCompletionSource = new TaskCompletionSource(); + + Execute.BeginOnUIThread(async () => + { + try + { + await f(); + + taskCompletionSource.SetResult(true); + } + catch (OperationCanceledException) + { + taskCompletionSource.SetCanceled(); + } + catch (Exception ex) + { + taskCompletionSource.SetException(ex); + } + }); + + return taskCompletionSource.Task; + + }, cancellationToken); /// /// Publishes a message on the UI thread. @@ -139,6 +152,7 @@ public static Task PublishOnUIThreadAsync(this IEventAggregator eventAggregator, /// The event aggregator. /// The message instance. /// A task that represents the asynchronous operation. - public static Task PublishOnUIThreadAsync(this IEventAggregator eventAggregator, object message) => eventAggregator.PublishOnUIThreadAsync(message, default); + public static Task PublishOnUIThreadAsync(this IEventAggregator eventAggregator, object message) + => eventAggregator.PublishOnUIThreadAsync(message, default); } } diff --git a/src/Caliburn.Micro.Core/Extensions/Execute.cs b/src/Caliburn.Micro.Core/Extensions/Execute.cs index 4a232b117..1449c302e 100644 --- a/src/Caliburn.Micro.Core/Extensions/Execute.cs +++ b/src/Caliburn.Micro.Core/Extensions/Execute.cs @@ -11,24 +11,28 @@ public static class Execute /// /// Indicates whether or not the framework is in design-time mode. /// - public static bool InDesignMode => PlatformProvider.Current.InDesignMode; + public static bool InDesignMode + => PlatformProvider.Current.InDesignMode; /// /// Executes the action on the UI thread asynchronously. /// /// The action to execute. - public static void BeginOnUIThread(this Action action) => PlatformProvider.Current.BeginOnUIThread(action); + public static void BeginOnUIThread(this Action action) + => PlatformProvider.Current.BeginOnUIThread(action); /// /// Executes the action on the UI thread asynchronously. /// /// The action to execute. - public static Task OnUIThreadAsync(this Func action) => PlatformProvider.Current.OnUIThreadAsync(action); + public static Task OnUIThreadAsync(this Func action) + => PlatformProvider.Current.OnUIThreadAsync(action); /// /// Executes the action on the UI thread. /// /// The action to execute. - public static void OnUIThread(this Action action) => PlatformProvider.Current.OnUIThread(action); + public static void OnUIThread(this Action action) + => PlatformProvider.Current.OnUIThread(action); } } diff --git a/src/Caliburn.Micro.Core/IoC/ExtensionPoints/IoC.cs b/src/Caliburn.Micro.Core/IoC/ExtensionPoints/IoC.cs index fa91dd05b..5e20963cf 100644 --- a/src/Caliburn.Micro.Core/IoC/ExtensionPoints/IoC.cs +++ b/src/Caliburn.Micro.Core/IoC/ExtensionPoints/IoC.cs @@ -12,17 +12,20 @@ public static class IoC /// /// Gets an instance by type and key. /// - public static Func GetInstance = (service, key) => { throw new InvalidOperationException("IoC is not initialized."); }; + public static Func GetInstance = (service, key) + => throw new InvalidOperationException("IoC is not initialized."); /// /// Gets all instances of a particular type. /// - public static Func> GetAllInstances = service => { throw new InvalidOperationException("IoC is not initialized."); }; + public static Func> GetAllInstances = service + => throw new InvalidOperationException("IoC is not initialized."); /// /// Passes an existing instance to the IoC container to enable dependencies to be injected. /// - public static Action BuildUp = instance => { throw new InvalidOperationException("IoC is not initialized."); }; + public static Action BuildUp = instance + => throw new InvalidOperationException("IoC is not initialized."); /// /// Gets an instance from the container. @@ -30,13 +33,15 @@ public static class IoC /// The type to resolve. /// The key to look up. /// The resolved instance. - public static T Get(string key = null) => (T)GetInstance(typeof(T), key); + public static T Get(string key = null) + => (T)GetInstance(typeof(T), key); /// /// Gets all instances of a particular type. /// /// The type to resolve. /// The resolved instances. - public static IEnumerable GetAll() => GetAllInstances(typeof(T)).Cast(); + public static IEnumerable GetAll() + => GetAllInstances(typeof(T)).Cast(); } } diff --git a/src/Caliburn.Micro.Core/IoC/Extensions/ContainerExtensions.cs b/src/Caliburn.Micro.Core/IoC/Extensions/ContainerExtensions.cs index d35c00fb8..adb23a2de 100644 --- a/src/Caliburn.Micro.Core/IoC/Extensions/ContainerExtensions.cs +++ b/src/Caliburn.Micro.Core/IoC/Extensions/ContainerExtensions.cs @@ -17,7 +17,8 @@ public static class ContainerExtensions /// The container. /// The key. /// The container. - public static SimpleContainer Singleton(this SimpleContainer container, string key = null) => Singleton(container, key); + public static SimpleContainer Singleton(this SimpleContainer container, string key = null) + => Singleton(container, key); /// /// Registers a singleton. @@ -41,7 +42,8 @@ public static SimpleContainer Singleton(this SimpleCo /// The container. /// The key. /// The container. - public static SimpleContainer PerRequest(this SimpleContainer container, string key = null) => PerRequest(container, key); + public static SimpleContainer PerRequest(this SimpleContainer container, string key = null) + => PerRequest(container, key); /// /// Registers an service to be created on each request. @@ -100,11 +102,11 @@ public static SimpleContainer AllTypesOf(this SimpleContainer containe Type serviceType = typeof(TService); IEnumerable types = from type in assembly.DefinedTypes - where serviceType.GetTypeInfo().IsAssignableFrom(type) - && !type.IsAbstract - && !type.IsInterface - && filter(type.AsType()) - select type; + where serviceType.GetTypeInfo().IsAssignableFrom(type) + && !type.IsAbstract + && !type.IsInterface + && filter(type.AsType()) + select type; foreach (TypeInfo type in types) { @@ -121,7 +123,8 @@ where serviceType.GetTypeInfo().IsAssignableFrom(type) /// The container. /// The key. /// The instance. - public static TService GetInstance(this SimpleContainer container, string key = null) => (TService)container.GetInstance(typeof(TService), key); + public static TService GetInstance(this SimpleContainer container, string key = null) + => (TService)container.GetInstance(typeof(TService), key); /// /// Gets all instances of a particular type and the given key (default null). @@ -130,7 +133,8 @@ where serviceType.GetTypeInfo().IsAssignableFrom(type) /// The container. /// The key shared by those instances /// The resolved instances. - public static IEnumerable GetAllInstances(this SimpleContainer container, string key = null) => container.GetAllInstances(typeof(TService), key).Cast(); + public static IEnumerable GetAllInstances(this SimpleContainer container, string key = null) + => container.GetAllInstances(typeof(TService), key).Cast(); /// /// Determines if a handler for the service/key has previously been registered. @@ -139,7 +143,8 @@ where serviceType.GetTypeInfo().IsAssignableFrom(type) /// The container. /// The key. /// True if a handler is registere; false otherwise. - public static bool HasHandler(this SimpleContainer container, string key = null) => container.HasHandler(typeof(TService), key); + public static bool HasHandler(this SimpleContainer container, string key = null) + => container.HasHandler(typeof(TService), key); /// /// Unregisters any handlers for the service/key that have previously been registered. @@ -147,6 +152,7 @@ where serviceType.GetTypeInfo().IsAssignableFrom(type) /// The service type. /// The container. /// The key. - public static void UnregisterHandler(this SimpleContainer container, string key = null) => container.UnregisterHandler(typeof(TService), key); + public static void UnregisterHandler(this SimpleContainer container, string key = null) + => container.UnregisterHandler(typeof(TService), key); } } diff --git a/src/Caliburn.Micro.Core/IoC/SimpleContainer.cs b/src/Caliburn.Micro.Core/IoC/SimpleContainer.cs index f239de855..e4fe64a38 100644 --- a/src/Caliburn.Micro.Core/IoC/SimpleContainer.cs +++ b/src/Caliburn.Micro.Core/IoC/SimpleContainer.cs @@ -21,9 +21,11 @@ public class SimpleContainer /// /// Initializes a new instance of the class. /// - public SimpleContainer() => _entries = new List(); + public SimpleContainer() + => _entries = new List(); - private SimpleContainer(IEnumerable entries) => _entries = new List(entries); + private SimpleContainer(IEnumerable entries) + => _entries = new List(entries); /// /// Whether to enable recursive property injection for all resolutions. @@ -36,7 +38,8 @@ public class SimpleContainer /// The service. /// The key. /// The implementation. - public void RegisterInstance(Type service, string key, object implementation) => RegisterHandler(service, key, container => implementation); + public void RegisterInstance(Type service, string key, object implementation) + => RegisterHandler(service, key, container => implementation); /// /// Registers the class so that a new instance is created on every request. @@ -44,7 +47,8 @@ public class SimpleContainer /// The service. /// The key. /// The implementation. - public void RegisterPerRequest(Type service, string key, Type implementation) => RegisterHandler(service, key, container => container.BuildInstance(implementation)); + public void RegisterPerRequest(Type service, string key, Type implementation) + => RegisterHandler(service, key, container => container.BuildInstance(implementation)); /// /// Registers the class so that it is created once, on first request, and the same instance is returned to all requestors thereafter. @@ -64,7 +68,8 @@ public void RegisterSingleton(Type service, string key, Type implementation) /// The service. /// The key. /// The handler. - public void RegisterHandler(Type service, string key, Func handler) => GetOrCreateEntry(service, key).Add(handler); + public void RegisterHandler(Type service, string key, Func handler) + => GetOrCreateEntry(service, key).Add(handler); /// /// Unregisters any handlers for the service/key that have previously been registered. @@ -144,7 +149,8 @@ public object GetInstance(Type service, string key) /// The service. /// The key. /// True if a handler is registere; false otherwise. - public bool HasHandler(Type service, string key) => GetEntry(service, key) != null; + public bool HasHandler(Type service, string key) + => GetEntry(service, key) != null; /// /// Requests all instances of a given type and the given key (default null). @@ -200,7 +206,8 @@ public void BuildUp(object instance) /// Creates a child container. /// /// A new container. - public SimpleContainer CreateChildContainer() => new(_entries); + public SimpleContainer CreateChildContainer() + => new(_entries); private ContainerEntry GetOrCreateEntry(Type service, string key) { @@ -272,16 +279,17 @@ private object[] DetermineConstructorArgs(Type implementation) return args.ToArray(); } - private ConstructorInfo SelectEligibleConstructor(Type type) => type.GetTypeInfo().DeclaredConstructors - .Where(c => c.IsPublic) - .Select(c => new - { - Constructor = c, - HandledParamters = c.GetParameters().Count(p => HasHandler(p.ParameterType, null)) - }) - .OrderByDescending(c => c.HandledParamters) - .Select(c => c.Constructor) - .FirstOrDefault(); + private ConstructorInfo SelectEligibleConstructor(Type type) + => type.GetTypeInfo().DeclaredConstructors + .Where(c => c.IsPublic) + .Select(c => new + { + Constructor = c, + HandledParamters = c.GetParameters().Count(p => HasHandler(p.ParameterType, null)) + }) + .OrderByDescending(c => c.HandledParamters) + .Select(c => c.Constructor) + .FirstOrDefault(); private class ContainerEntry : List> { @@ -291,7 +299,8 @@ private class ContainerEntry : List> private class FactoryFactory { - public Func Create(SimpleContainer container) => () => (T)container.GetInstance(typeof(T), null); + public Func Create(SimpleContainer container) + => () => (T)container.GetInstance(typeof(T), null); } } } diff --git a/src/Caliburn.Micro.Core/Logging/ExtensionPoints/LogManager.cs b/src/Caliburn.Micro.Core/Logging/ExtensionPoints/LogManager.cs index 6d1dab146..a5361a93f 100644 --- a/src/Caliburn.Micro.Core/Logging/ExtensionPoints/LogManager.cs +++ b/src/Caliburn.Micro.Core/Logging/ExtensionPoints/LogManager.cs @@ -12,7 +12,8 @@ public static class LogManager /// /// Creates an for the provided type. /// - public static Func GetLog = type => NullLogInstance; + public static Func GetLog + = type => NullLogInstance; private class NullLog : ILog { diff --git a/src/Caliburn.Micro.Core/Logging/Impl/DebugLog.cs b/src/Caliburn.Micro.Core/Logging/Impl/DebugLog.cs index 1e42604cf..014fab5f1 100644 --- a/src/Caliburn.Micro.Core/Logging/Impl/DebugLog.cs +++ b/src/Caliburn.Micro.Core/Logging/Impl/DebugLog.cs @@ -16,26 +16,30 @@ public class DebugLog : ILog /// Initializes a new instance of the class. /// /// The type. - public DebugLog(Type type) => _typeName = type.FullName; + public DebugLog(Type type) + => _typeName = type.FullName; /// /// Logs the message as info. /// /// A formatted message. /// Parameters to be injected into the formatted message. - public void Info(string format, params object[] args) => Debug.WriteLine("[{1}] INFO: {0}", string.Format(format, args), _typeName); + public void Info(string format, params object[] args) + => Debug.WriteLine("[{1}] INFO: {0}", string.Format(format, args), _typeName); /// /// Logs the message as a warning. /// /// A formatted message. /// Parameters to be injected into the formatted message. - public void Warn(string format, params object[] args) => Debug.WriteLine("[{1}] WARN: {0}", string.Format(format, args), _typeName); + public void Warn(string format, params object[] args) + => Debug.WriteLine("[{1}] WARN: {0}", string.Format(format, args), _typeName); /// /// Logs the exception. /// /// The exception. - public void Error(Exception exception) => Debug.WriteLine("[{1}] ERROR: {0}", exception, _typeName); + public void Error(Exception exception) + => Debug.WriteLine("[{1}] ERROR: {0}", exception, _typeName); } } diff --git a/src/Caliburn.Micro.Core/PlatformProvider/DefaultImpl/DefaultPlatformProvider.cs b/src/Caliburn.Micro.Core/PlatformProvider/DefaultImpl/DefaultPlatformProvider.cs index 91af7c6bf..e93ff1166 100644 --- a/src/Caliburn.Micro.Core/PlatformProvider/DefaultImpl/DefaultPlatformProvider.cs +++ b/src/Caliburn.Micro.Core/PlatformProvider/DefaultImpl/DefaultPlatformProvider.cs @@ -13,31 +13,36 @@ public class DefaultPlatformProvider : IPlatformProvider /// /// Indicates whether or not the framework is in design-time mode. /// - public virtual bool InDesignMode => true; + public virtual bool InDesignMode + => true; /// /// Executes the action on the UI thread asynchronously. /// /// The action to execute. - public virtual void BeginOnUIThread(Action action) => action(); + public virtual void BeginOnUIThread(Action action) + => action(); /// /// Executes the action on the UI thread asynchronously. /// /// The action to execute. /// - public virtual Task OnUIThreadAsync(Func action) => Task.Factory.StartNew(action); + public virtual Task OnUIThreadAsync(Func action) + => Task.Factory.StartNew(action); /// /// Executes the action on the UI thread. /// /// The action to execute. - public virtual void OnUIThread(Action action) => action(); + public virtual void OnUIThread(Action action) + => action(); /// /// Whether or not classes should execute property change notications on the UI thread. /// - public virtual bool PropertyChangeNotificationsOnUIThread => true; + public virtual bool PropertyChangeNotificationsOnUIThread + => true; /// /// Used to retrieve the root, non-framework-created view. @@ -52,7 +57,8 @@ public class DefaultPlatformProvider : IPlatformProvider /// The WindowManager marks that element as a framework-created element so that it can determine what it created vs. what was intended by the developer. /// Calling GetFirstNonGeneratedView allows the framework to discover what the original element was. /// - public virtual object GetFirstNonGeneratedView(object view) => view; + public virtual object GetFirstNonGeneratedView(object view) + => view; /// /// Executes the handler the fist time the view is loaded. @@ -60,14 +66,16 @@ public class DefaultPlatformProvider : IPlatformProvider /// The view. /// The handler. /// true if the handler was executed immediately; false otherwise - public virtual void ExecuteOnFirstLoad(object view, Action handler) => handler(view); + public virtual void ExecuteOnFirstLoad(object view, Action handler) + => handler(view); /// /// Executes the handler the next time the view's LayoutUpdated event fires. /// /// The view. /// The handler. - public virtual void ExecuteOnLayoutUpdated(object view, Action handler) => handler(view); + public virtual void ExecuteOnLayoutUpdated(object view, Action handler) + => handler(view); /// /// Get the close action for the specified view model. @@ -78,6 +86,7 @@ public class DefaultPlatformProvider : IPlatformProvider /// /// An to close the view model. /// - public virtual Func GetViewCloseAction(object viewModel, ICollection views, bool? dialogResult) => ct => Task.FromResult(true); + public virtual Func GetViewCloseAction(object viewModel, ICollection views, bool? dialogResult) + => ct => Task.FromResult(true); } } diff --git a/src/Caliburn.Micro.Core/PlatformProvider/ExtensionPoints/PlatformProvider.cs b/src/Caliburn.Micro.Core/PlatformProvider/ExtensionPoints/PlatformProvider.cs index 76014ef49..72d795504 100644 --- a/src/Caliburn.Micro.Core/PlatformProvider/ExtensionPoints/PlatformProvider.cs +++ b/src/Caliburn.Micro.Core/PlatformProvider/ExtensionPoints/PlatformProvider.cs @@ -8,6 +8,7 @@ public static class PlatformProvider /// /// Gets or sets the current . /// - public static IPlatformProvider Current { get; set; } = new DefaultPlatformProvider(); + public static IPlatformProvider Current { get; set; } + = new DefaultPlatformProvider(); } } diff --git a/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs b/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs index f9187e49e..110775baf 100644 --- a/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs +++ b/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs @@ -14,14 +14,16 @@ public static class ResultExtensions /// The result to decorate. /// The coroutine to execute when was canceled. /// - public static IResult WhenCancelled(this IResult result, Func coroutine) => new ContinueResultDecorator(result, coroutine); + public static IResult WhenCancelled(this IResult result, Func coroutine) + => new ContinueResultDecorator(result, coroutine); /// /// Overrides of the decorated instance. /// /// The result to decorate. /// - public static IResult OverrideCancel(this IResult result) => new OverrideCancelResultDecorator(result); + public static IResult OverrideCancel(this IResult result) + => new OverrideCancelResultDecorator(result); /// /// Rescues from the decorated by executing a coroutine. @@ -31,9 +33,9 @@ public static class ResultExtensions /// The rescue coroutine. /// Set to true to cancel the result after executing rescue. /// - public static IResult Rescue(this IResult result, Func rescue, - bool cancelResult = true) - where TException : Exception => new RescueResultDecorator(result, rescue, cancelResult); + public static IResult Rescue(this IResult result, Func rescue, bool cancelResult = true) + where TException : Exception + => new RescueResultDecorator(result, rescue, cancelResult); /// /// Rescues any exception from the decorated by executing a coroutine. @@ -42,8 +44,8 @@ public static IResult Rescue(this IResult result, FuncThe rescue coroutine. /// Set to true to cancel the result after executing rescue. /// - public static IResult Rescue(this IResult result, Func rescue, - bool cancelResult = true) => Rescue(result, rescue, cancelResult); + public static IResult Rescue(this IResult result, Func rescue, bool cancelResult = true) + => Rescue(result, rescue, cancelResult); /// /// Executes an asynchronous. @@ -51,7 +53,8 @@ public static IResult Rescue(this IResult result, Func rescu /// The coroutine to execute. /// The context to execute the coroutine within. /// A task that represents the asynchronous coroutine. - public static Task ExecuteAsync(this IResult result, CoroutineExecutionContext context = null) => InternalExecuteAsync(result, context); + public static Task ExecuteAsync(this IResult result, CoroutineExecutionContext context = null) + => InternalExecuteAsync(result, context); /// /// Executes an asynchronous. @@ -60,8 +63,8 @@ public static IResult Rescue(this IResult result, Func rescu /// The coroutine to execute. /// The context to execute the coroutine within. /// A task that represents the asynchronous coroutine. - public static Task ExecuteAsync(this IResult result, - CoroutineExecutionContext context = null) => InternalExecuteAsync(result, context); + public static Task ExecuteAsync(this IResult result, CoroutineExecutionContext context = null) + => InternalExecuteAsync(result, context); /// @@ -69,7 +72,8 @@ public static Task ExecuteAsync(this IResult result, /// /// The task. /// The coroutine that encapsulates the task. - public static TaskResult AsResult(this Task task) => new(task); + public static TaskResult AsResult(this Task task) + => new(task); /// /// Encapsulates a task inside a couroutine. @@ -77,7 +81,8 @@ public static Task ExecuteAsync(this IResult result, /// The type of the result. /// The task. /// The coroutine that encapsulates the task. - public static TaskResult AsResult(this Task task) => new(task); + public static TaskResult AsResult(this Task task) + => new(task); private static Task InternalExecuteAsync(IResult result, CoroutineExecutionContext context) { diff --git a/src/Caliburn.Micro.Core/Result/Impl/DelegateResult.cs b/src/Caliburn.Micro.Core/Result/Impl/DelegateResult.cs index 8ac540963..bcf360efe 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/DelegateResult.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/DelegateResult.cs @@ -13,7 +13,8 @@ public class DelegateResult : IResult /// Initializes a new instance of the class. /// /// The action. - public DelegateResult(Action action) => _toExecute = action; + public DelegateResult(Action action) + => _toExecute = action; /// /// Executes the result using the specified context. diff --git a/src/Caliburn.Micro.Core/Result/Impl/DelegateResult{TResult}.cs b/src/Caliburn.Micro.Core/Result/Impl/DelegateResult{TResult}.cs index 6d96cb505..6c571185f 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/DelegateResult{TResult}.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/DelegateResult{TResult}.cs @@ -14,7 +14,8 @@ public class DelegateResult : IResult /// Initializes a new instance of the class. /// /// The action. - public DelegateResult(Func action) => _toExecute = action; + public DelegateResult(Func action) + => _toExecute = action; /// /// Executes the result using the specified context. diff --git a/src/Caliburn.Micro.Core/Result/Impl/OverrideCancelResultDecorator.cs b/src/Caliburn.Micro.Core/Result/Impl/OverrideCancelResultDecorator.cs index 46b576aba..6bee81535 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/OverrideCancelResultDecorator.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/OverrideCancelResultDecorator.cs @@ -5,14 +5,17 @@ /// public class OverrideCancelResultDecorator : ResultDecoratorBase { - private static readonly ILog Log = LogManager.GetLog(typeof(OverrideCancelResultDecorator)); + private static readonly ILog Log + = LogManager.GetLog(typeof(OverrideCancelResultDecorator)); /// /// Initializes a new instance of the class. /// /// The result to decorate. public OverrideCancelResultDecorator(IResult result) - : base(result) { } + : base(result) + { + } /// /// Called when the execution of the decorated result has completed. diff --git a/src/Caliburn.Micro.Core/Result/Impl/ResultDecoratorBase.cs b/src/Caliburn.Micro.Core/Result/Impl/ResultDecoratorBase.cs index 852d5cba9..ce46f7aa4 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/ResultDecoratorBase.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/ResultDecoratorBase.cs @@ -14,7 +14,8 @@ public abstract class ResultDecoratorBase : IResult /// Initializes a new instance of the class. /// /// The result to decorate. - protected ResultDecoratorBase(IResult result) => _innerResult = result ?? throw new ArgumentNullException("result"); + protected ResultDecoratorBase(IResult result) + => _innerResult = result ?? throw new ArgumentNullException("result"); /// /// Executes the result using the specified context. @@ -60,6 +61,7 @@ private void InnerResultCompleted(object sender, ResultCompletionEventArgs args) /// Raises the event. /// /// The instance containing the event data. - protected void OnCompleted(ResultCompletionEventArgs args) => Completed(this, args); + protected void OnCompleted(ResultCompletionEventArgs args) + => Completed(this, args); } } diff --git a/src/Caliburn.Micro.Core/Result/Impl/SequentialResult.cs b/src/Caliburn.Micro.Core/Result/Impl/SequentialResult.cs index 0d6157efc..a2ac6c1dd 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/SequentialResult.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/SequentialResult.cs @@ -15,7 +15,8 @@ public class SequentialResult : IResult /// Initializes a new instance of the class. /// /// The enumerator. - public SequentialResult(IEnumerator enumerator) => _enumerator = enumerator; + public SequentialResult(IEnumerator enumerator) + => _enumerator = enumerator; /// /// Occurs when execution has completed. diff --git a/src/Caliburn.Micro.Core/Result/Impl/SimpleResult.cs b/src/Caliburn.Micro.Core/Result/Impl/SimpleResult.cs index e26cf721f..7f942738b 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/SimpleResult.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/SimpleResult.cs @@ -19,24 +19,34 @@ private SimpleResult(bool wasCancelled, Exception error) /// /// A result that is always succeeded. /// - public static IResult Succeeded() => new SimpleResult(false, null); + public static IResult Succeeded() + => new SimpleResult(false, null); /// /// A result that is always canceled. /// /// The result. - public static IResult Cancelled() => new SimpleResult(true, null); + public static IResult Cancelled() + => new SimpleResult(true, null); /// /// A result that is always failed. /// - public static IResult Failed(Exception error) => new SimpleResult(false, error); + public static IResult Failed(Exception error) + => new SimpleResult(false, error); /// /// Executes the result using the specified context. /// /// The context. - public void Execute(CoroutineExecutionContext context) => Completed(this, new ResultCompletionEventArgs { WasCancelled = _wasCancelled, Error = _error }); + public void Execute(CoroutineExecutionContext context) + => Completed( + this, + new ResultCompletionEventArgs + { + WasCancelled = _wasCancelled, + Error = _error, + }); /// /// Occurs when execution has completed. diff --git a/src/Caliburn.Micro.Core/Result/Impl/TaskResult.cs b/src/Caliburn.Micro.Core/Result/Impl/TaskResult.cs index 66df04578..38dba01ef 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/TaskResult.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/TaskResult.cs @@ -14,7 +14,8 @@ public class TaskResult : IResult /// Initializes a new instance of the class. /// /// The task. - public TaskResult(Task task) => _innerTask = task; + public TaskResult(Task task) + => _innerTask = task; /// /// Executes the result using the specified context. @@ -39,7 +40,14 @@ public void Execute(CoroutineExecutionContext context) /// Called when the asynchronous task has completed. /// /// The completed task. - protected virtual void OnCompleted(Task task) => Completed(this, new ResultCompletionEventArgs { WasCancelled = task.IsCanceled, Error = task.Exception }); + protected virtual void OnCompleted(Task task) + => Completed( + this, + new ResultCompletionEventArgs + { + WasCancelled = task.IsCanceled, + Error = task.Exception, + }); /// /// Occurs when execution has completed. diff --git a/src/Caliburn.Micro.Core/Screen/EventHandlers/AsyncEventHandler.cs b/src/Caliburn.Micro.Core/Screen/EventHandlers/AsyncEventHandler.cs index f92776d5e..de17ff44c 100644 --- a/src/Caliburn.Micro.Core/Screen/EventHandlers/AsyncEventHandler.cs +++ b/src/Caliburn.Micro.Core/Screen/EventHandlers/AsyncEventHandler.cs @@ -3,8 +3,6 @@ namespace Caliburn.Micro { - public delegate Task AsyncEventHandler( - object sender, - TEventArgs e) + public delegate Task AsyncEventHandler(object sender, TEventArgs e) where TEventArgs : EventArgs; } diff --git a/src/Caliburn.Micro.Core/Screen/Extensions/ActivateExtensions.cs b/src/Caliburn.Micro.Core/Screen/Extensions/ActivateExtensions.cs index 5f5641f11..f56af8e8d 100644 --- a/src/Caliburn.Micro.Core/Screen/Extensions/ActivateExtensions.cs +++ b/src/Caliburn.Micro.Core/Screen/Extensions/ActivateExtensions.cs @@ -12,6 +12,7 @@ public static class ActivateExtensions /// /// The instance to activate /// A task that represents the asynchronous operation. - public static Task ActivateAsync(this IActivate activate) => activate.ActivateAsync(default); + public static Task ActivateAsync(this IActivate activate) + => activate.ActivateAsync(default); } } diff --git a/src/Caliburn.Micro.Core/Screen/Extensions/AsyncEventHandlerExtensions.cs b/src/Caliburn.Micro.Core/Screen/Extensions/AsyncEventHandlerExtensions.cs index c4b2ecaa9..f84402d86 100644 --- a/src/Caliburn.Micro.Core/Screen/Extensions/AsyncEventHandlerExtensions.cs +++ b/src/Caliburn.Micro.Core/Screen/Extensions/AsyncEventHandlerExtensions.cs @@ -7,15 +7,11 @@ namespace Caliburn.Micro { public static class AsyncEventHandlerExtensions { - public static IEnumerable> GetHandlers( - this AsyncEventHandler handler) + public static IEnumerable> GetHandlers(this AsyncEventHandler handler) where TEventArgs : EventArgs => handler.GetInvocationList().Cast>(); - public static Task InvokeAllAsync( - this AsyncEventHandler handler, - object sender, - TEventArgs e) + public static Task InvokeAllAsync(this AsyncEventHandler handler, object sender, TEventArgs e) where TEventArgs : EventArgs => Task.WhenAll( handler.GetHandlers() diff --git a/src/Caliburn.Micro.Core/Screen/Extensions/DeactivateExtensions.cs b/src/Caliburn.Micro.Core/Screen/Extensions/DeactivateExtensions.cs index 54ee73c3e..acf51002c 100644 --- a/src/Caliburn.Micro.Core/Screen/Extensions/DeactivateExtensions.cs +++ b/src/Caliburn.Micro.Core/Screen/Extensions/DeactivateExtensions.cs @@ -13,6 +13,7 @@ public static class DeactivateExtensions /// The instance to deactivate /// Indicates whether or not this instance is being closed. /// A task that represents the asynchronous operation. - public static Task DeactivateAsync(this IDeactivate deactivate, bool close) => deactivate.DeactivateAsync(close, default); + public static Task DeactivateAsync(this IDeactivate deactivate, bool close) + => deactivate.DeactivateAsync(close, default); } } diff --git a/src/Caliburn.Micro.Core/Screen/Extensions/ScreenExtensions.cs b/src/Caliburn.Micro.Core/Screen/Extensions/ScreenExtensions.cs index 39bf464f7..648c8b121 100644 --- a/src/Caliburn.Micro.Core/Screen/Extensions/ScreenExtensions.cs +++ b/src/Caliburn.Micro.Core/Screen/Extensions/ScreenExtensions.cs @@ -13,7 +13,8 @@ public static class ScreenExtensions /// Activates the item if it implements , otherwise does nothing. /// /// The potential activatable. - public static Task TryActivateAsync(object potentialActivatable) => potentialActivatable is IActivate activator ? activator.ActivateAsync(CancellationToken.None) : Task.FromResult(true); + public static Task TryActivateAsync(object potentialActivatable) + => potentialActivatable is IActivate activator ? activator.ActivateAsync(CancellationToken.None) : Task.FromResult(true); /// /// Activates the item if it implements , otherwise does nothing. @@ -21,7 +22,8 @@ public static class ScreenExtensions /// The potential activatable. /// The cancellation token to cancel operation. /// A task that represents the asynchronous operation. - public static Task TryActivateAsync(object potentialActivatable, CancellationToken cancellationToken) => potentialActivatable is IActivate activator ? activator.ActivateAsync(cancellationToken) : Task.FromResult(true); + public static Task TryActivateAsync(object potentialActivatable, CancellationToken cancellationToken) + => potentialActivatable is IActivate activator ? activator.ActivateAsync(cancellationToken) : Task.FromResult(true); /// /// Deactivates the item if it implements , otherwise does nothing. @@ -29,7 +31,8 @@ public static class ScreenExtensions /// The potential deactivatable. /// Indicates whether or not to close the item after deactivating it. /// A task that represents the asynchronous operation. - public static Task TryDeactivateAsync(object potentialDeactivatable, bool close) => potentialDeactivatable is IDeactivate deactivator ? deactivator.DeactivateAsync(close, CancellationToken.None) : Task.FromResult(true); + public static Task TryDeactivateAsync(object potentialDeactivatable, bool close) + => potentialDeactivatable is IDeactivate deactivator ? deactivator.DeactivateAsync(close, CancellationToken.None) : Task.FromResult(true); /// /// Deactivates the item if it implements , otherwise does nothing. @@ -38,7 +41,8 @@ public static class ScreenExtensions /// Indicates whether or not to close the item after deactivating it. /// The cancellation token to cancel operation. /// A task that represents the asynchronous operation. - public static Task TryDeactivateAsync(object potentialDeactivatable, bool close, CancellationToken cancellationToken) => potentialDeactivatable is IDeactivate deactivator ? deactivator.DeactivateAsync(close, cancellationToken) : Task.FromResult(true); + public static Task TryDeactivateAsync(object potentialDeactivatable, bool close, CancellationToken cancellationToken) + => potentialDeactivatable is IDeactivate deactivator ? deactivator.DeactivateAsync(close, cancellationToken) : Task.FromResult(true); /// /// Closes the specified item. @@ -46,7 +50,8 @@ public static class ScreenExtensions /// The conductor. /// The item to close. /// A task that represents the asynchronous operation. - public static Task CloseItemAsync(this IConductor conductor, object item) => conductor.DeactivateItemAsync(item, true, CancellationToken.None); + public static Task CloseItemAsync(this IConductor conductor, object item) + => conductor.DeactivateItemAsync(item, true, CancellationToken.None); /// /// Closes the specified item. @@ -55,7 +60,8 @@ public static class ScreenExtensions /// The item to close. /// The cancellation token to cancel operation. /// A task that represents the asynchronous operation. - public static Task CloseItemAsync(this IConductor conductor, object item, CancellationToken cancellationToken) => conductor.DeactivateItemAsync(item, true, cancellationToken); + public static Task CloseItemAsync(this IConductor conductor, object item, CancellationToken cancellationToken) + => conductor.DeactivateItemAsync(item, true, cancellationToken); /// /// Closes the specified item. @@ -63,7 +69,9 @@ public static class ScreenExtensions /// The conductor. /// The item to close. /// A task that represents the asynchronous operation. - public static Task CloseItemAsync(this ConductorBase conductor, T item) where T : class => conductor.DeactivateItemAsync(item, true, CancellationToken.None); + public static Task CloseItemAsync(this ConductorBase conductor, T item) + where T : class + => conductor.DeactivateItemAsync(item, true, CancellationToken.None); /// /// Closes the specified item. @@ -72,7 +80,9 @@ public static class ScreenExtensions /// The item to close. /// The cancellation token to cancel operation. /// A task that represents the asynchronous operation. - public static Task CloseItemAsync(this ConductorBase conductor, T item, CancellationToken cancellationToken) where T : class => conductor.DeactivateItemAsync(item, true, cancellationToken); + public static Task CloseItemAsync(this ConductorBase conductor, T item, CancellationToken cancellationToken) + where T : class + => conductor.DeactivateItemAsync(item, true, cancellationToken); /// /// Activates a child whenever the specified parent is activated. diff --git a/src/Caliburn.Micro.Core/Screen/Screen.cs b/src/Caliburn.Micro.Core/Screen/Screen.cs index 583da8cf1..ad1d811fb 100644 --- a/src/Caliburn.Micro.Core/Screen/Screen.cs +++ b/src/Caliburn.Micro.Core/Screen/Screen.cs @@ -19,7 +19,8 @@ public class Screen : ViewAware, IScreen, IChild /// /// Creates an instance of the screen. /// - public Screen() => _displayName = GetType().FullName; + public Screen() + => _displayName = GetType().FullName; /// /// Indicates whether or not this instance is currently initialized. @@ -145,7 +146,8 @@ async Task IDeactivate.DeactivateAsync(bool close, CancellationToken cancellatio /// /// The cancellation token to cancel operation. /// A task that represents the asynchronous operation and holds the value of the close check.. - public virtual Task CanCloseAsync(CancellationToken cancellationToken = default) => Task.FromResult(true); + public virtual Task CanCloseAsync(CancellationToken cancellationToken = default) + => Task.FromResult(true); /// /// Tries to close this instance by asking its Parent to initiate shutdown or by asking its corresponding view to close. @@ -167,18 +169,21 @@ public virtual async Task TryCloseAsync(bool? dialogResult = null) /// /// Called when initializing. /// - protected virtual Task OnInitializeAsync(CancellationToken cancellationToken) => Task.FromResult(true); + protected virtual Task OnInitializeAsync(CancellationToken cancellationToken) + => Task.FromResult(true); /// /// Called when activating. /// - protected virtual Task OnActivateAsync(CancellationToken cancellationToken) => Task.FromResult(true); + protected virtual Task OnActivateAsync(CancellationToken cancellationToken) + => Task.FromResult(true); /// /// Called when view has been activated. /// - protected virtual Task OnActivatedAsync(CancellationToken cancellationToken) => Task.FromResult(true); + protected virtual Task OnActivatedAsync(CancellationToken cancellationToken) + => Task.FromResult(true); /// /// Called when deactivating. @@ -186,6 +191,7 @@ public virtual async Task TryCloseAsync(bool? dialogResult = null) /// Indicates whether this instance will be closed. /// The cancellation token to cancel operation. /// A task that represents the asynchronous operation. - protected virtual Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) => Task.FromResult(true); + protected virtual Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) + => Task.FromResult(true); } } diff --git a/src/Caliburn.Micro.Core/Types/BindableCollection.cs b/src/Caliburn.Micro.Core/Types/BindableCollection.cs index 9f4b5aba7..7a6d3dc85 100644 --- a/src/Caliburn.Micro.Core/Types/BindableCollection.cs +++ b/src/Caliburn.Micro.Core/Types/BindableCollection.cs @@ -15,14 +15,16 @@ public class BindableCollection : ObservableCollection, IObservableCollect /// /// Initializes a new instance of the class. /// - public BindableCollection() => IsNotifying = true; + public BindableCollection() + => IsNotifying = true; /// /// Initializes a new instance of the class. /// /// The collection from which the elements are copied. public BindableCollection(IEnumerable collection) - : base(collection) => IsNotifying = true; + : base(collection) + => IsNotifying = true; /// /// Enables/Disables property change notification. @@ -95,7 +97,8 @@ protected override sealed void InsertItem(int index, T item) /// /// Used to avoid compiler warning regarding unverifiable code. /// - protected virtual void InsertItemBase(int index, T item) => base.InsertItem(index, item); + protected virtual void InsertItemBase(int index, T item) + => base.InsertItem(index, item); /// /// Sets the item at the specified position. @@ -122,7 +125,8 @@ protected override sealed void SetItem(int index, T item) /// /// Used to avoid compiler warning regarding unverifiable code. /// - protected virtual void SetItemBase(int index, T item) => base.SetItem(index, item); + protected virtual void SetItemBase(int index, T item) + => base.SetItem(index, item); /// /// Removes the item at the specified position. @@ -147,12 +151,14 @@ protected override sealed void RemoveItem(int index) /// /// Used to avoid compiler warning regarding unverifiable code. /// - protected virtual void RemoveItemBase(int index) => base.RemoveItem(index); + protected virtual void RemoveItemBase(int index) + => base.RemoveItem(index); /// /// Clears the items contained by the collection. /// - protected override sealed void ClearItems() => OnUIThread(ClearItemsBase); + protected override sealed void ClearItems() + => OnUIThread(ClearItemsBase); /// /// Exposes the base implementation of the function. @@ -160,7 +166,8 @@ protected override sealed void RemoveItem(int index) /// /// Used to avoid compiler warning regarding unverifiable code. /// - protected virtual void ClearItemsBase() => base.ClearItems(); + protected virtual void ClearItemsBase() + => base.ClearItems(); /// /// Raises the event with the provided arguments. @@ -259,6 +266,7 @@ void RemoveRange() /// /// An extension point for subclasses to customise how property change notifications are handled. /// - protected virtual void OnUIThread(System.Action action) => action.OnUIThread(); + protected virtual void OnUIThread(System.Action action) + => action.OnUIThread(); } } diff --git a/src/Caliburn.Micro.Core/Types/PropertyChangedBase.cs b/src/Caliburn.Micro.Core/Types/PropertyChangedBase.cs index a32ed86eb..cd266502d 100644 --- a/src/Caliburn.Micro.Core/Types/PropertyChangedBase.cs +++ b/src/Caliburn.Micro.Core/Types/PropertyChangedBase.cs @@ -15,7 +15,8 @@ public class PropertyChangedBase : INotifyPropertyChangedEx /// /// Creates an instance of . /// - public PropertyChangedBase() => IsNotifying = true; + public PropertyChangedBase() + => IsNotifying = true; /// /// Occurs when a property value changes. @@ -31,7 +32,8 @@ public class PropertyChangedBase : INotifyPropertyChangedEx /// /// Raises a change notification indicating that all bindings should be refreshed. /// - public virtual void Refresh() => NotifyOfPropertyChange(string.Empty); + public virtual void Refresh() + => NotifyOfPropertyChange(string.Empty); /// /// Notifies subscribers of the property change. @@ -57,21 +59,24 @@ public virtual void NotifyOfPropertyChange([System.Runtime.CompilerServices.Call /// /// The type of the property. /// The property expression. - public void NotifyOfPropertyChange(Expression> property) => NotifyOfPropertyChange(property.GetMemberInfo().Name); + public void NotifyOfPropertyChange(Expression> property) + => NotifyOfPropertyChange(property.GetMemberInfo().Name); /// /// Raises the event directly. /// /// The instance containing the event data. [EditorBrowsable(EditorBrowsableState.Never)] - protected void OnPropertyChanged(PropertyChangedEventArgs e) => PropertyChanged?.Invoke(this, e); + protected void OnPropertyChanged(PropertyChangedEventArgs e) + => PropertyChanged?.Invoke(this, e); /// /// Executes the given action on the UI thread /// /// An extension point for subclasses to customise how property change notifications are handled. /// - protected virtual void OnUIThread(System.Action action) => action.OnUIThread(); + protected virtual void OnUIThread(System.Action action) + => action.OnUIThread(); /// /// Sets a backing field value and if it's changed raise a notification. diff --git a/src/Caliburn.Micro.Core/Types/WeakValueDictionary.cs b/src/Caliburn.Micro.Core/Types/WeakValueDictionary.cs index 18887e391..32be86f2d 100644 --- a/src/Caliburn.Micro.Core/Types/WeakValueDictionary.cs +++ b/src/Caliburn.Micro.Core/Types/WeakValueDictionary.cs @@ -16,13 +16,12 @@ internal class WeakValueDictionary : IDictionary private readonly Dictionary _inner; private readonly WeakReference _gcSentinel = new(new object()); - #region Cleanup handling - private bool IsCleanupNeeded() { if (_gcSentinel.Target == null) { _gcSentinel.Target = new object(); + return true; } @@ -46,14 +45,11 @@ private void CleanIfNeeded() } } - #endregion - - #region Constructors - /// /// Initializes a new instance of the class that is empty, has the default initial capacity, and uses the default equality comparer for the key type. /// - public WeakValueDictionary() => _inner = new Dictionary(); + public WeakValueDictionary() + => _inner = new Dictionary(); /// /// Initializes a new instance of the class that contains elements copied from the specified and uses the default equality comparer for the key type. @@ -80,22 +76,23 @@ public WeakValueDictionary(IDictionary dictionary, IEqualityCompar /// Initializes a new instance of the class that is empty, has the default initial capacity, and uses the specified . /// /// The implementation to use when comparing keys, or null to use the default for the type of the key. - public WeakValueDictionary(IEqualityComparer comparer) => _inner = new Dictionary(comparer); + public WeakValueDictionary(IEqualityComparer comparer) + => _inner = new Dictionary(comparer); /// /// Initializes a new instance of the class that is empty, has the specified initial capacity, and uses the default equality comparer for the key type. /// /// The initial number of elements that the can contain. - public WeakValueDictionary(int capacity) => _inner = new Dictionary(capacity); + public WeakValueDictionary(int capacity) + => _inner = new Dictionary(capacity); /// /// Initializes a new instance of the class that is empty, has the specified initial capacity, and uses the specified . /// /// The initial number of elements that the can contain. /// The implementation to use when comparing keys, or null to use the default for the type of the key. - public WeakValueDictionary(int capacity, IEqualityComparer comparer) => _inner = new Dictionary(capacity, comparer); - - #endregion + public WeakValueDictionary(int capacity, IEqualityComparer comparer) + => _inner = new Dictionary(capacity, comparer); /// /// Returns an enumerator that iterates through the . @@ -104,19 +101,24 @@ public WeakValueDictionary(IDictionary dictionary, IEqualityCompar public IEnumerator> GetEnumerator() { CleanIfNeeded(); - IEnumerable> enumerable = _inner.Select(pair => new KeyValuePair(pair.Key, (TValue)pair.Value.Target)) - .Where(pair => pair.Value != null); + IEnumerable> enumerable + = _inner + .Select(pair => new KeyValuePair(pair.Key, (TValue)pair.Value.Target)) + .Where(pair => pair.Value != null); return enumerable.GetEnumerator(); } - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); - void ICollection>.Add(KeyValuePair item) => Add(item.Key, item.Value); + void ICollection>.Add(KeyValuePair item) + => Add(item.Key, item.Value); /// /// Removes all keys and values from the . /// - public void Clear() => _inner.Clear(); + public void Clear() + => _inner.Clear(); bool ICollection>.Contains(KeyValuePair item) { @@ -142,8 +144,7 @@ void ICollection>.CopyTo(KeyValuePair[] if ((arrayIndex + Count) > array.Length) { - throw new ArgumentException( - "The number of elements in the source collection is greater than the available space from arrayIndex to the end of the destination array."); + throw new ArgumentException("The number of elements in the source collection is greater than the available space from arrayIndex to the end of the destination array."); } this.ToArray().CopyTo(array, arrayIndex); @@ -177,11 +178,13 @@ public int Count get { CleanIfNeeded(); + return _inner.Count; } } - bool ICollection>.IsReadOnly => false; + bool ICollection>.IsReadOnly + => false; /// /// Adds the specified key and value to the dictionary. @@ -199,7 +202,8 @@ public void Add(TKey key, TValue value) /// /// The key to locate in the . /// - public bool ContainsKey(TKey key) => TryGetValue(key, out _); + public bool ContainsKey(TKey key) + => TryGetValue(key, out _); /// /// Removes the value with the specified key from the . @@ -209,6 +213,7 @@ public void Add(TKey key, TValue value) public bool Remove(TKey key) { CleanIfNeeded(); + return _inner.Remove(key); } @@ -228,6 +233,7 @@ public bool TryGetValue(TKey key, out TValue value) if (!_inner.TryGetValue(key, out WeakReference wr)) { value = null; + return false; } @@ -236,10 +242,12 @@ public bool TryGetValue(TKey key, out TValue value) { _inner.Remove(key); value = null; + return false; } value = result; + return true; } @@ -272,30 +280,36 @@ public TValue this[TKey key] /// /// Gets a collection containing the keys in the . /// - public ICollection Keys => _inner.Keys; + public ICollection Keys + => _inner.Keys; /// /// Gets a collection containing the values in the . /// - public ICollection Values => new ValueCollection(this); - - #region Inner Types + public ICollection Values + => new ValueCollection(this); private sealed class ValueCollection : ICollection { private readonly WeakValueDictionary _inner; - public ValueCollection(WeakValueDictionary dictionary) => _inner = dictionary; + public ValueCollection(WeakValueDictionary dictionary) + => _inner = dictionary; - public IEnumerator GetEnumerator() => _inner.Select(pair => pair.Value).GetEnumerator(); + public IEnumerator GetEnumerator() + => _inner.Select(pair => pair.Value).GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); - void ICollection.Add(TValue item) => throw new NotSupportedException(); + void ICollection.Add(TValue item) + => throw new NotSupportedException(); - void ICollection.Clear() => throw new NotSupportedException(); + void ICollection.Clear() + => throw new NotSupportedException(); - bool ICollection.Contains(TValue item) => _inner.Any(pair => pair.Value == item); + bool ICollection.Contains(TValue item) + => _inner.Any(pair => pair.Value == item); public void CopyTo(TValue[] array, int arrayIndex) { @@ -318,13 +332,14 @@ public void CopyTo(TValue[] array, int arrayIndex) this.ToArray().CopyTo(array, arrayIndex); } - bool ICollection.Remove(TValue item) => throw new NotSupportedException(); + bool ICollection.Remove(TValue item) + => throw new NotSupportedException(); - public int Count => _inner.Count; + public int Count + => _inner.Count; - bool ICollection.IsReadOnly => true; + bool ICollection.IsReadOnly + => true; } - - #endregion } } diff --git a/src/Caliburn.Micro.Core/ViewAware/ViewAware.cs b/src/Caliburn.Micro.Core/ViewAware/ViewAware.cs index 02aa6036c..b53601378 100644 --- a/src/Caliburn.Micro.Core/ViewAware/ViewAware.cs +++ b/src/Caliburn.Micro.Core/ViewAware/ViewAware.cs @@ -14,22 +14,26 @@ public class ViewAware : PropertyChangedBase, IViewAware /// /// The default view context. /// - public static readonly object DefaultContext = new(); + public static readonly object DefaultContext + = new(); /// /// The view chache for this instance. /// - protected IDictionary Views => _views; + protected IDictionary Views + => _views; /// /// Creates an instance of . /// - public ViewAware() => _views = new WeakValueDictionary(); + public ViewAware() + => _views = new WeakValueDictionary(); /// /// Raised when a view is attached. /// - public event EventHandler ViewAttached = delegate { }; + public event EventHandler ViewAttached + = delegate { }; void IViewAware.AttachView(object view, object context) { @@ -101,6 +105,7 @@ protected virtual void OnViewReady(object view) public virtual object GetView(object context = null) { Views.TryGetValue(context ?? DefaultContext, out object view); + return view; } } From 35fbaac28ab044b545b7b99966d56aae24765298 Mon Sep 17 00:00:00 2001 From: khaled Date: Sat, 7 Oct 2023 05:09:38 +0200 Subject: [PATCH 05/14] - Applied 'Return Early Pattern' as much as possible. - Applied 'Fail Fast Principle' as much as possible. - Minor formatting. The Benefit is the code less nested, The 'Happy path' can hold more code without unnecessary nested complex method, because the 'Return Early Pattern' and 'Fail Fast Principle' paths has deterministic result for known conditions. --- .../Conductor/Conductor.cs | 35 ++--- .../ConductorWithCollectionAllActive.cs | 37 +++--- .../ConductorWithCollectionOneActive.cs | 120 ++++++++++-------- .../DefaultImpl/DefaultCloseStrategy.cs | 22 ++-- .../Coroutine/ExtensionPoints/Coroutine.cs | 30 +++-- .../EventAggregator/Contracts/IHandle.cs | 1 - .../EventAggregator/EventAggregator.cs | 17 ++- .../Extensions/EventAggregatorExtensions.cs | 2 - .../Extensions/ExpressionExtensions.cs | 14 +- .../IoC/Extensions/ContainerExtensions.cs | 32 +++-- .../IoC/SimpleContainer.cs | 68 +++++----- .../Result/Extensions/ResultExtensions.cs | 21 +-- .../Result/Impl/ContinueResultDecorator.cs | 18 ++- .../Result/Impl/DelegateResult.cs | 4 +- .../Result/Impl/DelegateResult{TResult}.cs | 3 +- .../Impl/OverrideCancelResultDecorator.cs | 5 +- .../Result/Impl/RescueResultDecorator.cs | 15 ++- .../Result/Impl/ResultDecoratorBase.cs | 3 +- .../Result/Impl/SequentialResult.cs | 46 ++++--- .../Result/Impl/SimpleResult.cs | 3 +- .../Result/Impl/TaskResult.cs | 17 +-- .../Result/Impl/TaskResult{TResult}.cs | 8 +- src/Caliburn.Micro.Core/Screen/Screen.cs | 72 ++++++----- .../Types/BindableCollection.cs | 116 +++++++++-------- .../Types/PropertyChangedBase.cs | 30 +++-- .../Types/WeakValueDictionary.cs | 41 +++--- .../ViewAware/ViewAware.cs | 27 ++-- 27 files changed, 445 insertions(+), 362 deletions(-) diff --git a/src/Caliburn.Micro.Core/Conductor/Conductor.cs b/src/Caliburn.Micro.Core/Conductor/Conductor.cs index 9324fc566..27dee3172 100644 --- a/src/Caliburn.Micro.Core/Conductor/Conductor.cs +++ b/src/Caliburn.Micro.Core/Conductor/Conductor.cs @@ -14,24 +14,26 @@ public override async Task ActivateItemAsync(T item, CancellationToken cancellat { if (item != null && item.Equals(ActiveItem)) { - if (IsActive) + if (!IsActive) { - await ScreenExtensions.TryActivateAsync(item, cancellationToken); - OnActivationProcessed(item, true); + return; } + + await ScreenExtensions.TryActivateAsync(item, cancellationToken); + OnActivationProcessed(item, true); + return; } ICloseResult closeResult = await CloseStrategy.ExecuteAsync(new[] { ActiveItem }, cancellationToken); - - if (closeResult.CloseCanOccur) - { - await ChangeActiveItemAsync(item, true, cancellationToken); - } - else + if (!closeResult.CloseCanOccur) { OnActivationProcessed(item, false); + + return; } + + await ChangeActiveItemAsync(item, true, cancellationToken); } /// @@ -49,11 +51,12 @@ public override async Task DeactivateItemAsync(T item, bool close, CancellationT } ICloseResult closeResult = await CloseStrategy.ExecuteAsync(new[] { ActiveItem }, CancellationToken.None); - - if (closeResult.CloseCanOccur) + if (!closeResult.CloseCanOccur) { - await ChangeActiveItemAsync(default, close); + return; } + + await ChangeActiveItemAsync(default, close); } /// @@ -61,7 +64,7 @@ public override async Task DeactivateItemAsync(T item, bool close, CancellationT /// /// The cancellation token to cancel operation. /// A task that represents the asynchronous operation. - public override async Task CanCloseAsync(CancellationToken cancellationToken = default ) + public override async Task CanCloseAsync(CancellationToken cancellationToken = default) { ICloseResult closeResult = await CloseStrategy.ExecuteAsync(new[] { ActiveItem }, cancellationToken); @@ -72,7 +75,7 @@ public override async Task DeactivateItemAsync(T item, bool close, CancellationT /// Called when activating. /// /// A task that represents the asynchronous operation. - protected override Task OnActivateAsync(CancellationToken cancellationToken) + protected override Task OnActivateAsync(CancellationToken cancellationToken) => ScreenExtensions.TryActivateAsync(ActiveItem, cancellationToken); /// @@ -81,14 +84,14 @@ protected override Task OnActivateAsync(CancellationToken cancellationToken) /// Indicates whether this instance will be closed. /// The cancellation token to cancel operation. /// A task that represents the asynchronous operation. - protected override Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) + protected override Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) => ScreenExtensions.TryDeactivateAsync(ActiveItem, close, cancellationToken); /// /// Gets the children. /// /// The collection of children. - public override IEnumerable GetChildren() + public override IEnumerable GetChildren() => new[] { ActiveItem }; } } diff --git a/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionAllActive.cs b/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionAllActive.cs index 808ceeaf9..e15522177 100644 --- a/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionAllActive.cs +++ b/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionAllActive.cs @@ -59,13 +59,13 @@ public AllActive() /// /// Gets the items that are currently being conducted. /// - public IObservableCollection Items + public IObservableCollection Items => _items; /// /// Called when activating. /// - protected override Task OnActivateAsync(CancellationToken cancellationToken) + protected override Task OnActivateAsync(CancellationToken cancellationToken) => Task.WhenAll(_items.OfType().Select(x => x.ActivateAsync(cancellationToken))); /// @@ -94,16 +94,18 @@ public override async Task CanCloseAsync(CancellationToken cancellationTok { ICloseResult closeResult = await CloseStrategy.ExecuteAsync(_items.ToList(), cancellationToken); - if (!closeResult.CloseCanOccur && closeResult.Children.Any()) + if (closeResult.CloseCanOccur || !closeResult.Children.Any()) { - foreach (IDeactivate deactivate in closeResult.Children.OfType()) - { - await deactivate.DeactivateAsync(true, cancellationToken); - } + return closeResult.CloseCanOccur; + } - _items.RemoveRange(closeResult.Children); + foreach (IDeactivate deactivate in closeResult.Children.OfType()) + { + await deactivate.DeactivateAsync(true, cancellationToken); } + _items.RemoveRange(closeResult.Children); + return closeResult.CloseCanOccur; } @@ -151,22 +153,27 @@ public override async Task DeactivateItemAsync(T item, bool close, CancellationT if (item == null) return; - if (close) + if (!close) { - ICloseResult closeResult = await CloseStrategy.ExecuteAsync(new[] { item }, CancellationToken.None); + await ScreenExtensions.TryDeactivateAsync(item, false, cancellationToken); - if (closeResult.CloseCanOccur) - await CloseItemCoreAsync(item, cancellationToken); + return; } - else - await ScreenExtensions.TryDeactivateAsync(item, false, cancellationToken); + + ICloseResult closeResult = await CloseStrategy.ExecuteAsync(new[] { item }, CancellationToken.None); + if (!closeResult.CloseCanOccur) + { + return; + } + + await CloseItemCoreAsync(item, cancellationToken); } /// /// Gets the children. /// /// The collection of children. - public override IEnumerable GetChildren() + public override IEnumerable GetChildren() => _items; private async Task CloseItemCoreAsync(T item, CancellationToken cancellationToken = default) diff --git a/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionOneActive.cs b/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionOneActive.cs index 6a56753f2..b434a0f38 100644 --- a/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionOneActive.cs +++ b/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionOneActive.cs @@ -48,14 +48,14 @@ public OneActive() /// /// Gets the items that are currently being conducted. /// - public IObservableCollection Items + public IObservableCollection Items => _items; /// /// Gets the children. /// /// The collection of children. - public override IEnumerable GetChildren() + public override IEnumerable GetChildren() => _items; /// @@ -66,18 +66,20 @@ public override IEnumerable GetChildren() /// A task that represents the asynchronous operation. public override async Task ActivateItemAsync(T item, CancellationToken cancellationToken = default) { - if (item != null && item.Equals(ActiveItem)) + if (item == null || !item.Equals(ActiveItem)) { - if (IsActive) - { - await ScreenExtensions.TryActivateAsync(item, cancellationToken); - OnActivationProcessed(item, true); - } + await ChangeActiveItemAsync(item, false, cancellationToken); return; } - await ChangeActiveItemAsync(item, false, cancellationToken); + if (!IsActive) + { + return; + } + + await ScreenExtensions.TryActivateAsync(item, cancellationToken); + OnActivationProcessed(item, true); } /// @@ -90,16 +92,22 @@ public override async Task ActivateItemAsync(T item, CancellationToken cancellat public override async Task DeactivateItemAsync(T item, bool close, CancellationToken cancellationToken = default) { if (item == null) + { return; + } if (!close) - await ScreenExtensions.TryDeactivateAsync(item, false, cancellationToken); - else { - ICloseResult closeResult = await CloseStrategy.ExecuteAsync(new[] { item }, CancellationToken.None); + await ScreenExtensions.TryDeactivateAsync(item, false, cancellationToken); - if (closeResult.CloseCanOccur) - await CloseItemCoreAsync(item, cancellationToken); + return; + } + + ICloseResult closeResult = await CloseStrategy.ExecuteAsync(new[] { item }, CancellationToken.None); + + if (closeResult.CloseCanOccur) + { + await CloseItemCoreAsync(item, cancellationToken); } } @@ -148,39 +156,40 @@ protected virtual T DetermineNextItemToActivate(IList list, int lastIndex) public override async Task CanCloseAsync(CancellationToken cancellationToken = default) { ICloseResult closeResult = await CloseStrategy.ExecuteAsync(_items.ToList(), cancellationToken); - - if (!closeResult.CloseCanOccur && closeResult.Children.Any()) + if (closeResult.CloseCanOccur || !closeResult.Children.Any()) { - IEnumerable closable = closeResult.Children; + return closeResult.CloseCanOccur; + } - if (closable.Contains(ActiveItem)) - { - var list = _items.ToList(); - T next = ActiveItem; - do - { - T previous = next; - next = DetermineNextItemToActivate(list, list.IndexOf(previous)); - list.Remove(previous); - } while (closable.Contains(next)); + IEnumerable closable = closeResult.Children; - T previousActive = ActiveItem; - await ChangeActiveItemAsync(next, true); - _items.Remove(previousActive); + if (closable.Contains(ActiveItem)) + { + var list = _items.ToList(); + T next = ActiveItem; + do + { + T previous = next; + next = DetermineNextItemToActivate(list, list.IndexOf(previous)); + list.Remove(previous); + } while (closable.Contains(next)); - var stillToClose = closable.ToList(); - stillToClose.Remove(previousActive); - closable = stillToClose; - } + T previousActive = ActiveItem; + await ChangeActiveItemAsync(next, true); + _items.Remove(previousActive); - foreach (IDeactivate deactivate in closable.OfType()) - { - await deactivate.DeactivateAsync(true, cancellationToken); - } + var stillToClose = closable.ToList(); + stillToClose.Remove(previousActive); + closable = stillToClose; + } - _items.RemoveRange(closable); + foreach (IDeactivate deactivate in closable.OfType()) + { + await deactivate.DeactivateAsync(true, cancellationToken); } + _items.RemoveRange(closable); + return closeResult.CloseCanOccur; } @@ -189,7 +198,7 @@ public override async Task CanCloseAsync(CancellationToken cancellationTok /// /// The cancellation token to cancel operation. /// A task that represents the asynchronous operation. - protected override Task OnActivateAsync(CancellationToken cancellationToken) + protected override Task OnActivateAsync(CancellationToken cancellationToken) => ScreenExtensions.TryActivateAsync(ActiveItem, cancellationToken); /// @@ -200,19 +209,19 @@ protected override Task OnActivateAsync(CancellationToken cancellationToken) /// A task that represents the asynchronous operation. protected override async Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) { - if (close) + if (!close) { - foreach (IDeactivate deactivate in _items.OfType()) - { - await deactivate.DeactivateAsync(true, cancellationToken); - } + await ScreenExtensions.TryDeactivateAsync(ActiveItem, false, cancellationToken); - _items.Clear(); + return; } - else + + foreach (IDeactivate deactivate in _items.OfType()) { - await ScreenExtensions.TryDeactivateAsync(ActiveItem, false, cancellationToken); + await deactivate.DeactivateAsync(true, cancellationToken); } + + _items.Clear(); } /// @@ -225,17 +234,16 @@ protected override T EnsureItem(T newItem) if (newItem == null) { newItem = DetermineNextItemToActivate(_items, ActiveItem != null ? _items.IndexOf(ActiveItem) : 0); - } - else - { - var index = _items.IndexOf(newItem); - if (index == -1) - _items.Add(newItem); - else - newItem = _items[index]; + return base.EnsureItem(newItem); } + var index = _items.IndexOf(newItem); + if (index == -1) + _items.Add(newItem); + else + newItem = _items[index]; + return base.EnsureItem(newItem); } } diff --git a/src/Caliburn.Micro.Core/Conductor/DefaultImpl/DefaultCloseStrategy.cs b/src/Caliburn.Micro.Core/Conductor/DefaultImpl/DefaultCloseStrategy.cs index 6b738b46e..4d15e09f0 100644 --- a/src/Caliburn.Micro.Core/Conductor/DefaultImpl/DefaultCloseStrategy.cs +++ b/src/Caliburn.Micro.Core/Conductor/DefaultImpl/DefaultCloseStrategy.cs @@ -16,7 +16,7 @@ public class DefaultCloseStrategy : ICloseStrategy /// Creates an instance of the class. /// /// Indicates that even if all conducted items are not closable, those that are should be closed. The default is FALSE. - public DefaultCloseStrategy(bool closeConductedItemsWhenConductorCannotClose = false) + public DefaultCloseStrategy(bool closeConductedItemsWhenConductorCannotClose = false) => _closeConductedItemsWhenConductorCannotClose = closeConductedItemsWhenConductorCannotClose; /// @@ -24,24 +24,22 @@ public async Task> ExecuteAsync(IEnumerable toClose, Cancella { var closeable = new List(); var closeCanOccur = true; - - foreach(T child in toClose) + foreach (T child in toClose) { - if (child is IGuardClose guard) + if (child is not IGuardClose guard) { - var canClose = await guard.CanCloseAsync(cancellationToken); + closeable.Add(child); + continue; + } - if (canClose) - { - closeable.Add(child); - } - closeCanOccur = closeCanOccur && canClose; - } - else + var canClose = await guard.CanCloseAsync(cancellationToken); + if (canClose) { closeable.Add(child); } + + closeCanOccur = closeCanOccur && canClose; } if (!_closeConductedItemsWhenConductorCannotClose && !closeCanOccur) diff --git a/src/Caliburn.Micro.Core/Coroutine/ExtensionPoints/Coroutine.cs b/src/Caliburn.Micro.Core/Coroutine/ExtensionPoints/Coroutine.cs index 9adab9c9d..73fee5311 100644 --- a/src/Caliburn.Micro.Core/Coroutine/ExtensionPoints/Coroutine.cs +++ b/src/Caliburn.Micro.Core/Coroutine/ExtensionPoints/Coroutine.cs @@ -9,7 +9,7 @@ namespace Caliburn.Micro /// public static class Coroutine { - private static readonly ILog Log + private static readonly ILog Log = LogManager.GetLog(typeof(Coroutine)); /// @@ -63,22 +63,25 @@ public static Task ExecuteAsync( if (e.Error != null) { taskSource.SetException(e.Error); + + return; } - else if (e.WasCancelled) + + if (e.WasCancelled) { taskSource.SetCanceled(); + + return; } - else - { - taskSource.SetResult(null); - } + + taskSource.SetResult(null); }); return taskSource.Task; } private static void ExecuteOnCompleted( - IResult result, + IResult result, EventHandler handler) { void OnCompledted(object s, ResultCompletionEventArgs e) @@ -99,15 +102,18 @@ public static event EventHandler Completed if (e.Error != null) { Log.Error(e.Error); + + return; } - else if (e.WasCancelled) + + if (e.WasCancelled) { Log.Info("Coroutine execution cancelled."); + + return; } - else - { - Log.Info("Coroutine execution completed."); - } + + Log.Info("Coroutine execution completed."); }; } } diff --git a/src/Caliburn.Micro.Core/EventAggregator/Contracts/IHandle.cs b/src/Caliburn.Micro.Core/EventAggregator/Contracts/IHandle.cs index 5c3f32399..281705708 100644 --- a/src/Caliburn.Micro.Core/EventAggregator/Contracts/IHandle.cs +++ b/src/Caliburn.Micro.Core/EventAggregator/Contracts/IHandle.cs @@ -17,6 +17,5 @@ public interface IHandle /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// A task that represents the asynchronous coroutine. Task HandleAsync(TMessage message, CancellationToken cancellationToken); - } } diff --git a/src/Caliburn.Micro.Core/EventAggregator/EventAggregator.cs b/src/Caliburn.Micro.Core/EventAggregator/EventAggregator.cs index eb3e9f24c..00739fddd 100644 --- a/src/Caliburn.Micro.Core/EventAggregator/EventAggregator.cs +++ b/src/Caliburn.Micro.Core/EventAggregator/EventAggregator.cs @@ -56,7 +56,6 @@ public virtual void Unsubscribe(object subscriber) lock (_handlers) { Handler found = _handlers.FirstOrDefault(x => x.Matches(subscriber)); - if (found != null) { _handlers.Remove(found); @@ -118,18 +117,22 @@ public Handler(object handler, Func, Task> marshal) //var interfaces = handler.GetType().GetTypeInfo().ImplementedInterfaces // .Where(x => typeof(IHandle).GetTypeInfo().IsAssignableFrom(x.GetTypeInfo()) && x.GetTypeInfo().IsGenericType); - IEnumerable interfaces = handler.GetType().GetTypeInfo().ImplementedInterfaces - .Where(x => x.GetTypeInfo().IsGenericType && x.GetGenericTypeDefinition() == typeof(IHandle<>)); - + IEnumerable interfaces + = handler + .GetType() + .GetTypeInfo().ImplementedInterfaces + .Where(x => x.GetTypeInfo().IsGenericType && + x.GetGenericTypeDefinition() == typeof(IHandle<>)); foreach (Type @interface in interfaces) { Type type = @interface.GetTypeInfo().GenericTypeArguments[0]; MethodInfo method = @interface.GetRuntimeMethod("HandleAsync", new[] { type, typeof(CancellationToken) }); - - if (method != null) + if (method == null) { - _supportedHandlers[type] = method; + continue; } + + _supportedHandlers[type] = method; } } diff --git a/src/Caliburn.Micro.Core/EventAggregator/Extensions/EventAggregatorExtensions.cs b/src/Caliburn.Micro.Core/EventAggregator/Extensions/EventAggregatorExtensions.cs index 1fa836216..5d8b8df4d 100644 --- a/src/Caliburn.Micro.Core/EventAggregator/Extensions/EventAggregatorExtensions.cs +++ b/src/Caliburn.Micro.Core/EventAggregator/Extensions/EventAggregatorExtensions.cs @@ -49,7 +49,6 @@ public static void SubscribeOnUIThread(this IEventAggregator eventAggregator, ob f => { var taskCompletionSource = new TaskCompletionSource(); - Execute.BeginOnUIThread(async () => { try @@ -123,7 +122,6 @@ public static Task PublishOnUIThreadAsync(this IEventAggregator eventAggregator, f => { var taskCompletionSource = new TaskCompletionSource(); - Execute.BeginOnUIThread(async () => { try diff --git a/src/Caliburn.Micro.Core/Extensions/ExpressionExtensions.cs b/src/Caliburn.Micro.Core/Extensions/ExpressionExtensions.cs index 8ef0e5b95..08287430a 100644 --- a/src/Caliburn.Micro.Core/Extensions/ExpressionExtensions.cs +++ b/src/Caliburn.Micro.Core/Extensions/ExpressionExtensions.cs @@ -16,16 +16,10 @@ public static class ExpressionExtensions public static MemberInfo GetMemberInfo(this Expression expression) { var lambda = (LambdaExpression)expression; - - MemberExpression memberExpression; - if (lambda.Body is UnaryExpression unaryExpression) - { - memberExpression = (MemberExpression)unaryExpression.Operand; - } - else - { - memberExpression = (MemberExpression)lambda.Body; - } + MemberExpression memberExpression + = lambda.Body is UnaryExpression unaryExpression + ? (MemberExpression)unaryExpression.Operand + : (MemberExpression)lambda.Body; return memberExpression.Member; } diff --git a/src/Caliburn.Micro.Core/IoC/Extensions/ContainerExtensions.cs b/src/Caliburn.Micro.Core/IoC/Extensions/ContainerExtensions.cs index adb23a2de..8ba5b18c6 100644 --- a/src/Caliburn.Micro.Core/IoC/Extensions/ContainerExtensions.cs +++ b/src/Caliburn.Micro.Core/IoC/Extensions/ContainerExtensions.cs @@ -32,6 +32,7 @@ public static SimpleContainer Singleton(this SimpleCo where TImplementation : TService { container.RegisterSingleton(typeof(TService), key, typeof(TImplementation)); + return container; } @@ -57,6 +58,7 @@ public static SimpleContainer PerRequest(this SimpleC where TImplementation : TService { container.RegisterPerRequest(typeof(TService), key, typeof(TImplementation)); + return container; } @@ -70,6 +72,7 @@ public static SimpleContainer PerRequest(this SimpleC public static SimpleContainer Instance(this SimpleContainer container, TService instance) { container.RegisterInstance(typeof(TService), null, instance); + return container; } @@ -84,6 +87,7 @@ public static SimpleContainer Handler(this SimpleContainer container, Func handler) { container.RegisterHandler(typeof(TService), null, handler); + return container; } @@ -95,19 +99,20 @@ public static SimpleContainer Handler(this SimpleContainer container, /// The assembly. /// The type filter. /// The container. - public static SimpleContainer AllTypesOf(this SimpleContainer container, Assembly assembly, - Func filter = null) + public static SimpleContainer AllTypesOf( + this SimpleContainer container, + Assembly assembly, + Func filter = null) { filter ??= type => true; - Type serviceType = typeof(TService); - IEnumerable types = from type in assembly.DefinedTypes - where serviceType.GetTypeInfo().IsAssignableFrom(type) - && !type.IsAbstract - && !type.IsInterface - && filter(type.AsType()) - select type; - + IEnumerable types + = from type in assembly.DefinedTypes + where serviceType.GetTypeInfo().IsAssignableFrom(type) + && !type.IsAbstract + && !type.IsInterface + && filter(type.AsType()) + select type; foreach (TypeInfo type in types) { container.RegisterSingleton(typeof(TService), null, type.AsType()); @@ -124,7 +129,8 @@ where serviceType.GetTypeInfo().IsAssignableFrom(type) /// The key. /// The instance. public static TService GetInstance(this SimpleContainer container, string key = null) - => (TService)container.GetInstance(typeof(TService), key); + => (TService)container + .GetInstance(typeof(TService), key); /// /// Gets all instances of a particular type and the given key (default null). @@ -134,7 +140,9 @@ public static TService GetInstance(this SimpleContainer container, str /// The key shared by those instances /// The resolved instances. public static IEnumerable GetAllInstances(this SimpleContainer container, string key = null) - => container.GetAllInstances(typeof(TService), key).Cast(); + => container + .GetAllInstances(typeof(TService), key) + .Cast(); /// /// Determines if a handler for the service/key has previously been registered. diff --git a/src/Caliburn.Micro.Core/IoC/SimpleContainer.cs b/src/Caliburn.Micro.Core/IoC/SimpleContainer.cs index e4fe64a38..279beaed6 100644 --- a/src/Caliburn.Micro.Core/IoC/SimpleContainer.cs +++ b/src/Caliburn.Micro.Core/IoC/SimpleContainer.cs @@ -79,10 +79,12 @@ public void RegisterHandler(Type service, string key, Func @@ -97,12 +99,13 @@ public object GetInstance(Type service, string key) if (entry != null) { var instance = entry.Single()(this); - - if (EnablePropertyInjection && instance != null) + if (!EnablePropertyInjection || instance == null) { - BuildUp(instance); + return instance; } + BuildUp(instance); + return instance; } @@ -110,37 +113,38 @@ public object GetInstance(Type service, string key) { return null; } - TypeInfo serviceTypeInfo = service.GetTypeInfo(); + TypeInfo serviceTypeInfo = service.GetTypeInfo(); if (DelegateTypeInfo.IsAssignableFrom(serviceTypeInfo)) { Type typeToCreate = serviceTypeInfo.GenericTypeArguments[0]; Type factoryFactoryType = typeof(FactoryFactory<>).MakeGenericType(typeToCreate); var factoryFactoryHost = Activator.CreateInstance(factoryFactoryType); MethodInfo factoryFactoryMethod = factoryFactoryType.GetRuntimeMethod("Create", new Type[] { _simpleContainerType }); + return factoryFactoryMethod.Invoke(factoryFactoryHost, new object[] { this }); } - if (EnumerableTypeInfo.IsAssignableFrom(serviceTypeInfo) && serviceTypeInfo.IsGenericType) + if (!EnumerableTypeInfo.IsAssignableFrom(serviceTypeInfo) || !serviceTypeInfo.IsGenericType) { - Type listType = serviceTypeInfo.GenericTypeArguments[0]; - var instances = GetAllInstances(listType).ToList(); - var array = Array.CreateInstance(listType, instances.Count); + return null; + } - for (var i = 0; i < array.Length; i++) - { - if (EnablePropertyInjection) - { - BuildUp(instances[i]); - } + Type listType = serviceTypeInfo.GenericTypeArguments[0]; + var instances = GetAllInstances(listType).ToList(); + var array = Array.CreateInstance(listType, instances.Count); - array.SetValue(instances[i], i); + for (var i = 0; i < array.Length; i++) + { + if (EnablePropertyInjection) + { + BuildUp(instances[i]); } - return array; + array.SetValue(instances[i], i); } - return null; + return array; } /// @@ -194,11 +198,12 @@ public void BuildUp(object instance) foreach (PropertyInfo property in properties) { var value = GetInstance(property.PropertyType, null); - - if (value != null) + if (value == null) { - property.SetValue(instance, value, null); + continue; } + + property.SetValue(instance, value, null); } } @@ -212,11 +217,13 @@ public SimpleContainer CreateChildContainer() private ContainerEntry GetOrCreateEntry(Type service, string key) { ContainerEntry entry = GetEntry(service, key); - if (entry == null) + if (entry != null) { - entry = new ContainerEntry { Service = service, Key = key }; - _entries.Add(entry); + return entry; } + + entry = new ContainerEntry { Service = service, Key = key }; + _entries.Add(entry); return entry; } @@ -245,6 +252,7 @@ private ContainerEntry GetEntry(Type service, string key) protected object BuildInstance(Type type) { var args = DetermineConstructorArgs(type); + return ActivateInstance(type, args); } @@ -258,6 +266,7 @@ protected virtual object ActivateInstance(Type type, object[] args) { var instance = args.Length > 0 ? System.Activator.CreateInstance(type, args) : System.Activator.CreateInstance(type); Activated(instance); + return instance; } @@ -270,11 +279,12 @@ private object[] DetermineConstructorArgs(Type implementation) { var args = new List(); ConstructorInfo constructor = SelectEligibleConstructor(implementation); - - if (constructor != null) + if (constructor == null) { - args.AddRange(constructor.GetParameters().Select(info => GetInstance(info.ParameterType, null))); + return args.ToArray(); } + + args.AddRange(constructor.GetParameters().Select(info => GetInstance(info.ParameterType, null))); return args.ToArray(); } @@ -299,7 +309,7 @@ private class ContainerEntry : List> private class FactoryFactory { - public Func Create(SimpleContainer container) + public Func Create(SimpleContainer container) => () => (T)container.GetInstance(typeof(T), null); } } diff --git a/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs b/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs index 110775baf..59f000cb6 100644 --- a/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs +++ b/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs @@ -53,7 +53,7 @@ public static IResult Rescue(this IResult result, Func rescu /// The coroutine to execute. /// The context to execute the coroutine within. /// A task that represents the asynchronous coroutine. - public static Task ExecuteAsync(this IResult result, CoroutineExecutionContext context = null) + public static Task ExecuteAsync(this IResult result, CoroutineExecutionContext context = null) => InternalExecuteAsync(result, context); /// @@ -63,7 +63,7 @@ public static Task ExecuteAsync(this IResult result, CoroutineExecutionContext c /// The coroutine to execute. /// The context to execute the coroutine within. /// A task that represents the asynchronous coroutine. - public static Task ExecuteAsync(this IResult result, CoroutineExecutionContext context = null) + public static Task ExecuteAsync(this IResult result, CoroutineExecutionContext context = null) => InternalExecuteAsync(result, context); @@ -72,7 +72,7 @@ public static Task ExecuteAsync(this IResult result, /// /// The task. /// The coroutine that encapsulates the task. - public static TaskResult AsResult(this Task task) + public static TaskResult AsResult(this Task task) => new(task); /// @@ -81,7 +81,7 @@ public static TaskResult AsResult(this Task task) /// The type of the result. /// The task. /// The coroutine that encapsulates the task. - public static TaskResult AsResult(this Task task) + public static TaskResult AsResult(this Task task) => new(task); private static Task InternalExecuteAsync(IResult result, CoroutineExecutionContext context) @@ -95,15 +95,18 @@ void OnCompleted(object s, ResultCompletionEventArgs e) if (e.Error != null) { taskSource.SetException(e.Error); + + return; } - else if (e.WasCancelled) + + if (e.WasCancelled) { taskSource.SetCanceled(); + + return; } - else - { - taskSource.SetResult(result is IResult rr ? rr.Result : default); - } + + taskSource.SetResult(result is IResult rr ? rr.Result : default); } try diff --git a/src/Caliburn.Micro.Core/Result/Impl/ContinueResultDecorator.cs b/src/Caliburn.Micro.Core/Result/Impl/ContinueResultDecorator.cs index 758a996fe..50b93c9f4 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/ContinueResultDecorator.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/ContinueResultDecorator.cs @@ -16,7 +16,7 @@ public class ContinueResultDecorator : ResultDecoratorBase /// The result to decorate. /// The coroutine to execute when was canceled. public ContinueResultDecorator(IResult result, Func coroutine) - : base(result) + : base(result) => _coroutine = coroutine ?? throw new ArgumentNullException("coroutine"); /// @@ -30,12 +30,12 @@ protected override void OnInnerResultCompleted(CoroutineExecutionContext context if (args.Error != null || !args.WasCancelled) { OnCompleted(new ResultCompletionEventArgs { Error = args.Error }); + + return; } - else - { - Log.Info(string.Format("Executing coroutine because {0} was cancelled.", innerResult.GetType().Name)); - Continue(context); - } + + Log.Info(string.Format("Executing coroutine because {0} was cancelled.", innerResult.GetType().Name)); + Continue(context); } private void Continue(CoroutineExecutionContext context) @@ -66,7 +66,11 @@ private void Continue(CoroutineExecutionContext context) private void ContinueCompleted(object sender, ResultCompletionEventArgs args) { ((IResult)sender).Completed -= ContinueCompleted; - OnCompleted(new ResultCompletionEventArgs { Error = args.Error, WasCancelled = (args.Error == null) }); + OnCompleted(new ResultCompletionEventArgs + { + Error = args.Error, + WasCancelled = args.Error == null, + }); } } } diff --git a/src/Caliburn.Micro.Core/Result/Impl/DelegateResult.cs b/src/Caliburn.Micro.Core/Result/Impl/DelegateResult.cs index bcf360efe..6187a580e 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/DelegateResult.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/DelegateResult.cs @@ -23,7 +23,6 @@ public DelegateResult(Action action) public void Execute(CoroutineExecutionContext context) { var eventArgs = new ResultCompletionEventArgs(); - try { _toExecute(); @@ -39,6 +38,7 @@ public void Execute(CoroutineExecutionContext context) /// /// Occurs when execution has completed. /// - public event EventHandler Completed = delegate { }; + public event EventHandler Completed + = delegate { }; } } diff --git a/src/Caliburn.Micro.Core/Result/Impl/DelegateResult{TResult}.cs b/src/Caliburn.Micro.Core/Result/Impl/DelegateResult{TResult}.cs index 6c571185f..395605bbe 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/DelegateResult{TResult}.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/DelegateResult{TResult}.cs @@ -45,6 +45,7 @@ public void Execute(CoroutineExecutionContext context) /// /// Occurs when execution has completed. /// - public event EventHandler Completed = delegate { }; + public event EventHandler Completed + = delegate { }; } } diff --git a/src/Caliburn.Micro.Core/Result/Impl/OverrideCancelResultDecorator.cs b/src/Caliburn.Micro.Core/Result/Impl/OverrideCancelResultDecorator.cs index 6bee81535..3608dc09d 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/OverrideCancelResultDecorator.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/OverrideCancelResultDecorator.cs @@ -30,7 +30,10 @@ protected override void OnInnerResultCompleted(CoroutineExecutionContext context Log.Info(string.Format("Overriding WasCancelled from {0}.", innerResult.GetType().Name)); } - OnCompleted(new ResultCompletionEventArgs { Error = args.Error }); + OnCompleted(new ResultCompletionEventArgs + { + Error = args.Error, + }); } } } diff --git a/src/Caliburn.Micro.Core/Result/Impl/RescueResultDecorator.cs b/src/Caliburn.Micro.Core/Result/Impl/RescueResultDecorator.cs index 4b6d90407..45744ed01 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/RescueResultDecorator.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/RescueResultDecorator.cs @@ -35,13 +35,13 @@ protected override void OnInnerResultCompleted(CoroutineExecutionContext context if (args.Error is not TException error) { OnCompleted(args); + + return; } - else - { - Log.Error(error); - Log.Info(string.Format("Executing coroutine because {0} threw an exception.", innerResult.GetType().Name)); - Rescue(context, error); - } + + Log.Error(error); + Log.Info(string.Format("Executing coroutine because {0} threw an exception.", innerResult.GetType().Name)); + Rescue(context, error); } private void Rescue(CoroutineExecutionContext context, TException exception) @@ -75,7 +75,8 @@ private void RescueCompleted(object sender, ResultCompletionEventArgs args) OnCompleted(new ResultCompletionEventArgs { Error = args.Error, - WasCancelled = (args.Error == null && (args.WasCancelled || _cancelResult)) + WasCancelled = args.Error == null && + (args.WasCancelled || _cancelResult) }); } } diff --git a/src/Caliburn.Micro.Core/Result/Impl/ResultDecoratorBase.cs b/src/Caliburn.Micro.Core/Result/Impl/ResultDecoratorBase.cs index ce46f7aa4..89621fc5e 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/ResultDecoratorBase.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/ResultDecoratorBase.cs @@ -55,7 +55,8 @@ private void InnerResultCompleted(object sender, ResultCompletionEventArgs args) /// /// Occurs when execution has completed. /// - public event EventHandler Completed = delegate { }; + public event EventHandler Completed + = delegate { }; /// /// Raises the event. diff --git a/src/Caliburn.Micro.Core/Result/Impl/SequentialResult.cs b/src/Caliburn.Micro.Core/Result/Impl/SequentialResult.cs index a2ac6c1dd..d8386639e 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/SequentialResult.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/SequentialResult.cs @@ -15,13 +15,15 @@ public class SequentialResult : IResult /// Initializes a new instance of the class. /// /// The enumerator. - public SequentialResult(IEnumerator enumerator) + public SequentialResult(IEnumerator enumerator) => _enumerator = enumerator; /// /// Occurs when execution has completed. /// - public event EventHandler Completed = delegate { }; + public event EventHandler Completed + = delegate + { }; /// /// Executes the result using the specified context. @@ -43,6 +45,7 @@ private void ChildCompleted(object sender, ResultCompletionEventArgs args) if (args.Error != null || args.WasCancelled) { OnComplete(args.Error, args.WasCancelled); + return; } @@ -57,31 +60,38 @@ private void ChildCompleted(object sender, ResultCompletionEventArgs args) return; } - if (moveNextSucceeded) + if (!moveNextSucceeded) { - try - { - IResult next = _enumerator.Current; - IoC.BuildUp(next); - next.Completed += ChildCompleted; - next.Execute(_context); - } - catch (Exception ex) - { - OnComplete(ex, false); - return; - } + OnComplete(null, false); + + return; + } + + try + { + IResult next = _enumerator.Current; + IoC.BuildUp(next); + next.Completed += ChildCompleted; + next.Execute(_context); } - else + catch (Exception ex) { - OnComplete(null, false); + OnComplete(ex, false); + + return; } } private void OnComplete(Exception error, bool wasCancelled) { _enumerator.Dispose(); - Completed(this, new ResultCompletionEventArgs { Error = error, WasCancelled = wasCancelled }); + Completed( + this, + new ResultCompletionEventArgs + { + Error = error, + WasCancelled = wasCancelled, + }); } } } diff --git a/src/Caliburn.Micro.Core/Result/Impl/SimpleResult.cs b/src/Caliburn.Micro.Core/Result/Impl/SimpleResult.cs index 7f942738b..571b32840 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/SimpleResult.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/SimpleResult.cs @@ -51,6 +51,7 @@ public void Execute(CoroutineExecutionContext context) /// /// Occurs when execution has completed. /// - public event EventHandler Completed = delegate { }; + public event EventHandler Completed + = delegate { }; } } diff --git a/src/Caliburn.Micro.Core/Result/Impl/TaskResult.cs b/src/Caliburn.Micro.Core/Result/Impl/TaskResult.cs index 38dba01ef..9e9405cb4 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/TaskResult.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/TaskResult.cs @@ -26,14 +26,14 @@ public void Execute(CoroutineExecutionContext context) if (_innerTask.IsCompleted) { OnCompleted(_innerTask); + + return; } - else - { - _innerTask.ContinueWith(OnCompleted, - System.Threading.SynchronizationContext.Current != null - ? TaskScheduler.FromCurrentSynchronizationContext() - : TaskScheduler.Current); - } + + _innerTask.ContinueWith(OnCompleted, + System.Threading.SynchronizationContext.Current != null + ? TaskScheduler.FromCurrentSynchronizationContext() + : TaskScheduler.Current); } /// @@ -52,6 +52,7 @@ protected virtual void OnCompleted(Task task) /// /// Occurs when execution has completed. /// - public event EventHandler Completed = delegate { }; + public event EventHandler Completed + = delegate { }; } } diff --git a/src/Caliburn.Micro.Core/Result/Impl/TaskResult{TResult}.cs b/src/Caliburn.Micro.Core/Result/Impl/TaskResult{TResult}.cs index 9cd1ad175..910b8025c 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/TaskResult{TResult}.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/TaskResult{TResult}.cs @@ -29,11 +29,15 @@ public TaskResult(Task task) /// The completed task. protected override void OnCompleted(Task task) { - if (!task.IsFaulted && !task.IsCanceled) + if (task.IsFaulted || task.IsCanceled) { - Result = ((Task)task).Result; + base.OnCompleted(task); + + return; } + Result = ((Task)task).Result; + base.OnCompleted(task); } } diff --git a/src/Caliburn.Micro.Core/Screen/Screen.cs b/src/Caliburn.Micro.Core/Screen/Screen.cs index ad1d811fb..58ce608c6 100644 --- a/src/Caliburn.Micro.Core/Screen/Screen.cs +++ b/src/Caliburn.Micro.Core/Screen/Screen.cs @@ -19,7 +19,7 @@ public class Screen : ViewAware, IScreen, IChild /// /// Creates an instance of the screen. /// - public Screen() + public Screen() => _displayName = GetType().FullName; /// @@ -79,17 +79,27 @@ private set /// /// Raised after activation occurs. /// - public virtual event AsyncEventHandler Activated = delegate { return Task.FromResult(true); }; + public virtual event AsyncEventHandler Activated + = delegate + { + return Task.FromResult(true); + }; /// /// Raised before deactivation. /// - public virtual event EventHandler AttemptingDeactivation = delegate { }; + public virtual event EventHandler AttemptingDeactivation + = delegate + { }; /// /// Raised after deactivation. /// - public virtual event AsyncEventHandler Deactivated = delegate { return Task.FromResult(true); }; + public virtual event AsyncEventHandler Deactivated + = delegate + { + return Task.FromResult(true); + }; async Task IActivate.ActivateAsync(CancellationToken cancellationToken) { @@ -117,28 +127,32 @@ async Task IActivate.ActivateAsync(CancellationToken cancellationToken) async Task IDeactivate.DeactivateAsync(bool close, CancellationToken cancellationToken) { - if (IsActive || IsInitialized && close) + if (!IsActive && (!IsInitialized || !close)) { - AttemptingDeactivation?.Invoke(this, new DeactivationEventArgs - { - WasClosed = close - }); - - Log.Info("Deactivating {0}.", this); - await OnDeactivateAsync(close, cancellationToken); - IsActive = false; - - await (Deactivated?.InvokeAllAsync(this, new DeactivationEventArgs - { - WasClosed = close - }) ?? Task.FromResult(true)); - - if (close) - { - Views.Clear(); - Log.Info("Closed {0}.", this); - } + return; + } + + AttemptingDeactivation?.Invoke(this, new DeactivationEventArgs + { + WasClosed = close + }); + + Log.Info("Deactivating {0}.", this); + await OnDeactivateAsync(close, cancellationToken); + IsActive = false; + + await (Deactivated?.InvokeAllAsync(this, new DeactivationEventArgs + { + WasClosed = close + }) ?? Task.FromResult(true)); + + if (!close) + { + return; } + + Views.Clear(); + Log.Info("Closed {0}.", this); } /// @@ -146,7 +160,7 @@ async Task IDeactivate.DeactivateAsync(bool close, CancellationToken cancellatio /// /// The cancellation token to cancel operation. /// A task that represents the asynchronous operation and holds the value of the close check.. - public virtual Task CanCloseAsync(CancellationToken cancellationToken = default) + public virtual Task CanCloseAsync(CancellationToken cancellationToken = default) => Task.FromResult(true); /// @@ -169,20 +183,20 @@ public virtual async Task TryCloseAsync(bool? dialogResult = null) /// /// Called when initializing. /// - protected virtual Task OnInitializeAsync(CancellationToken cancellationToken) + protected virtual Task OnInitializeAsync(CancellationToken cancellationToken) => Task.FromResult(true); /// /// Called when activating. /// - protected virtual Task OnActivateAsync(CancellationToken cancellationToken) + protected virtual Task OnActivateAsync(CancellationToken cancellationToken) => Task.FromResult(true); /// /// Called when view has been activated. /// - protected virtual Task OnActivatedAsync(CancellationToken cancellationToken) + protected virtual Task OnActivatedAsync(CancellationToken cancellationToken) => Task.FromResult(true); /// @@ -191,7 +205,7 @@ protected virtual Task OnActivatedAsync(CancellationToken cancellationToken) /// Indicates whether this instance will be closed. /// The cancellation token to cancel operation. /// A task that represents the asynchronous operation. - protected virtual Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) + protected virtual Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) => Task.FromResult(true); } } diff --git a/src/Caliburn.Micro.Core/Types/BindableCollection.cs b/src/Caliburn.Micro.Core/Types/BindableCollection.cs index 7a6d3dc85..1fbe1495b 100644 --- a/src/Caliburn.Micro.Core/Types/BindableCollection.cs +++ b/src/Caliburn.Micro.Core/Types/BindableCollection.cs @@ -15,7 +15,7 @@ public class BindableCollection : ObservableCollection, IObservableCollect /// /// Initializes a new instance of the class. /// - public BindableCollection() + public BindableCollection() => IsNotifying = true; /// @@ -23,7 +23,7 @@ public BindableCollection() /// /// The collection from which the elements are copied. public BindableCollection(IEnumerable collection) - : base(collection) + : base(collection) => IsNotifying = true; /// @@ -37,17 +37,19 @@ public BindableCollection(IEnumerable collection) /// Name of the property. public virtual void NotifyOfPropertyChange(string propertyName) { - if (IsNotifying) + if (!IsNotifying) { - if (PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) - { - OnUIThread(() => OnPropertyChanged(new PropertyChangedEventArgs(propertyName))); - } - else - { - OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); - } + return; + } + + if (!PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) + { + OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); + + return; } + + OnUIThread(() => OnPropertyChanged(new PropertyChangedEventArgs(propertyName))); } /// @@ -55,21 +57,21 @@ public virtual void NotifyOfPropertyChange(string propertyName) /// public void Refresh() { - if (PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) + if (!PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) { - OnUIThread(() => - { - OnPropertyChanged(new PropertyChangedEventArgs("Count")); - OnPropertyChanged(new PropertyChangedEventArgs("Item[]")); - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); - }); + OnPropertyChanged(new PropertyChangedEventArgs("Count")); + OnPropertyChanged(new PropertyChangedEventArgs("Item[]")); + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); + + return; } - else + + OnUIThread(() => { OnPropertyChanged(new PropertyChangedEventArgs("Count")); OnPropertyChanged(new PropertyChangedEventArgs("Item[]")); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); - } + }); } /// @@ -79,14 +81,14 @@ public void Refresh() /// The item to be inserted. protected override sealed void InsertItem(int index, T item) { - if (PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) - { - OnUIThread(() => InsertItemBase(index, item)); - } - else + if (!PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) { InsertItemBase(index, item); + + return; } + + OnUIThread(() => InsertItemBase(index, item)); } /// @@ -97,7 +99,7 @@ protected override sealed void InsertItem(int index, T item) /// /// Used to avoid compiler warning regarding unverifiable code. /// - protected virtual void InsertItemBase(int index, T item) + protected virtual void InsertItemBase(int index, T item) => base.InsertItem(index, item); /// @@ -107,14 +109,14 @@ protected virtual void InsertItemBase(int index, T item) /// The item to set. protected override sealed void SetItem(int index, T item) { - if (PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) - { - OnUIThread(() => SetItemBase(index, item)); - } - else + if (!PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) { SetItemBase(index, item); + + return; } + + OnUIThread(() => SetItemBase(index, item)); } /// @@ -125,7 +127,7 @@ protected override sealed void SetItem(int index, T item) /// /// Used to avoid compiler warning regarding unverifiable code. /// - protected virtual void SetItemBase(int index, T item) + protected virtual void SetItemBase(int index, T item) => base.SetItem(index, item); /// @@ -134,14 +136,14 @@ protected virtual void SetItemBase(int index, T item) /// The position used to identify the item to remove. protected override sealed void RemoveItem(int index) { - if (PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) - { - OnUIThread(() => RemoveItemBase(index)); - } - else + if (!PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) { RemoveItemBase(index); + + return; } + + OnUIThread(() => RemoveItemBase(index)); } /// @@ -151,13 +153,13 @@ protected override sealed void RemoveItem(int index) /// /// Used to avoid compiler warning regarding unverifiable code. /// - protected virtual void RemoveItemBase(int index) + protected virtual void RemoveItemBase(int index) => base.RemoveItem(index); /// /// Clears the items contained by the collection. /// - protected override sealed void ClearItems() + protected override sealed void ClearItems() => OnUIThread(ClearItemsBase); /// @@ -166,7 +168,7 @@ protected override sealed void ClearItems() /// /// Used to avoid compiler warning regarding unverifiable code. /// - protected virtual void ClearItemsBase() + protected virtual void ClearItemsBase() => base.ClearItems(); /// @@ -175,10 +177,12 @@ protected virtual void ClearItemsBase() /// Arguments of the event being raised. protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) { - if (IsNotifying) + if (!IsNotifying) { - base.OnCollectionChanged(e); + return; } + + base.OnCollectionChanged(e); } /// @@ -187,10 +191,12 @@ protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) /// The event data to report in the event. protected override void OnPropertyChanged(PropertyChangedEventArgs e) { - if (IsNotifying) + if (!IsNotifying) { - base.OnPropertyChanged(e); + return; } + + base.OnPropertyChanged(e); } /// @@ -216,14 +222,14 @@ void AddRange() OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } - if (PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) - { - OnUIThread(AddRange); - } - else + if (!PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) { AddRange(); + + return; } + + OnUIThread(AddRange); } /// @@ -251,14 +257,14 @@ void RemoveRange() OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } - if (PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) - { - OnUIThread(RemoveRange); - } - else + if (!PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) { RemoveRange(); + + return; } + + OnUIThread(RemoveRange); } /// @@ -266,7 +272,7 @@ void RemoveRange() /// /// An extension point for subclasses to customise how property change notifications are handled. /// - protected virtual void OnUIThread(System.Action action) + protected virtual void OnUIThread(System.Action action) => action.OnUIThread(); } } diff --git a/src/Caliburn.Micro.Core/Types/PropertyChangedBase.cs b/src/Caliburn.Micro.Core/Types/PropertyChangedBase.cs index cd266502d..5f9bc62ad 100644 --- a/src/Caliburn.Micro.Core/Types/PropertyChangedBase.cs +++ b/src/Caliburn.Micro.Core/Types/PropertyChangedBase.cs @@ -15,7 +15,7 @@ public class PropertyChangedBase : INotifyPropertyChangedEx /// /// Creates an instance of . /// - public PropertyChangedBase() + public PropertyChangedBase() => IsNotifying = true; /// @@ -32,7 +32,7 @@ public PropertyChangedBase() /// /// Raises a change notification indicating that all bindings should be refreshed. /// - public virtual void Refresh() + public virtual void Refresh() => NotifyOfPropertyChange(string.Empty); /// @@ -41,17 +41,19 @@ public virtual void Refresh() /// Name of the property. public virtual void NotifyOfPropertyChange([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) { - if (IsNotifying && PropertyChanged != null) + if (!IsNotifying || PropertyChanged == null) { - if (PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) - { - OnUIThread(() => OnPropertyChanged(new PropertyChangedEventArgs(propertyName))); - } - else - { - OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); - } + return; } + + if (!PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) + { + OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); + + return; + } + + OnUIThread(() => OnPropertyChanged(new PropertyChangedEventArgs(propertyName))); } /// @@ -59,7 +61,7 @@ public virtual void NotifyOfPropertyChange([System.Runtime.CompilerServices.Call /// /// The type of the property. /// The property expression. - public void NotifyOfPropertyChange(Expression> property) + public void NotifyOfPropertyChange(Expression> property) => NotifyOfPropertyChange(property.GetMemberInfo().Name); /// @@ -67,7 +69,7 @@ public void NotifyOfPropertyChange(Expression> proper /// /// The instance containing the event data. [EditorBrowsable(EditorBrowsableState.Never)] - protected void OnPropertyChanged(PropertyChangedEventArgs e) + protected void OnPropertyChanged(PropertyChangedEventArgs e) => PropertyChanged?.Invoke(this, e); /// @@ -75,7 +77,7 @@ protected void OnPropertyChanged(PropertyChangedEventArgs e) /// /// An extension point for subclasses to customise how property change notifications are handled. /// - protected virtual void OnUIThread(System.Action action) + protected virtual void OnUIThread(System.Action action) => action.OnUIThread(); /// diff --git a/src/Caliburn.Micro.Core/Types/WeakValueDictionary.cs b/src/Caliburn.Micro.Core/Types/WeakValueDictionary.cs index 32be86f2d..f5ec93a6d 100644 --- a/src/Caliburn.Micro.Core/Types/WeakValueDictionary.cs +++ b/src/Caliburn.Micro.Core/Types/WeakValueDictionary.cs @@ -18,14 +18,14 @@ internal class WeakValueDictionary : IDictionary private bool IsCleanupNeeded() { - if (_gcSentinel.Target == null) + if (_gcSentinel.Target != null) { - _gcSentinel.Target = new object(); - - return true; + return false; } - return false; + _gcSentinel.Target = new object(); + + return true; } private void CleanAbandonedItems() @@ -39,10 +39,12 @@ private void CleanAbandonedItems() private void CleanIfNeeded() { - if (IsCleanupNeeded()) + if (!IsCleanupNeeded()) { - CleanAbandonedItems(); + return; } + + CleanAbandonedItems(); } /// @@ -229,7 +231,6 @@ public bool Remove(TKey key) public bool TryGetValue(TKey key, out TValue value) { CleanIfNeeded(); - if (!_inner.TryGetValue(key, out WeakReference wr)) { value = null; @@ -238,17 +239,17 @@ public bool TryGetValue(TKey key, out TValue value) } var result = (TValue)wr.Target; - if (result == null) + if (result != null) { - _inner.Remove(key); - value = null; + value = result; - return false; + return true; } - value = result; + _inner.Remove(key); + value = null; - return true; + return false; } /// @@ -261,15 +262,9 @@ public bool TryGetValue(TKey key, out TValue value) /// public TValue this[TKey key] { - get - { - if (!TryGetValue(key, out TValue result)) - { - throw new KeyNotFoundException(); - } - - return result; - } + get => TryGetValue(key, out TValue result) + ? result + : throw new KeyNotFoundException(); set { CleanIfNeeded(); diff --git a/src/Caliburn.Micro.Core/ViewAware/ViewAware.cs b/src/Caliburn.Micro.Core/ViewAware/ViewAware.cs index b53601378..059ddc461 100644 --- a/src/Caliburn.Micro.Core/ViewAware/ViewAware.cs +++ b/src/Caliburn.Micro.Core/ViewAware/ViewAware.cs @@ -14,26 +14,27 @@ public class ViewAware : PropertyChangedBase, IViewAware /// /// The default view context. /// - public static readonly object DefaultContext + public static readonly object DefaultContext = new(); /// /// The view chache for this instance. /// - protected IDictionary Views + protected IDictionary Views => _views; /// /// Creates an instance of . /// - public ViewAware() + public ViewAware() => _views = new WeakValueDictionary(); /// /// Raised when a view is attached. /// - public event EventHandler ViewAttached - = delegate { }; + public event EventHandler ViewAttached + = delegate + { }; void IViewAware.AttachView(object view, object context) { @@ -44,14 +45,14 @@ void IViewAware.AttachView(object view, object context) OnViewAttached(nonGeneratedView, context); ViewAttached(this, new ViewAttachedEventArgs { View = nonGeneratedView, Context = context }); - if (this is not IActivate activatable || activatable.IsActive) - { - PlatformProvider.Current.ExecuteOnLayoutUpdated(nonGeneratedView, OnViewReady); - } - else + if (this is IActivate activatable && !activatable.IsActive) { AttachViewReadyOnActivated(activatable, nonGeneratedView); + + return; } + + PlatformProvider.Current.ExecuteOnLayoutUpdated(nonGeneratedView, OnViewReady); } private static void AttachViewReadyOnActivated(IActivate activatable, object nonGeneratedView) @@ -61,10 +62,12 @@ Task OnActivated(object s, ActivationEventArgs e) { ((IActivate)s).Activated -= OnActivated; var view = viewReference.Target; - if (view != null) + if (view == null) { - PlatformProvider.Current.ExecuteOnLayoutUpdated(view, ((ViewAware)s).OnViewReady); + return Task.CompletedTask; } + + PlatformProvider.Current.ExecuteOnLayoutUpdated(view, ((ViewAware)s).OnViewReady); return Task.CompletedTask; } From ee636874d3b226bb9e8be208290c43c23a80bcf8 Mon Sep 17 00:00:00 2001 From: khaled Date: Sat, 7 Oct 2023 05:41:36 +0200 Subject: [PATCH 06/14] - Added disabled settings for Code Analysis. You can activate Code Analysis by setting 'SetupCodeAnalysis' to true in the project file '.csproj' and change SDK version in global.json to 7.0.400, build and you will get punch of errors, you suppress them by setting 'SuppressCodeAnalysisWarnings' to true. The list of errors in the .csproj file need to be fixed next, one by one, we remove item from NoWarn, fix the code, build, test and refactor. --- .../Caliburn.Micro.Core.csproj | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/Caliburn.Micro.Core/Caliburn.Micro.Core.csproj b/src/Caliburn.Micro.Core/Caliburn.Micro.Core.csproj index e42533612..c9c2b9551 100644 --- a/src/Caliburn.Micro.Core/Caliburn.Micro.Core.csproj +++ b/src/Caliburn.Micro.Core/Caliburn.Micro.Core.csproj @@ -10,6 +10,55 @@ latest + + + + false + false + + + + $(NoWarn);CA1711;CA1051;CA1003;CA2211;CA1070;CA1034;CA1052 + $(NoWarn);CA1062;CA2007;CA1033;CA2016;CA1031;CA1507;CA1716 + $(NoWarn);CA1305;CA2008;CA1825;CA1849;CA1822;CA1812;CA1852 + + + + 7 + prompt + True + All + latest-all + true + True + True + True + True + true + + From 44a7f5480cf65db17b8664b7f47f3567c41d34ef Mon Sep 17 00:00:00 2001 From: khaled Date: Sat, 7 Oct 2023 07:23:57 +0200 Subject: [PATCH 07/14] - Enabled Code Analysis, 6 types of issues fixed, another 14 types still there and need attention, some of theme is critical. CA1711 // Identifiers should not have incorrect suffix - AsyncEventHandler.cs - INotifyPropertyChangedEx.cs Cause: EventHandler and Ex suffix. CA1003 // Use generic event handler instances - SimpleContainer.cs -> event Action Activated - IActivate.cs -> event AsyncEventHandler Activated - IDeactivate.cs -> event AsyncEventHandler Deactivated Cause: Action instead of EventHandler, custome delegate AsyncEventHandler for EventHandler. Solution: use EventHandler delegate for Action, CA1070 // Do not declare event fields as virtual - Screen.cs -> public virtual event AsyncEventHandler Activated - Screen.cs -> public virtual event EventHandler AttemptingDeactivation - Screen.cs -> public virtual event AsyncEventHandler Deactivated - ConductorBase.cs -> public virtual event EventHandler ActivationProcessed - PropertyChangedBase.cs -> public virtual event PropertyChangedEventHandler PropertyChanged Cause: virtual keyword, events should not be overrding. Solution: Remove virtual keyword. CA1052 // Static holder types should be Static or NotInheritable - ConductorWithCollectionAllActive.cs -> Collection::AllActive - ConductorWithCollectionOneActive.cs -> Collection::OneActive CA1034 // Nested types should not be visible - ConductorWithCollectionAllActive.cs -> Collection::AllActive - ConductorWithCollectionOneActive.cs -> Collection::OneActive Cause: Nesting public class. Solution: move class to new namespace namespace Caliburn.Micro.Conductor.Collection { public class AllActive : ConductorBase { } } namespace Caliburn.Micro.Conductor.Collection { public class OneActive : ConductorBase { } } CA1062 // Validate arguments of public methods Cause: arguments used without validation. Solution: validate arguments of methods, when failed, return, return null or throw. - throw new ArgumentNullException(nameof(argumentName)) - throw new ArgumentException(message, nameof(argumentName)) CA2007 // Consider calling ConfigureAwait on the awaited task This is critical issue. read here and decide when to use ConfigureAwait(false) or ConfigureAwait(true) https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2007 CA1033 // Interface methods should be callable by child types - ViewAware.cs -> void IViewAware.AttachView(object view, object context) - Screen.cs -> async Task IActivate.ActivateAsync(CancellationToken cancellationToken) - Screen.cs -> async Task IDeactivate.DeactivateAsync(bool close, CancellationToken cancellationToken) Cause: Explicit implementation of the interface methods. Solution: - Add public method with same signature (Will not cause breaking change). - Make class sealed (Breaking change). - Make the implementation public instead of Explicit. CA1031 // Do not catch general exception types This is critical issue. Cause: catch (Exception ex). Solution: Catch Specific exception type, or rethrow the exception. CA1716 // Identifiers should not match keywords - ILog.cs -> void Error(...) - PropertyChangedBase.cs -> public virtual bool Set(...) Cause: using of reserved keyword (Error and Set). Solution: Change the name if possible, otherwise suppress this error. CA2008 // Do not create tasks without passing a TaskScheduler This is critical issue. - DefaultPlatformProvider.cs -> public virtual Task OnUIThreadAsync(Func action) => Task.Factory.StartNew(action); Cause: new task without specifying TaskScheduler. Solution: read the docs and decid. CA1849 // Call async methods when in an async method - ResultExtensions.cs -> result.Execute(context ?? new CoroutineExecutionContext()) Cause: There is method named 'ExecuteAsync'. Solution: ignore this error for this case, because calling ExecuteAsync will cause endless loop. CA1822 // Mark members as static CA1812 // Avoid uninstantiated internal classes - SimpleContainer.cs -> FactoryFactory.Create Cause: Pure Function not accessing any instance data. Solution: Can't change this since it is used by GetInstance method with reflection, or you have to change the logic of calling this method by reflection. --- .../Caliburn.Micro.Core.csproj | 25 +++++++++++-------- .../Conductor/Conductor.cs | 2 +- .../ConductorWithCollectionOneActive.cs | 4 +-- .../Coroutine/ExtensionPoints/Coroutine.cs | 2 +- .../EventAggregator/EventAggregator.cs | 2 +- .../IoC/ExtensionPoints/IoC.cs | 19 ++++++++------ .../IoC/SimpleContainer.cs | 6 ++--- .../Logging/ExtensionPoints/LogManager.cs | 7 +++--- .../Logging/Impl/DebugLog.cs | 5 ++-- .../EventArgs/ResultCompletionEventArgs.cs | 4 +-- .../Result/Impl/ContinueResultDecorator.cs | 5 ++-- .../Impl/OverrideCancelResultDecorator.cs | 6 +++-- .../Result/Impl/RescueResultDecorator.cs | 5 ++-- .../Result/Impl/ResultDecoratorBase.cs | 2 +- .../Types/WeakValueDictionary.cs | 10 ++++---- src/global.json | 2 +- 16 files changed, 59 insertions(+), 47 deletions(-) diff --git a/src/Caliburn.Micro.Core/Caliburn.Micro.Core.csproj b/src/Caliburn.Micro.Core/Caliburn.Micro.Core.csproj index c9c2b9551..14459dc34 100644 --- a/src/Caliburn.Micro.Core/Caliburn.Micro.Core.csproj +++ b/src/Caliburn.Micro.Core/Caliburn.Micro.Core.csproj @@ -11,38 +11,41 @@ + + - false - false + true + true - $(NoWarn);CA1711;CA1051;CA1003;CA2211;CA1070;CA1034;CA1052 - $(NoWarn);CA1062;CA2007;CA1033;CA2016;CA1031;CA1507;CA1716 - $(NoWarn);CA1305;CA2008;CA1825;CA1849;CA1822;CA1812;CA1852 + $(NoWarn);CA1711;CA1003;CA1070;CA1034;CA1052;CA1062;CA2007 + $(NoWarn);CA1033;CA1031;CA1716;CA2008;CA1849;CA1822;CA1812 diff --git a/src/Caliburn.Micro.Core/Conductor/Conductor.cs b/src/Caliburn.Micro.Core/Conductor/Conductor.cs index 27dee3172..619971476 100644 --- a/src/Caliburn.Micro.Core/Conductor/Conductor.cs +++ b/src/Caliburn.Micro.Core/Conductor/Conductor.cs @@ -56,7 +56,7 @@ public override async Task DeactivateItemAsync(T item, bool close, CancellationT return; } - await ChangeActiveItemAsync(default, close); + await ChangeActiveItemAsync(default, close, cancellationToken); } /// diff --git a/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionOneActive.cs b/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionOneActive.cs index b434a0f38..5b01db099 100644 --- a/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionOneActive.cs +++ b/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionOneActive.cs @@ -118,7 +118,7 @@ private async Task CloseItemCoreAsync(T item, CancellationToken cancellationToke var index = _items.IndexOf(item); T next = DetermineNextItemToActivate(_items, index); - await ChangeActiveItemAsync(next, true); + await ChangeActiveItemAsync(next, true, cancellationToken); } else { @@ -175,7 +175,7 @@ public override async Task CanCloseAsync(CancellationToken cancellationTok } while (closable.Contains(next)); T previousActive = ActiveItem; - await ChangeActiveItemAsync(next, true); + await ChangeActiveItemAsync(next, true, cancellationToken); _items.Remove(previousActive); var stillToClose = closable.ToList(); diff --git a/src/Caliburn.Micro.Core/Coroutine/ExtensionPoints/Coroutine.cs b/src/Caliburn.Micro.Core/Coroutine/ExtensionPoints/Coroutine.cs index 73fee5311..992d112bb 100644 --- a/src/Caliburn.Micro.Core/Coroutine/ExtensionPoints/Coroutine.cs +++ b/src/Caliburn.Micro.Core/Coroutine/ExtensionPoints/Coroutine.cs @@ -15,7 +15,7 @@ private static readonly ILog Log /// /// Creates the parent enumerator. /// - public static Func, IResult> CreateParentEnumerator + public static Func, IResult> CreateParentEnumerator { get; set; } = inner => new SequentialResult(inner); /// diff --git a/src/Caliburn.Micro.Core/EventAggregator/EventAggregator.cs b/src/Caliburn.Micro.Core/EventAggregator/EventAggregator.cs index 00739fddd..567dd14b5 100644 --- a/src/Caliburn.Micro.Core/EventAggregator/EventAggregator.cs +++ b/src/Caliburn.Micro.Core/EventAggregator/EventAggregator.cs @@ -103,7 +103,7 @@ public virtual Task PublishAsync(object message, Func, Task> marshal, }); } - private class Handler + private sealed class Handler { private readonly Func, Task> _marshal; private readonly WeakReference _reference; diff --git a/src/Caliburn.Micro.Core/IoC/ExtensionPoints/IoC.cs b/src/Caliburn.Micro.Core/IoC/ExtensionPoints/IoC.cs index 5e20963cf..8f414a64a 100644 --- a/src/Caliburn.Micro.Core/IoC/ExtensionPoints/IoC.cs +++ b/src/Caliburn.Micro.Core/IoC/ExtensionPoints/IoC.cs @@ -12,20 +12,23 @@ public static class IoC /// /// Gets an instance by type and key. /// - public static Func GetInstance = (service, key) - => throw new InvalidOperationException("IoC is not initialized."); + public static Func GetInstance { get; set; } + = (service, key) + => throw new InvalidOperationException("IoC is not initialized."); /// /// Gets all instances of a particular type. /// - public static Func> GetAllInstances = service - => throw new InvalidOperationException("IoC is not initialized."); + public static Func> GetAllInstances { get; set; } + = service + => throw new InvalidOperationException("IoC is not initialized."); /// /// Passes an existing instance to the IoC container to enable dependencies to be injected. /// - public static Action BuildUp = instance - => throw new InvalidOperationException("IoC is not initialized."); + public static Action BuildUp { get; set; } + = instance + => throw new InvalidOperationException("IoC is not initialized."); /// /// Gets an instance from the container. @@ -33,7 +36,7 @@ public static class IoC /// The type to resolve. /// The key to look up. /// The resolved instance. - public static T Get(string key = null) + public static T Get(string key = null) => (T)GetInstance(typeof(T), key); /// @@ -41,7 +44,7 @@ public static T Get(string key = null) /// /// The type to resolve. /// The resolved instances. - public static IEnumerable GetAll() + public static IEnumerable GetAll() => GetAllInstances(typeof(T)).Cast(); } } diff --git a/src/Caliburn.Micro.Core/IoC/SimpleContainer.cs b/src/Caliburn.Micro.Core/IoC/SimpleContainer.cs index 279beaed6..b92e0850e 100644 --- a/src/Caliburn.Micro.Core/IoC/SimpleContainer.cs +++ b/src/Caliburn.Micro.Core/IoC/SimpleContainer.cs @@ -168,7 +168,7 @@ public IEnumerable GetAllInstances(Type service, string key = null) if (entries == null) { - return new object[0]; + return Array.Empty(); } IEnumerable instances = entries.Select(e => e(this)); @@ -301,13 +301,13 @@ private ConstructorInfo SelectEligibleConstructor(Type type) .Select(c => c.Constructor) .FirstOrDefault(); - private class ContainerEntry : List> + private sealed class ContainerEntry : List> { public string Key; public Type Service; } - private class FactoryFactory + private sealed class FactoryFactory { public Func Create(SimpleContainer container) => () => (T)container.GetInstance(typeof(T), null); diff --git a/src/Caliburn.Micro.Core/Logging/ExtensionPoints/LogManager.cs b/src/Caliburn.Micro.Core/Logging/ExtensionPoints/LogManager.cs index a5361a93f..0d0a5b917 100644 --- a/src/Caliburn.Micro.Core/Logging/ExtensionPoints/LogManager.cs +++ b/src/Caliburn.Micro.Core/Logging/ExtensionPoints/LogManager.cs @@ -12,10 +12,11 @@ public static class LogManager /// /// Creates an for the provided type. /// - public static Func GetLog - = type => NullLogInstance; + public static Func GetLog { get; set; } + = type + => NullLogInstance; - private class NullLog : ILog + private sealed class NullLog : ILog { public void Info(string format, params object[] args) { } public void Warn(string format, params object[] args) { } diff --git a/src/Caliburn.Micro.Core/Logging/Impl/DebugLog.cs b/src/Caliburn.Micro.Core/Logging/Impl/DebugLog.cs index 014fab5f1..a9014d33e 100644 --- a/src/Caliburn.Micro.Core/Logging/Impl/DebugLog.cs +++ b/src/Caliburn.Micro.Core/Logging/Impl/DebugLog.cs @@ -2,6 +2,7 @@ using System; using System.Diagnostics; +using System.Globalization; namespace Caliburn.Micro { @@ -25,7 +26,7 @@ public DebugLog(Type type) /// A formatted message. /// Parameters to be injected into the formatted message. public void Info(string format, params object[] args) - => Debug.WriteLine("[{1}] INFO: {0}", string.Format(format, args), _typeName); + => Debug.WriteLine("[{1}] INFO: {0}", string.Format(CultureInfo.InvariantCulture, format, args), _typeName); /// /// Logs the message as a warning. @@ -33,7 +34,7 @@ public void Info(string format, params object[] args) /// A formatted message. /// Parameters to be injected into the formatted message. public void Warn(string format, params object[] args) - => Debug.WriteLine("[{1}] WARN: {0}", string.Format(format, args), _typeName); + => Debug.WriteLine("[{1}] WARN: {0}", string.Format(CultureInfo.InvariantCulture, format, args), _typeName); /// /// Logs the exception. diff --git a/src/Caliburn.Micro.Core/Result/EventArgs/ResultCompletionEventArgs.cs b/src/Caliburn.Micro.Core/Result/EventArgs/ResultCompletionEventArgs.cs index e6e86b196..8c43dbbcb 100644 --- a/src/Caliburn.Micro.Core/Result/EventArgs/ResultCompletionEventArgs.cs +++ b/src/Caliburn.Micro.Core/Result/EventArgs/ResultCompletionEventArgs.cs @@ -11,12 +11,12 @@ public class ResultCompletionEventArgs : EventArgs /// Gets or sets the error if one occurred. /// /// The error. - public Exception Error; + public Exception Error { get; set; } /// /// Gets or sets a value indicating whether the result was cancelled. /// /// true if cancelled; otherwise, false. - public bool WasCancelled; + public bool WasCancelled { get; set; } } } diff --git a/src/Caliburn.Micro.Core/Result/Impl/ContinueResultDecorator.cs b/src/Caliburn.Micro.Core/Result/Impl/ContinueResultDecorator.cs index 50b93c9f4..3e18f20ce 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/ContinueResultDecorator.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/ContinueResultDecorator.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; namespace Caliburn.Micro { @@ -17,7 +18,7 @@ public class ContinueResultDecorator : ResultDecoratorBase /// The coroutine to execute when was canceled. public ContinueResultDecorator(IResult result, Func coroutine) : base(result) - => _coroutine = coroutine ?? throw new ArgumentNullException("coroutine"); + => _coroutine = coroutine ?? throw new ArgumentNullException(nameof(coroutine)); /// /// Called when the execution of the decorated result has completed. @@ -34,7 +35,7 @@ protected override void OnInnerResultCompleted(CoroutineExecutionContext context return; } - Log.Info(string.Format("Executing coroutine because {0} was cancelled.", innerResult.GetType().Name)); + Log.Info(string.Format(CultureInfo.InvariantCulture, "Executing coroutine because {0} was cancelled.", innerResult.GetType().Name)); Continue(context); } diff --git a/src/Caliburn.Micro.Core/Result/Impl/OverrideCancelResultDecorator.cs b/src/Caliburn.Micro.Core/Result/Impl/OverrideCancelResultDecorator.cs index 3608dc09d..34c893ece 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/OverrideCancelResultDecorator.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/OverrideCancelResultDecorator.cs @@ -1,4 +1,6 @@ -namespace Caliburn.Micro +using System.Globalization; + +namespace Caliburn.Micro { /// /// A result decorator that overrides of the decorated instance. @@ -27,7 +29,7 @@ protected override void OnInnerResultCompleted(CoroutineExecutionContext context { if (args.WasCancelled) { - Log.Info(string.Format("Overriding WasCancelled from {0}.", innerResult.GetType().Name)); + Log.Info(string.Format(CultureInfo.InvariantCulture, "Overriding WasCancelled from {0}.", innerResult.GetType().Name)); } OnCompleted(new ResultCompletionEventArgs diff --git a/src/Caliburn.Micro.Core/Result/Impl/RescueResultDecorator.cs b/src/Caliburn.Micro.Core/Result/Impl/RescueResultDecorator.cs index 45744ed01..06fa2325f 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/RescueResultDecorator.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/RescueResultDecorator.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; namespace Caliburn.Micro { @@ -20,7 +21,7 @@ public class RescueResultDecorator : ResultDecoratorBase where TExce /// Set to true to cancel the result after executing rescue. public RescueResultDecorator(IResult result, Func coroutine, bool cancelResult = true) : base(result) { - _coroutine = coroutine ?? throw new ArgumentNullException("coroutine"); + _coroutine = coroutine ?? throw new ArgumentNullException(nameof(coroutine)); _cancelResult = cancelResult; } @@ -40,7 +41,7 @@ protected override void OnInnerResultCompleted(CoroutineExecutionContext context } Log.Error(error); - Log.Info(string.Format("Executing coroutine because {0} threw an exception.", innerResult.GetType().Name)); + Log.Info(string.Format(CultureInfo.InvariantCulture, "Executing coroutine because {0} threw an exception.", innerResult.GetType().Name)); Rescue(context, error); } diff --git a/src/Caliburn.Micro.Core/Result/Impl/ResultDecoratorBase.cs b/src/Caliburn.Micro.Core/Result/Impl/ResultDecoratorBase.cs index 89621fc5e..919855031 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/ResultDecoratorBase.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/ResultDecoratorBase.cs @@ -15,7 +15,7 @@ public abstract class ResultDecoratorBase : IResult /// /// The result to decorate. protected ResultDecoratorBase(IResult result) - => _innerResult = result ?? throw new ArgumentNullException("result"); + => _innerResult = result ?? throw new ArgumentNullException(nameof(result)); /// /// Executes the result using the specified context. diff --git a/src/Caliburn.Micro.Core/Types/WeakValueDictionary.cs b/src/Caliburn.Micro.Core/Types/WeakValueDictionary.cs index f5ec93a6d..ab514704a 100644 --- a/src/Caliburn.Micro.Core/Types/WeakValueDictionary.cs +++ b/src/Caliburn.Micro.Core/Types/WeakValueDictionary.cs @@ -10,7 +10,7 @@ namespace Caliburn.Micro /// /// The type of keys in the dictionary. /// The type of values in the dictionary. - internal class WeakValueDictionary : IDictionary + internal sealed class WeakValueDictionary : IDictionary where TValue : class { private readonly Dictionary _inner; @@ -136,12 +136,12 @@ void ICollection>.CopyTo(KeyValuePair[] { if (array == null) { - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); } if (arrayIndex < 0 || arrayIndex >= array.Length) { - throw new ArgumentOutOfRangeException("arrayIndex"); + throw new ArgumentOutOfRangeException(nameof(arrayIndex)); } if ((arrayIndex + Count) > array.Length) @@ -310,12 +310,12 @@ public void CopyTo(TValue[] array, int arrayIndex) { if (array == null) { - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); } if (arrayIndex < 0 || arrayIndex >= array.Length) { - throw new ArgumentOutOfRangeException("arrayIndex"); + throw new ArgumentOutOfRangeException(nameof(arrayIndex)); } if ((arrayIndex + Count) > array.Length) diff --git a/src/global.json b/src/global.json index 0b63e4cfe..d487bcea7 100644 --- a/src/global.json +++ b/src/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "7.0.100" + "version": "7.0.400" }, "msbuild-sdks": { "MSBuild.Sdk.Extras": "3.0.44" From bd1b3a98e954fd2e2b7422c433c3c617a0b3aff2 Mon Sep 17 00:00:00 2001 From: khaled Date: Sat, 7 Oct 2023 09:28:02 +0200 Subject: [PATCH 08/14] - Removed Zombie Code. - Added StyleCop package. - Added StyleCop configuration file 'stylecop.json'. - Applied StyleCop rules, Methods, Properties, Events and Indexers ordered according to these rules. - Removed empty xml documentation. - Added missing curly braces. - .editorconfig changed to enforce specific coding style, these changes can be rolled-back and StyleCop will enforce the new changes. By all these changes you should now have well structured project, organized by features, each feature folder contains all necessary files. Coding style enforced by dotnet analyzers and StyleCop, The rules is configurable via .editorconfig and stylecop.json files. But there still a lot of improvements that can be applied to the code itself by using new capabilities of the compiler, for example using record and struct record. The important final note, the warnings in (...) have to be resolved, they are critical and change the framework behaviors. --- .editorconfig | 385 +++++++++---- .../Caliburn.Micro.Core.csproj | 7 + .../Conductor/Base/ConductorBase.cs | 142 +++-- .../Base/ConductorBaseWithActiveItem.cs | 101 ++-- .../Conductor/Conductor.cs | 139 +++-- .../ConductorWithCollectionAllActive.cs | 320 ++++++----- .../ConductorWithCollectionOneActive.cs | 409 +++++++------- .../Conductor/Contracts/ICloseResult.cs | 26 +- .../Conductor/Contracts/ICloseStrategy.cs | 26 +- .../Conductor/Contracts/IConductActiveItem.cs | 14 +- .../Conductor/Contracts/IConductor.cs | 48 +- .../Conductor/Contracts/IHaveActiveItem.cs | 18 +- .../Conductor/Contracts/IParent.cs | 24 +- .../Conductor/Contracts/IParent{T}.cs | 26 +- .../Conductor/DefaultImpl/CloseResult.cs | 49 +- .../DefaultImpl/DefaultCloseStrategy.cs | 72 ++- .../EventArgs/ActivationProcessedEventArgs.cs | 28 +- .../Extensions/ConductorExtensions.cs | 26 +- .../Coroutine/ExtensionPoints/Coroutine.cs | 179 +++---- .../Models/CoroutineExecutionContext.cs | 34 +- .../Contracts/IEventAggregator.cs | 62 ++- .../EventAggregator/Contracts/IHandle.cs | 28 +- .../EventAggregator/EventAggregator.cs | 214 ++++---- .../Extensions/EventAggregatorExtensions.cs | 253 ++++----- .../Extensions/EnumerableExtensions.cs | 30 +- src/Caliburn.Micro.Core/Extensions/Execute.cs | 56 +- .../Extensions/ExpressionExtensions.cs | 35 +- .../IoC/ExtensionPoints/IoC.cs | 76 ++- .../IoC/Extensions/ContainerExtensions.cs | 295 +++++----- .../IoC/SimpleContainer.cs | 494 ++++++++--------- .../Logging/Contracts/ILog.cs | 44 +- .../Logging/ExtensionPoints/LogManager.cs | 36 +- .../Logging/Impl/DebugLog.cs | 66 ++- .../Contracts/IPlatformProvider.cs | 118 ++-- .../DefaultImpl/DefaultPlatformProvider.cs | 148 +++-- .../ExtensionPoints/PlatformProvider.cs | 20 +- .../Result/Contracts/IResult.cs | 28 +- .../Result/Contracts/IResult{TResult}.cs | 20 +- .../EventArgs/ResultCompletionEventArgs.cs | 30 +- .../Result/Extensions/ResultExtensions.cs | 220 ++++---- .../Result/Impl/ContinueResultDecorator.cs | 111 ++-- .../Result/Impl/DelegateResult.cs | 62 +-- .../Result/Impl/DelegateResult{TResult}.cs | 73 ++- .../Impl/OverrideCancelResultDecorator.cs | 58 +- .../Result/Impl/RescueResultDecorator.cs | 126 ++--- .../Result/Impl/ResultDecoratorBase.cs | 107 ++-- .../Result/Impl/SequentialResult.cs | 138 +++-- .../Result/Impl/SimpleResult.cs | 100 ++-- .../Result/Impl/TaskResult.cs | 92 ++-- .../Result/Impl/TaskResult{TResult}.cs | 59 +- .../Screen/Contracts/IActivate.cs | 38 +- .../Screen/Contracts/IChild.cs | 18 +- .../Screen/Contracts/IChild{TParent}.cs | 20 +- .../Screen/Contracts/IClose.cs | 22 +- .../Screen/Contracts/IDeactivate.cs | 40 +- .../Screen/Contracts/IGuardClose.cs | 22 +- .../Screen/Contracts/IHaveDisplayName.cs | 18 +- .../Screen/Contracts/IScreen.cs | 16 +- .../Screen/EventArgs/ActivationEventArgs.cs | 18 +- .../Screen/EventArgs/DeactivationEventArgs.cs | 18 +- .../Screen/EventHandlers/AsyncEventHandler.cs | 9 +- .../Screen/Extensions/ActivateExtensions.cs | 24 +- .../Extensions/AsyncEventHandlerExtensions.cs | 24 +- .../Screen/Extensions/DeactivateExtensions.cs | 26 +- .../Screen/Extensions/ScreenExtensions.cs | 251 +++++---- src/Caliburn.Micro.Core/Screen/Screen.cs | 351 ++++++------ .../Types/BindableCollection.cs | 434 +++++++-------- .../Types/INotifyPropertyChangedEx.cs | 36 +- .../Types/IObservableCollection.cs | 32 +- .../Types/PropertyChangedBase.cs | 175 +++--- .../Types/WeakValueDictionary.cs | 506 ++++++++---------- .../ViewAware/Contracts/IViewAware.cs | 42 +- .../EventArgs/ViewAttachedEventArgs.cs | 26 +- .../ViewAware/ViewAware.cs | 175 +++--- src/stylecop.json | 68 +++ 75 files changed, 3734 insertions(+), 3947 deletions(-) create mode 100644 src/stylecop.json diff --git a/.editorconfig b/.editorconfig index fa83487e0..becf76c82 100644 --- a/.editorconfig +++ b/.editorconfig @@ -12,100 +12,63 @@ insert_final_newline = true indent_style = space indent_size = 4 -# C# files -[*.cs] -# New line preferences -csharp_new_line_before_open_brace = all -csharp_new_line_before_else = true -csharp_new_line_before_catch = true -csharp_new_line_before_finally = true -csharp_new_line_before_members_in_object_initializers = true -csharp_new_line_before_members_in_anonymous_types = true -csharp_new_line_between_query_expression_clauses = true - -# Indentation preferences -csharp_indent_block_contents = true -csharp_indent_braces = false -csharp_indent_case_contents = true -csharp_indent_switch_labels = true -csharp_indent_labels = one_less_than_current - -# avoid this. unless absolutely necessary -dotnet_style_qualification_for_field = false:suggestion -dotnet_style_qualification_for_property = false:suggestion -dotnet_style_qualification_for_method = false:suggestion -dotnet_style_qualification_for_event = false:suggestion - -# only use var when it's obvious what the variable type is -csharp_style_var_for_built_in_types = false:none -csharp_style_var_when_type_is_apparent = false:none -csharp_style_var_elsewhere = false:suggestion - -# use language keywords instead of BCL types -dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion -dotnet_style_predefined_type_for_member_access = true:suggestion +[*.{asm,inc}] +indent_size = 8 -# name all constant fields using PascalCase -dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion -dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields -dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style +# Xml project files +[*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}] +indent_size = 2 -dotnet_naming_symbols.constant_fields.applicable_kinds = field -dotnet_naming_symbols.constant_fields.required_modifiers = const +# Xml config files +[*.{props,targets,config,nuspec}] +indent_size = 2 -dotnet_naming_style.pascal_case_style.capitalization = pascal_case +[CMakeLists.txt] +indent_size = 2 -# static fields should have s_ prefix -dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion -dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields -dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style +[*.cmd] +indent_size = 2 -dotnet_naming_symbols.static_fields.applicable_kinds = field -dotnet_naming_symbols.static_fields.required_modifiers = static +[**.md] +indent_style = tab +trim_trailing_whitespace = false -dotnet_naming_style.static_prefix_style.capitalization = pascal_case +[*.ps1] +indent_size = 2 -# internal and private fields should be _camelCase -dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion -dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields -dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style +[*.sh] +indent_size = 2 +end_of_line = lf -dotnet_naming_symbols.private_internal_fields.applicable_kinds = field -dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal +[{*.yml,*.yaml,package.json}] +indent_size = 2 -dotnet_naming_style.camel_case_underscore_style.required_prefix = _ -dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case +[**.json] +indent_size = 2 -# Code style defaults -dotnet_sort_system_directives_first = true +# C# files +[*.cs] +tab_width = 4 +end_of_line = crlf +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_labels = one_less_than_current +csharp_indent_switch_labels = true +csharp_new_line_before_catch = false +csharp_new_line_before_else = false +csharp_new_line_before_finally = false +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_open_brace = none +csharp_new_line_between_query_expression_clauses = true +csharp_prefer_braces = true:error +csharp_prefer_simple_default_expression = true:error +csharp_prefer_simple_using_statement = true:error +csharp_prefer_static_local_function = true:suggestion csharp_preserve_single_line_blocks = true -csharp_preserve_single_line_statements = false - -# Expression-level preferences -dotnet_style_object_initializer = true:suggestion -dotnet_style_collection_initializer = true:suggestion -dotnet_style_explicit_tuple_names = true:suggestion -dotnet_style_coalesce_expression = true:suggestion -dotnet_style_null_propagation = true:suggestion - -# Expression-bodied members -csharp_style_expression_bodied_methods = false:none -csharp_style_expression_bodied_constructors = false:none -csharp_style_expression_bodied_operators = false:none -csharp_style_expression_bodied_properties = true:none -csharp_style_expression_bodied_indexers = true:none -csharp_style_expression_bodied_accessors = true:none - -# Pattern matching -csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion -csharp_style_pattern_matching_over_as_with_null_check = true:suggestion -csharp_style_inlined_variable_declaration = true:suggestion - -# Null checking preferences -csharp_style_throw_expression = true:suggestion -csharp_style_conditional_delegate_call = true:suggestion - -# Space preferences +csharp_preserve_single_line_statements = true csharp_space_after_cast = false csharp_space_after_colon_in_inheritance_clause = true csharp_space_after_comma = true @@ -113,7 +76,7 @@ csharp_space_after_dot = false csharp_space_after_keywords_in_control_flow_statements = true csharp_space_after_semicolon_in_for_statement = true csharp_space_around_binary_operators = before_and_after -csharp_space_around_declaration_statements = do_not_ignore +csharp_space_around_declaration_statements = false csharp_space_before_colon_in_inheritance_clause = true csharp_space_before_comma = false csharp_space_before_dot = false @@ -128,20 +91,250 @@ csharp_space_between_method_declaration_name_and_open_parenthesis = false csharp_space_between_method_declaration_parameter_list_parentheses = false csharp_space_between_parentheses = false csharp_space_between_square_brackets = false +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent +csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent +csharp_style_conditional_delegate_call = true:error +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_style_expression_bodied_accessors = true:error +csharp_style_expression_bodied_constructors = true:error +csharp_style_expression_bodied_indexers = true:error +csharp_style_expression_bodied_lambdas = true:error +csharp_style_expression_bodied_local_functions = true:error +csharp_style_expression_bodied_methods = true:error +csharp_style_expression_bodied_operators = true:error +csharp_style_expression_bodied_properties = true:error +csharp_style_implicit_object_creation_when_type_is_apparent = false:none +csharp_style_inlined_variable_declaration = true:error +csharp_style_namespace_declarations = file_scoped:error +csharp_style_pattern_matching_over_as_with_null_check = true:error +csharp_style_pattern_matching_over_is_with_cast_check = true:error +csharp_style_prefer_extended_property_pattern = true:error +csharp_style_prefer_index_operator = true:error +csharp_style_prefer_local_over_anonymous_function = true:error +csharp_style_prefer_method_group_conversion = true:suggestion +csharp_style_prefer_not_pattern = true:error +csharp_style_prefer_null_check_over_type_check = true:error +csharp_style_prefer_pattern_matching = true:error +csharp_style_prefer_range_operator = true:error +csharp_style_prefer_readonly_struct = true:suggestion +csharp_style_prefer_switch_expression = true:error +csharp_style_prefer_top_level_statements = true:suggestion +csharp_style_prefer_tuple_swap = true:suggestion +csharp_style_prefer_utf8_string_literals = true:suggestion +csharp_style_throw_expression = true:error +csharp_style_unused_value_assignment_preference = discard_variable:error +csharp_style_unused_value_expression_statement_preference = discard_variable:silent +csharp_style_var_elsewhere = false:error +csharp_style_var_for_built_in_types = false:error +csharp_style_var_when_type_is_apparent = true:error +csharp_using_directive_placement = outside_namespace:error -[*.{asm,inc}] -indent_size = 8 +csharp_style_prefer_readonly_struct_member = true:suggestion +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent -# Xml project files -[*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}] -indent_size = 2 +[*.{cs,vb}] +tab_width = 4 +end_of_line = crlf -# Xml config files -[*.{props,targets,config,nuspec}] -indent_size = 2 +dotnet_style_namespace_match_folder = false:silent +dotnet_style_operator_placement_when_wrapping = beginning_of_line -[CMakeLists.txt] -indent_size = 2 +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_collection_initializer = true:error +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_null_propagation = true:error +dotnet_style_object_initializer = true:error +dotnet_style_prefer_auto_properties = true:error +dotnet_style_prefer_compound_assignment = true:error +dotnet_style_prefer_conditional_expression_over_assignment = true:error +dotnet_style_prefer_conditional_expression_over_return = true:error +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:error +dotnet_style_prefer_simplified_boolean_expressions = true:error +dotnet_style_prefer_simplified_interpolation = true:suggestion +dotnet_style_readonly_field = true:error +dotnet_style_predefined_type_for_locals_parameters_members = true:error +dotnet_style_predefined_type_for_member_access = true:error +dotnet_style_require_accessibility_modifiers = for_non_interface_members:error +dotnet_style_allow_multiple_blank_lines_experimental = false:error +dotnet_style_allow_statement_immediately_after_block_experimental = true:silent +dotnet_code_quality_unused_parameters = all:error +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:error +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:error +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:error +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion +dotnet_style_qualification_for_field = false:error +dotnet_style_qualification_for_property = false:error +dotnet_style_qualification_for_method = false:error +dotnet_style_qualification_for_event = false:error +dotnet_diagnostic.SA0001.severity = none +dotnet_diagnostic.SA1633.severity = silent +dotnet_diagnostic.SA1500.severity = silent +dotnet_diagnostic.SA1309.severity = silent +dotnet_diagnostic.SA1101.severity = silent -[*.cmd] -indent_size = 2 \ No newline at end of file +dotnet_diagnostic.NUnit2001.severity = warning +dotnet_diagnostic.NUnit2002.severity = warning +dotnet_diagnostic.NUnit2003.severity = warning +dotnet_diagnostic.NUnit2004.severity = warning +dotnet_diagnostic.NUnit2016.severity = warning +dotnet_diagnostic.NUnit2017.severity = warning +dotnet_diagnostic.NUnit2018.severity = warning +dotnet_diagnostic.NUnit2019.severity = warning +dotnet_diagnostic.NUnit2027.severity = warning +dotnet_diagnostic.NUnit2028.severity = warning +dotnet_diagnostic.NUnit2029.severity = warning +dotnet_diagnostic.NUnit2030.severity = warning +dotnet_diagnostic.NUnit2032.severity = warning +dotnet_diagnostic.NUnit2033.severity = warning +dotnet_diagnostic.NUnit2034.severity = warning +dotnet_diagnostic.NUnit2035.severity = warning +dotnet_diagnostic.NUnit2036.severity = warning +dotnet_diagnostic.NUnit2037.severity = warning +dotnet_diagnostic.NUnit2038.severity = warning +dotnet_diagnostic.NUnit2039.severity = warning +dotnet_diagnostic.NUnit1028.severity = warning +dotnet_diagnostic.IDE0052.severity = warning +dotnet_diagnostic.IDE0021.severity = warning +dotnet_diagnostic.IDE0059.severity = warning +dotnet_diagnostic.IDE0008.severity = warning +dotnet_diagnostic.IDE0051.severity = warning +dotnet_diagnostic.IDE0064.severity = warning +dotnet_diagnostic.IDE0076.severity = warning +dotnet_diagnostic.IDE0077.severity = warning +dotnet_diagnostic.SYSLIB1045.severity = warning +dotnet_diagnostic.SYSLIB1054.severity = warning +dotnet_diagnostic.CA1070.severity = warning +dotnet_diagnostic.CA2016.severity = warning +dotnet_diagnostic.IDE0004.severity = warning +dotnet_diagnostic.IDE0005.severity = silent +dotnet_diagnostic.IDE2000.severity = warning +dotnet_diagnostic.IDE0241.severity = warning +dotnet_diagnostic.IDE0240.severity = warning +dotnet_diagnostic.IDE0200.severity = warning +dotnet_diagnostic.IDE0083.severity = warning +dotnet_diagnostic.IDE0080.severity = warning +dotnet_diagnostic.IDE0078.severity = warning +dotnet_diagnostic.IDE0075.severity = warning +dotnet_diagnostic.IDE0074.severity = warning +dotnet_diagnostic.IDE0065.severity = warning +dotnet_diagnostic.IDE0017.severity = warning +dotnet_diagnostic.IDE0018.severity = warning +dotnet_diagnostic.IDE0019.severity = warning +dotnet_diagnostic.IDE0020.severity = warning +dotnet_diagnostic.IDE0022.severity = warning +dotnet_diagnostic.IDE0023.severity = warning +dotnet_diagnostic.IDE0024.severity = warning +dotnet_diagnostic.IDE0025.severity = warning +dotnet_diagnostic.IDE0026.severity = warning +dotnet_diagnostic.IDE0027.severity = warning +dotnet_diagnostic.IDE0028.severity = warning +dotnet_diagnostic.IDE0029.severity = warning +dotnet_diagnostic.IDE0030.severity = warning +dotnet_diagnostic.IDE0031.severity = warning +dotnet_diagnostic.IDE0032.severity = suggestion +dotnet_diagnostic.IDE0034.severity = warning +dotnet_diagnostic.IDE0036.severity = warning +dotnet_diagnostic.IDE0039.severity = suggestion +dotnet_diagnostic.IDE0040.severity = warning +dotnet_diagnostic.IDE0045.severity = warning +dotnet_diagnostic.IDE0046.severity = warning +dotnet_diagnostic.IDE0047.severity = warning +dotnet_diagnostic.IDE0048.severity = warning +dotnet_diagnostic.IDE0053.severity = warning +dotnet_diagnostic.IDE0054.severity = warning +dotnet_diagnostic.IDE0055.severity = warning +csharp_style_prefer_primary_constructors = true:suggestion + +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = error +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +# Naming styles + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_code_quality_unused_parameters = all:error +dotnet_style_allow_multiple_blank_lines_experimental = false:error +dotnet_style_allow_statement_immediately_after_block_experimental = true:silent +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:error +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:error +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:error +dotnet_style_predefined_type_for_locals_parameters_members = true:error +dotnet_style_predefined_type_for_member_access = true:error +dotnet_style_qualification_for_event = false:error +dotnet_style_qualification_for_field = false:error +dotnet_style_qualification_for_method = false:error +dotnet_style_qualification_for_property = false:error +dotnet_style_readonly_field = true:error +dotnet_style_require_accessibility_modifiers = for_non_interface_members:error + +dotnet_diagnostic.CA1014.severity = silent +dotnet_diagnostic.CA1303.severity = silent +dotnet_diagnostic.CA1822.severity = silent + +dotnet_diagnostic.CA1827.severity = warning +dotnet_diagnostic.CA1828.severity = warning +dotnet_diagnostic.CA2211.severity = warning +dotnet_diagnostic.CA2219.severity = warning +dotnet_diagnostic.CA2245.severity = warning +dotnet_diagnostic.CA1000.severity = warning +dotnet_diagnostic.CA1018.severity = warning +dotnet_diagnostic.CA1041.severity = warning +dotnet_diagnostic.CA1050.severity = warning +dotnet_diagnostic.CA1051.severity = warning +dotnet_diagnostic.CA1067.severity = warning +dotnet_diagnostic.CA1068.severity = warning +dotnet_diagnostic.CA1069.severity = warning +dotnet_diagnostic.CA1016.severity = warning +dotnet_diagnostic.CA1061.severity = warning +dotnet_diagnostic.CA1401.severity = warning +dotnet_diagnostic.CA1421.severity = warning +dotnet_diagnostic.CA1419.severity = warning +dotnet_diagnostic.CA2009.severity = warning +dotnet_diagnostic.CA2011.severity = warning +dotnet_diagnostic.CA2012.severity = warning +dotnet_diagnostic.CA2019.severity = warning +dotnet_diagnostic.CA5351.severity = warning +dotnet_diagnostic.CA5350.severity = warning +dotnet_diagnostic.CA1010.severity = warning +dotnet_diagnostic.IDE0070.severity = warning +dotnet_diagnostic.IDE0044.severity = warning diff --git a/src/Caliburn.Micro.Core/Caliburn.Micro.Core.csproj b/src/Caliburn.Micro.Core/Caliburn.Micro.Core.csproj index 14459dc34..bbcf4e6a1 100644 --- a/src/Caliburn.Micro.Core/Caliburn.Micro.Core.csproj +++ b/src/Caliburn.Micro.Core/Caliburn.Micro.Core.csproj @@ -41,6 +41,7 @@ true true + true @@ -83,4 +84,10 @@ + + + + + + diff --git a/src/Caliburn.Micro.Core/Conductor/Base/ConductorBase.cs b/src/Caliburn.Micro.Core/Conductor/Base/ConductorBase.cs index a68735a4f..c7f00e5d4 100644 --- a/src/Caliburn.Micro.Core/Conductor/Base/ConductorBase.cs +++ b/src/Caliburn.Micro.Core/Conductor/Base/ConductorBase.cs @@ -4,91 +4,89 @@ using System.Threading; using System.Threading.Tasks; -namespace Caliburn.Micro -{ - /// - /// A base class for various implementations of . - /// - /// The type that is being conducted. - public abstract class ConductorBase : Screen, IConductor, IParent where T : class - { - private ICloseStrategy _closeStrategy; +namespace Caliburn.Micro; - /// - /// Gets or sets the close strategy. - /// - /// The close strategy. - public ICloseStrategy CloseStrategy - { - get => _closeStrategy ??= new DefaultCloseStrategy(); - set => _closeStrategy = value; - } +/// +/// A base class for various implementations of . +/// +/// The type that is being conducted. +public abstract class ConductorBase : Screen, IConductor, IParent + where T : class { + private ICloseStrategy _closeStrategy; - Task IConductor.DeactivateItemAsync(object item, bool close, CancellationToken cancellationToken) - => DeactivateItemAsync((T)item, close, cancellationToken); + /// + /// Occurs when an activation request is processed. + /// + public virtual event EventHandler ActivationProcessed + = (sender, e) => { }; - IEnumerable IParent.GetChildren() - => GetChildren(); + /// + /// Gets or sets the close strategy. + /// + /// The close strategy. + public ICloseStrategy CloseStrategy { + get => _closeStrategy ??= new DefaultCloseStrategy(); + set => _closeStrategy = value; + } - /// - /// Occurs when an activation request is processed. - /// - public virtual event EventHandler ActivationProcessed = delegate { }; + Task IConductor.DeactivateItemAsync(object item, bool close, CancellationToken cancellationToken) + => DeactivateItemAsync((T)item, close, cancellationToken); - /// - /// Gets the children. - /// - /// The collection of children. - public abstract IEnumerable GetChildren(); + IEnumerable IParent.GetChildren() + => GetChildren(); - Task IConductor.ActivateItemAsync(object item, CancellationToken cancellationToken) - => ActivateItemAsync((T)item, cancellationToken); + /// + /// Gets the children. + /// + /// The collection of children. + public abstract IEnumerable GetChildren(); - /// - /// Activates the specified item. - /// - /// The item to activate. - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - /// A task that represents the asynchronous operation. - public abstract Task ActivateItemAsync(T item, CancellationToken cancellationToken = default); + Task IConductor.ActivateItemAsync(object item, CancellationToken cancellationToken) + => ActivateItemAsync((T)item, cancellationToken); - /// - /// Deactivates the specified item. - /// - /// The item to close. - /// Indicates whether or not to close the item after deactivating it. - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation. - public abstract Task DeactivateItemAsync(T item, bool close, CancellationToken cancellationToken = default); + /// + /// Activates the specified item. + /// + /// The item to activate. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A task that represents the asynchronous operation. + public abstract Task ActivateItemAsync(T item, CancellationToken cancellationToken = default); - /// - /// Called by a subclass when an activation needs processing. - /// - /// The item on which activation was attempted. - /// if set to true activation was successful. - protected virtual void OnActivationProcessed(T item, bool success) - { - if (item == null) - return; + /// + /// Deactivates the specified item. + /// + /// The item to close. + /// Indicates whether or not to close the item after deactivating it. + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation. + public abstract Task DeactivateItemAsync(T item, bool close, CancellationToken cancellationToken = default); - ActivationProcessed?.Invoke(this, new ActivationProcessedEventArgs - { - Item = item, - Success = success - }); + /// + /// Called by a subclass when an activation needs processing. + /// + /// The item on which activation was attempted. + /// if set to true activation was successful. + protected virtual void OnActivationProcessed(T item, bool success) { + if (item == null) { + return; } - /// - /// Ensures that an item is ready to be activated. - /// - /// The item that is about to be activated. - /// The item to be activated. - protected virtual T EnsureItem(T newItem) - { - if (newItem is IChild node && node.Parent != this) - node.Parent = this; + ActivationProcessed?.Invoke(this, new ActivationProcessedEventArgs { + Item = item, + Success = success, + }); + } - return newItem; + /// + /// Ensures that an item is ready to be activated. + /// + /// The item that is about to be activated. + /// The item to be activated. + protected virtual T EnsureItem(T newItem) { + if (newItem is IChild node && node.Parent != this) { + node.Parent = this; } + + return newItem; } } diff --git a/src/Caliburn.Micro.Core/Conductor/Base/ConductorBaseWithActiveItem.cs b/src/Caliburn.Micro.Core/Conductor/Base/ConductorBaseWithActiveItem.cs index 01fc47635..657badf04 100644 --- a/src/Caliburn.Micro.Core/Conductor/Base/ConductorBaseWithActiveItem.cs +++ b/src/Caliburn.Micro.Core/Conductor/Base/ConductorBaseWithActiveItem.cs @@ -1,63 +1,60 @@ using System.Threading; using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// A base class for various implementations of that maintain an active item. +/// +/// The type that is being conducted. +public abstract class ConductorBaseWithActiveItem : ConductorBase, IConductActiveItem + where T : class { + private T _activeItem; + /// - /// A base class for various implementations of that maintain an active item. + /// The currently active item. /// - /// The type that is being conducted. - public abstract class ConductorBaseWithActiveItem : ConductorBase, IConductActiveItem where T : class - { - private T _activeItem; - - /// - /// The currently active item. - /// - public T ActiveItem - { - get => _activeItem; - set => ActivateItemAsync(value, CancellationToken.None); - } + public T ActiveItem { + get => _activeItem; + set => ActivateItemAsync(value, CancellationToken.None); + } - /// - /// The currently active item. - /// - /// - object IHaveActiveItem.ActiveItem - { - get => ActiveItem; - set => ActiveItem = (T)value; - } + /// + /// The currently active item. + /// + /// + object IHaveActiveItem.ActiveItem { + get => ActiveItem; + set => ActiveItem = (T)value; + } - /// - /// Changes the active item. - /// - /// The new item to activate. - /// Indicates whether or not to close the previous active item. - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation. - protected virtual async Task ChangeActiveItemAsync(T newItem, bool closePrevious, CancellationToken cancellationToken) - { - await ScreenExtensions.TryDeactivateAsync(_activeItem, closePrevious, cancellationToken); - newItem = EnsureItem(newItem); - - _activeItem = newItem; - NotifyOfPropertyChange(nameof(ActiveItem)); - - if (IsActive) - await ScreenExtensions.TryActivateAsync(newItem, cancellationToken); - - OnActivationProcessed(_activeItem, true); + /// + /// Changes the active item. + /// + /// The new item to activate. + /// Indicates whether or not to close the previous active item. + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation. + protected virtual async Task ChangeActiveItemAsync(T newItem, bool closePrevious, CancellationToken cancellationToken) { + await ScreenExtensions.TryDeactivateAsync(_activeItem, closePrevious, cancellationToken); + newItem = EnsureItem(newItem); + + _activeItem = newItem; + NotifyOfPropertyChange(nameof(ActiveItem)); + + if (IsActive) { + await ScreenExtensions.TryActivateAsync(newItem, cancellationToken); } - /// - /// Changes the active item. - /// - /// The new item to activate. - /// Indicates whether or not to close the previous active item. - /// A task that represents the asynchronous operation. - protected Task ChangeActiveItemAsync(T newItem, bool closePrevious) - => ChangeActiveItemAsync(newItem, closePrevious, default); + OnActivationProcessed(_activeItem, true); } + + /// + /// Changes the active item. + /// + /// The new item to activate. + /// Indicates whether or not to close the previous active item. + /// A task that represents the asynchronous operation. + protected Task ChangeActiveItemAsync(T newItem, bool closePrevious) + => ChangeActiveItemAsync(newItem, closePrevious, default); } diff --git a/src/Caliburn.Micro.Core/Conductor/Conductor.cs b/src/Caliburn.Micro.Core/Conductor/Conductor.cs index 619971476..6ced26e42 100644 --- a/src/Caliburn.Micro.Core/Conductor/Conductor.cs +++ b/src/Caliburn.Micro.Core/Conductor/Conductor.cs @@ -2,96 +2,87 @@ using System.Threading; using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// An implementation of that holds on to and activates only one item at a time. +/// +public partial class Conductor : ConductorBaseWithActiveItem + where T : class { /// - /// An implementation of that holds on to and activates only one item at a time. + /// Gets the children. /// - public partial class Conductor : ConductorBaseWithActiveItem where T : class - { - /// - public override async Task ActivateItemAsync(T item, CancellationToken cancellationToken = default) - { - if (item != null && item.Equals(ActiveItem)) - { - if (!IsActive) - { - return; - } - - await ScreenExtensions.TryActivateAsync(item, cancellationToken); - OnActivationProcessed(item, true); + /// The collection of children. + public override IEnumerable GetChildren() + => new[] { ActiveItem }; + /// + public override async Task ActivateItemAsync(T item, CancellationToken cancellationToken = default) { + if (item != null && item.Equals(ActiveItem)) { + if (!IsActive) { return; } - ICloseResult closeResult = await CloseStrategy.ExecuteAsync(new[] { ActiveItem }, cancellationToken); - if (!closeResult.CloseCanOccur) - { - OnActivationProcessed(item, false); - - return; - } + await ScreenExtensions.TryActivateAsync(item, cancellationToken); + OnActivationProcessed(item, true); - await ChangeActiveItemAsync(item, true, cancellationToken); + return; } - /// - /// Deactivates the specified item. - /// - /// The item to close. - /// Indicates whether or not to close the item after deactivating it. - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation. - public override async Task DeactivateItemAsync(T item, bool close, CancellationToken cancellationToken = default) - { - if (item == null || !item.Equals(ActiveItem)) - { - return; - } + ICloseResult closeResult = await CloseStrategy.ExecuteAsync(new[] { ActiveItem }, cancellationToken); + if (!closeResult.CloseCanOccur) { + OnActivationProcessed(item, false); - ICloseResult closeResult = await CloseStrategy.ExecuteAsync(new[] { ActiveItem }, CancellationToken.None); - if (!closeResult.CloseCanOccur) - { - return; - } - - await ChangeActiveItemAsync(default, close, cancellationToken); + return; } - /// - /// Called to check whether or not this instance can close. - /// - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation. - public override async Task CanCloseAsync(CancellationToken cancellationToken = default) - { - ICloseResult closeResult = await CloseStrategy.ExecuteAsync(new[] { ActiveItem }, cancellationToken); + await ChangeActiveItemAsync(item, true, cancellationToken); + } - return closeResult.CloseCanOccur; + /// + /// Deactivates the specified item. + /// + /// The item to close. + /// Indicates whether or not to close the item after deactivating it. + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation. + public override async Task DeactivateItemAsync(T item, bool close, CancellationToken cancellationToken = default) { + if (item == null || !item.Equals(ActiveItem)) { + return; } - /// - /// Called when activating. - /// - /// A task that represents the asynchronous operation. - protected override Task OnActivateAsync(CancellationToken cancellationToken) - => ScreenExtensions.TryActivateAsync(ActiveItem, cancellationToken); + ICloseResult closeResult = await CloseStrategy.ExecuteAsync(new[] { ActiveItem }, CancellationToken.None); + if (!closeResult.CloseCanOccur) { + return; + } + + await ChangeActiveItemAsync(default, close, cancellationToken); + } - /// - /// Called when deactivating. - /// - /// Indicates whether this instance will be closed. - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation. - protected override Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) - => ScreenExtensions.TryDeactivateAsync(ActiveItem, close, cancellationToken); + /// + /// Called to check whether or not this instance can close. + /// + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation. + public override async Task CanCloseAsync(CancellationToken cancellationToken = default) { + ICloseResult closeResult = await CloseStrategy.ExecuteAsync(new[] { ActiveItem }, cancellationToken); - /// - /// Gets the children. - /// - /// The collection of children. - public override IEnumerable GetChildren() - => new[] { ActiveItem }; + return closeResult.CloseCanOccur; } + + /// + /// Called when activating. + /// + /// A task that represents the asynchronous operation. + protected override Task OnActivateAsync(CancellationToken cancellationToken) + => ScreenExtensions.TryActivateAsync(ActiveItem, cancellationToken); + + /// + /// Called when deactivating. + /// + /// Indicates whether this instance will be closed. + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation. + protected override Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) + => ScreenExtensions.TryDeactivateAsync(ActiveItem, close, cancellationToken); } diff --git a/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionAllActive.cs b/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionAllActive.cs index e15522177..70849c603 100644 --- a/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionAllActive.cs +++ b/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionAllActive.cs @@ -6,198 +6,186 @@ using System.Threading; using System.Threading.Tasks; -namespace Caliburn.Micro -{ - public partial class Conductor - { +namespace Caliburn.Micro; + +public partial class Conductor { + /// + /// An implementation of that holds on many items. + /// + public partial class Collection { /// - /// An implementation of that holds on many items. + /// An implementation of that holds on to many items which are all activated. /// - public partial class Collection - { + public class AllActive : ConductorBase { + private readonly BindableCollection _items = new(); + private readonly bool _openPublicItems; + + /// + /// Initializes a new instance of the class. + /// + /// if set to true opens public items that are properties of this class. + public AllActive(bool openPublicItems) + : this() + => _openPublicItems = openPublicItems; + /// - /// An implementation of that holds on to many items which are all activated. + /// Initializes a new instance of the class. /// - public class AllActive : ConductorBase - { - private readonly BindableCollection _items = new(); - private readonly bool _openPublicItems; - - /// - /// Initializes a new instance of the class. - /// - /// if set to true opens public items that are properties of this class. - public AllActive(bool openPublicItems) - : this() - => _openPublicItems = openPublicItems; - - /// - /// Initializes a new instance of the class. - /// - public AllActive() - => _items.CollectionChanged += - (s, e) => - { - switch (e.Action) - { - case NotifyCollectionChangedAction.Add: - e.NewItems.OfType().Apply(x => x.Parent = this); - break; - case NotifyCollectionChangedAction.Remove: - e.OldItems.OfType().Apply(x => x.Parent = null); - break; - case NotifyCollectionChangedAction.Replace: - e.NewItems.OfType().Apply(x => x.Parent = this); - e.OldItems.OfType().Apply(x => x.Parent = null); - break; - case NotifyCollectionChangedAction.Reset: - _items.OfType().Apply(x => x.Parent = this); - break; - } - }; - - /// - /// Gets the items that are currently being conducted. - /// - public IObservableCollection Items - => _items; - - /// - /// Called when activating. - /// - protected override Task OnActivateAsync(CancellationToken cancellationToken) - => Task.WhenAll(_items.OfType().Select(x => x.ActivateAsync(cancellationToken))); - - /// - /// Called when deactivating. - /// - /// Indicates whether this instance will be closed. - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation. - protected override async Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) - { - foreach (IDeactivate deactivate in _items.OfType()) - { - await deactivate.DeactivateAsync(close, cancellationToken); + public AllActive() + => _items.CollectionChanged += + (s, e) => { + switch (e.Action) { + case NotifyCollectionChangedAction.Add: + e.NewItems.OfType().Apply(x => x.Parent = this); + break; + case NotifyCollectionChangedAction.Remove: + e.OldItems.OfType().Apply(x => x.Parent = null); + break; + case NotifyCollectionChangedAction.Replace: + e.NewItems.OfType().Apply(x => x.Parent = this); + e.OldItems.OfType().Apply(x => x.Parent = null); + break; + case NotifyCollectionChangedAction.Reset: + _items.OfType().Apply(x => x.Parent = this); + break; } + }; + + /// + /// Gets the items that are currently being conducted. + /// + public IObservableCollection Items + => _items; + + /// + /// Called to check whether or not this instance can close. + /// + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation. + public override async Task CanCloseAsync(CancellationToken cancellationToken = default) { + ICloseResult closeResult = await CloseStrategy.ExecuteAsync(_items.ToList(), cancellationToken); - if (close) - _items.Clear(); + if (closeResult.CloseCanOccur || !closeResult.Children.Any()) { + return closeResult.CloseCanOccur; } - /// - /// Called to check whether or not this instance can close. - /// - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation. - public override async Task CanCloseAsync(CancellationToken cancellationToken = default) - { - ICloseResult closeResult = await CloseStrategy.ExecuteAsync(_items.ToList(), cancellationToken); - - if (closeResult.CloseCanOccur || !closeResult.Children.Any()) - { - return closeResult.CloseCanOccur; - } + foreach (IDeactivate deactivate in closeResult.Children.OfType()) { + await deactivate.DeactivateAsync(true, cancellationToken); + } - foreach (IDeactivate deactivate in closeResult.Children.OfType()) - { - await deactivate.DeactivateAsync(true, cancellationToken); - } + _items.RemoveRange(closeResult.Children); - _items.RemoveRange(closeResult.Children); + return closeResult.CloseCanOccur; + } - return closeResult.CloseCanOccur; + /// + /// Activates the specified item. + /// + /// The item to activate. + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation. + public override async Task ActivateItemAsync(T item, CancellationToken cancellationToken = default) { + if (item == null) { + return; } - /// - /// Called when initializing. - /// - protected override async Task OnInitializeAsync(CancellationToken cancellationToken) - { - if (_openPublicItems) - await Task.WhenAll(GetType().GetRuntimeProperties() - .Where(x => x.Name != "Parent" && typeof(T).GetTypeInfo().IsAssignableFrom(x.PropertyType.GetTypeInfo())) - .Select(x => x.GetValue(this, null)) - .Cast() - .Select(i => ActivateItemAsync(i, cancellationToken))); + item = EnsureItem(item); + + if (IsActive) { + await ScreenExtensions.TryActivateAsync(item, cancellationToken); } - /// - /// Activates the specified item. - /// - /// The item to activate. - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation. - public override async Task ActivateItemAsync(T item, CancellationToken cancellationToken = default) - { - if (item == null) - return; + OnActivationProcessed(item, true); + } + + /// + /// Deactivates the specified item. + /// + /// The item to close. + /// Indicates whether or not to close the item after deactivating it. + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation. + public override async Task DeactivateItemAsync(T item, bool close, CancellationToken cancellationToken = default) { + if (item == null) { + return; + } - item = EnsureItem(item); + if (!close) { + await ScreenExtensions.TryDeactivateAsync(item, false, cancellationToken); - if (IsActive) - await ScreenExtensions.TryActivateAsync(item, cancellationToken); + return; + } - OnActivationProcessed(item, true); + ICloseResult closeResult = await CloseStrategy.ExecuteAsync(new[] { item }, CancellationToken.None); + if (!closeResult.CloseCanOccur) { + return; } - /// - /// Deactivates the specified item. - /// - /// The item to close. - /// Indicates whether or not to close the item after deactivating it. - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation. - public override async Task DeactivateItemAsync(T item, bool close, CancellationToken cancellationToken = default) - { - if (item == null) - return; - - if (!close) - { - await ScreenExtensions.TryDeactivateAsync(item, false, cancellationToken); - - return; - } + await CloseItemCoreAsync(item, cancellationToken); + } - ICloseResult closeResult = await CloseStrategy.ExecuteAsync(new[] { item }, CancellationToken.None); - if (!closeResult.CloseCanOccur) - { - return; - } - - await CloseItemCoreAsync(item, cancellationToken); + /// + /// Gets the children. + /// + /// The collection of children. + public override IEnumerable GetChildren() + => _items; + + /// + /// Called when activating. + /// + protected override Task OnActivateAsync(CancellationToken cancellationToken) + => Task.WhenAll(_items.OfType().Select(x => x.ActivateAsync(cancellationToken))); + + /// + /// Called when deactivating. + /// + /// Indicates whether this instance will be closed. + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation. + protected override async Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) { + foreach (IDeactivate deactivate in _items.OfType()) { + await deactivate.DeactivateAsync(close, cancellationToken); + } + + if (close) { + _items.Clear(); } + } - /// - /// Gets the children. - /// - /// The collection of children. - public override IEnumerable GetChildren() - => _items; - - private async Task CloseItemCoreAsync(T item, CancellationToken cancellationToken = default) - { - await ScreenExtensions.TryDeactivateAsync(item, true, cancellationToken); - _items.Remove(item); + /// + /// Called when initializing. + /// + protected override async Task OnInitializeAsync(CancellationToken cancellationToken) { + if (_openPublicItems) { + await Task.WhenAll(GetType().GetRuntimeProperties() + .Where(x => x.Name != "Parent" && typeof(T).GetTypeInfo().IsAssignableFrom(x.PropertyType.GetTypeInfo())) + .Select(x => x.GetValue(this, null)) + .Cast() + .Select(i => ActivateItemAsync(i, cancellationToken))); } + } - /// - /// Ensures that an item is ready to be activated. - /// - /// The item that is about to be activated. - /// The item to be activated. - protected override T EnsureItem(T newItem) - { - var index = _items.IndexOf(newItem); - - if (index == -1) - _items.Add(newItem); - else - newItem = _items[index]; - - return base.EnsureItem(newItem); + /// + /// Ensures that an item is ready to be activated. + /// + /// The item that is about to be activated. + /// The item to be activated. + protected override T EnsureItem(T newItem) { + int index = _items.IndexOf(newItem); + + if (index == -1) { + _items.Add(newItem); + } else { + newItem = _items[index]; } + + return base.EnsureItem(newItem); + } + + private async Task CloseItemCoreAsync(T item, CancellationToken cancellationToken = default) { + await ScreenExtensions.TryDeactivateAsync(item, true, cancellationToken); + _items.Remove(item); } } } diff --git a/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionOneActive.cs b/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionOneActive.cs index 5b01db099..2441c34d2 100644 --- a/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionOneActive.cs +++ b/src/Caliburn.Micro.Core/Conductor/ConductorWithCollectionOneActive.cs @@ -4,248 +4,219 @@ using System.Threading; using System.Threading.Tasks; -namespace Caliburn.Micro -{ - public partial class Conductor - { +namespace Caliburn.Micro; + +public partial class Conductor { + /// + /// An implementation of that holds on many items. + /// + public partial class Collection { /// - /// An implementation of that holds on many items. + /// An implementation of that holds on many items but only activates one at a time. /// - public partial class Collection - { + public class OneActive : ConductorBaseWithActiveItem { + private readonly BindableCollection _items = new(); + /// - /// An implementation of that holds on many items but only activates one at a time. + /// Initializes a new instance of the class. /// - public class OneActive : ConductorBaseWithActiveItem - { - private readonly BindableCollection _items = new(); - - /// - /// Initializes a new instance of the class. - /// - public OneActive() - => _items.CollectionChanged += - (s, e) => - { - switch (e.Action) - { - case NotifyCollectionChangedAction.Add: - e.NewItems.OfType().Apply(x => x.Parent = this); - break; - case NotifyCollectionChangedAction.Remove: - e.OldItems.OfType().Apply(x => x.Parent = null); - break; - case NotifyCollectionChangedAction.Replace: - e.NewItems.OfType().Apply(x => x.Parent = this); - e.OldItems.OfType().Apply(x => x.Parent = null); - break; - case NotifyCollectionChangedAction.Reset: - _items.OfType().Apply(x => x.Parent = this); - break; - } - }; - - /// - /// Gets the items that are currently being conducted. - /// - public IObservableCollection Items - => _items; - - /// - /// Gets the children. - /// - /// The collection of children. - public override IEnumerable GetChildren() - => _items; - - /// - /// Activates the specified item. - /// - /// The item to activate. - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - /// A task that represents the asynchronous operation. - public override async Task ActivateItemAsync(T item, CancellationToken cancellationToken = default) - { - if (item == null || !item.Equals(ActiveItem)) - { - await ChangeActiveItemAsync(item, false, cancellationToken); - - return; - } - - if (!IsActive) - { - return; - } - - await ScreenExtensions.TryActivateAsync(item, cancellationToken); - OnActivationProcessed(item, true); - } + public OneActive() + => _items.CollectionChanged += + (s, e) => { + switch (e.Action) { + case NotifyCollectionChangedAction.Add: + e.NewItems.OfType().Apply(x => x.Parent = this); + break; + case NotifyCollectionChangedAction.Remove: + e.OldItems.OfType().Apply(x => x.Parent = null); + break; + case NotifyCollectionChangedAction.Replace: + e.NewItems.OfType().Apply(x => x.Parent = this); + e.OldItems.OfType().Apply(x => x.Parent = null); + break; + case NotifyCollectionChangedAction.Reset: + _items.OfType().Apply(x => x.Parent = this); + break; + } + }; + + /// + /// Gets the items that are currently being conducted. + /// + public IObservableCollection Items + => _items; + + /// + /// Gets the children. + /// + /// The collection of children. + public override IEnumerable GetChildren() + => _items; - /// - /// Deactivates the specified item. - /// - /// The item to close. - /// Indicates whether or not to close the item after deactivating it. - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation. - public override async Task DeactivateItemAsync(T item, bool close, CancellationToken cancellationToken = default) - { - if (item == null) - { - return; - } - - if (!close) - { - await ScreenExtensions.TryDeactivateAsync(item, false, cancellationToken); - - return; - } - - ICloseResult closeResult = await CloseStrategy.ExecuteAsync(new[] { item }, CancellationToken.None); - - if (closeResult.CloseCanOccur) - { - await CloseItemCoreAsync(item, cancellationToken); - } + /// + /// Activates the specified item. + /// + /// The item to activate. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A task that represents the asynchronous operation. + public override async Task ActivateItemAsync(T item, CancellationToken cancellationToken = default) { + if (item == null || !item.Equals(ActiveItem)) { + await ChangeActiveItemAsync(item, false, cancellationToken); + + return; } - private async Task CloseItemCoreAsync(T item, CancellationToken cancellationToken = default) - { - if (item.Equals(ActiveItem)) - { - var index = _items.IndexOf(item); - T next = DetermineNextItemToActivate(_items, index); - - await ChangeActiveItemAsync(next, true, cancellationToken); - } - else - { - await ScreenExtensions.TryDeactivateAsync(item, true, cancellationToken); - } - - _items.Remove(item); + if (!IsActive) { + return; } - /// - /// Determines the next item to activate based on the last active index. - /// - /// The list of possible active items. - /// The index of the last active item. - /// The next item to activate. - /// Called after an active item is closed. - protected virtual T DetermineNextItemToActivate(IList list, int lastIndex) - { - var toRemoveAt = lastIndex - 1; + await ScreenExtensions.TryActivateAsync(item, cancellationToken); + OnActivationProcessed(item, true); + } - if (toRemoveAt == -1 && list.Count > 1) - return list[1]; + /// + /// Deactivates the specified item. + /// + /// The item to close. + /// Indicates whether or not to close the item after deactivating it. + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation. + public override async Task DeactivateItemAsync(T item, bool close, CancellationToken cancellationToken = default) { + if (item == null) { + return; + } - if (toRemoveAt > -1 && toRemoveAt < list.Count - 1) - return list[toRemoveAt]; + if (!close) { + await ScreenExtensions.TryDeactivateAsync(item, false, cancellationToken); - return default; + return; } - /// - /// Called to check whether or not this instance can close. - /// - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation. - public override async Task CanCloseAsync(CancellationToken cancellationToken = default) - { - ICloseResult closeResult = await CloseStrategy.ExecuteAsync(_items.ToList(), cancellationToken); - if (closeResult.CloseCanOccur || !closeResult.Children.Any()) - { - return closeResult.CloseCanOccur; - } - - IEnumerable closable = closeResult.Children; - - if (closable.Contains(ActiveItem)) - { - var list = _items.ToList(); - T next = ActiveItem; - do - { - T previous = next; - next = DetermineNextItemToActivate(list, list.IndexOf(previous)); - list.Remove(previous); - } while (closable.Contains(next)); - - T previousActive = ActiveItem; - await ChangeActiveItemAsync(next, true, cancellationToken); - _items.Remove(previousActive); - - var stillToClose = closable.ToList(); - stillToClose.Remove(previousActive); - closable = stillToClose; - } - - foreach (IDeactivate deactivate in closable.OfType()) - { - await deactivate.DeactivateAsync(true, cancellationToken); - } - - _items.RemoveRange(closable); + ICloseResult closeResult = await CloseStrategy.ExecuteAsync(new[] { item }, CancellationToken.None); + + if (closeResult.CloseCanOccur) { + await CloseItemCoreAsync(item, cancellationToken); + } + } + /// + /// Called to check whether or not this instance can close. + /// + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation. + public override async Task CanCloseAsync(CancellationToken cancellationToken = default) { + ICloseResult closeResult = await CloseStrategy.ExecuteAsync(_items.ToList(), cancellationToken); + if (closeResult.CloseCanOccur || !closeResult.Children.Any()) { return closeResult.CloseCanOccur; } - /// - /// Called when activating. - /// - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation. - protected override Task OnActivateAsync(CancellationToken cancellationToken) - => ScreenExtensions.TryActivateAsync(ActiveItem, cancellationToken); - - /// - /// Called when deactivating. - /// - /// Indicates whether this instance will be closed. - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation. - protected override async Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) - { - if (!close) - { - await ScreenExtensions.TryDeactivateAsync(ActiveItem, false, cancellationToken); - - return; - } - - foreach (IDeactivate deactivate in _items.OfType()) - { - await deactivate.DeactivateAsync(true, cancellationToken); - } - - _items.Clear(); + IEnumerable closable = closeResult.Children; + + if (closable.Contains(ActiveItem)) { + var list = _items.ToList(); + T next = ActiveItem; + do { + T previous = next; + next = DetermineNextItemToActivate(list, list.IndexOf(previous)); + list.Remove(previous); + } while (closable.Contains(next)); + + T previousActive = ActiveItem; + await ChangeActiveItemAsync(next, true, cancellationToken); + _items.Remove(previousActive); + + var stillToClose = closable.ToList(); + stillToClose.Remove(previousActive); + closable = stillToClose; + } + + foreach (IDeactivate deactivate in closable.OfType()) { + await deactivate.DeactivateAsync(true, cancellationToken); } - /// - /// Ensures that an item is ready to be activated. - /// - /// The item that is about to be activated. - /// The item to be activated. - protected override T EnsureItem(T newItem) - { - if (newItem == null) - { - newItem = DetermineNextItemToActivate(_items, ActiveItem != null ? _items.IndexOf(ActiveItem) : 0); - - return base.EnsureItem(newItem); - } - - var index = _items.IndexOf(newItem); - if (index == -1) - _items.Add(newItem); - else - newItem = _items[index]; + _items.RemoveRange(closable); + + return closeResult.CloseCanOccur; + } + + /// + /// Called when activating. + /// + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation. + protected override Task OnActivateAsync(CancellationToken cancellationToken) + => ScreenExtensions.TryActivateAsync(ActiveItem, cancellationToken); + + /// + /// Called when deactivating. + /// + /// Indicates whether this instance will be closed. + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation. + protected override async Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) { + if (!close) { + await ScreenExtensions.TryDeactivateAsync(ActiveItem, false, cancellationToken); + + return; + } + + foreach (IDeactivate deactivate in _items.OfType()) { + await deactivate.DeactivateAsync(true, cancellationToken); + } + + _items.Clear(); + } + + /// + /// Ensures that an item is ready to be activated. + /// + /// The item that is about to be activated. + /// The item to be activated. + protected override T EnsureItem(T newItem) { + if (newItem == null) { + newItem = DetermineNextItemToActivate(_items, ActiveItem != null ? _items.IndexOf(ActiveItem) : 0); return base.EnsureItem(newItem); } + + int index = _items.IndexOf(newItem); + if (index == -1) { + _items.Add(newItem); + } else { + newItem = _items[index]; + } + + return base.EnsureItem(newItem); + } + + /// + /// Determines the next item to activate based on the last active index. + /// + /// The list of possible active items. + /// The index of the last active item. + /// The next item to activate. + /// Called after an active item is closed. + protected virtual T DetermineNextItemToActivate(IList list, int lastIndex) { + int toRemoveAt = lastIndex - 1; + + return toRemoveAt == -1 && list.Count > 1 + ? list[1] + : toRemoveAt > -1 && toRemoveAt < list.Count - 1 + ? list[toRemoveAt] + : default; + } + + private async Task CloseItemCoreAsync(T item, CancellationToken cancellationToken = default) { + if (item.Equals(ActiveItem)) { + int index = _items.IndexOf(item); + T next = DetermineNextItemToActivate(_items, index); + + await ChangeActiveItemAsync(next, true, cancellationToken); + } else { + await ScreenExtensions.TryDeactivateAsync(item, true, cancellationToken); + } + + _items.Remove(item); } } } diff --git a/src/Caliburn.Micro.Core/Conductor/Contracts/ICloseResult.cs b/src/Caliburn.Micro.Core/Conductor/Contracts/ICloseResult.cs index c165b4a81..99ebe9396 100644 --- a/src/Caliburn.Micro.Core/Conductor/Contracts/ICloseResult.cs +++ b/src/Caliburn.Micro.Core/Conductor/Contracts/ICloseResult.cs @@ -1,20 +1,18 @@ using System.Collections.Generic; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Results from the close strategy. +/// +public interface ICloseResult { /// - /// Results from the close strategy. + /// Indicates which children shbould close if the parent cannot. /// - public interface ICloseResult - { - /// - /// Indicates which children shbould close if the parent cannot. - /// - IEnumerable Children { get; } + IEnumerable Children { get; } - /// - /// Indicates whether a close can occur - /// - bool CloseCanOccur { get; } - } + /// + /// Indicates whether a close can occur. + /// + bool CloseCanOccur { get; } } diff --git a/src/Caliburn.Micro.Core/Conductor/Contracts/ICloseStrategy.cs b/src/Caliburn.Micro.Core/Conductor/Contracts/ICloseStrategy.cs index 4d365d0ad..ee29f34da 100644 --- a/src/Caliburn.Micro.Core/Conductor/Contracts/ICloseStrategy.cs +++ b/src/Caliburn.Micro.Core/Conductor/Contracts/ICloseStrategy.cs @@ -3,20 +3,18 @@ using System.Threading; using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Used to gather the results from multiple child elements which may or may not prevent closing. +/// +/// The type of child element. +public interface ICloseStrategy { /// - /// Used to gather the results from multiple child elements which may or may not prevent closing. + /// Executes the strategy. /// - /// The type of child element. - public interface ICloseStrategy - { - /// - /// Executes the strategy. - /// - /// Items that are requesting close. - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation and contains the result of the strategy. - Task> ExecuteAsync(IEnumerable toClose, CancellationToken cancellationToken = default); - } + /// Items that are requesting close. + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation and contains the result of the strategy. + Task> ExecuteAsync(IEnumerable toClose, CancellationToken cancellationToken = default); } diff --git a/src/Caliburn.Micro.Core/Conductor/Contracts/IConductActiveItem.cs b/src/Caliburn.Micro.Core/Conductor/Contracts/IConductActiveItem.cs index 8b3f6d40d..f672e5ffa 100644 --- a/src/Caliburn.Micro.Core/Conductor/Contracts/IConductActiveItem.cs +++ b/src/Caliburn.Micro.Core/Conductor/Contracts/IConductActiveItem.cs @@ -2,12 +2,10 @@ using System.Threading; using System.Threading.Tasks; -namespace Caliburn.Micro -{ - /// - /// An that also implements . - /// - public interface IConductActiveItem : IConductor, IHaveActiveItem - { - } +namespace Caliburn.Micro; + +/// +/// An that also implements . +/// +public interface IConductActiveItem : IConductor, IHaveActiveItem { } diff --git a/src/Caliburn.Micro.Core/Conductor/Contracts/IConductor.cs b/src/Caliburn.Micro.Core/Conductor/Contracts/IConductor.cs index 356ecc534..e2d6867d0 100644 --- a/src/Caliburn.Micro.Core/Conductor/Contracts/IConductor.cs +++ b/src/Caliburn.Micro.Core/Conductor/Contracts/IConductor.cs @@ -2,33 +2,31 @@ using System.Threading; using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Denotes an instance which conducts other objects by managing an ActiveItem and maintaining a strict lifecycle. +/// +/// Conducted instances can optin to the lifecycle by impelenting any of the follosing , , . +public interface IConductor : IParent, INotifyPropertyChangedEx { /// - /// Denotes an instance which conducts other objects by managing an ActiveItem and maintaining a strict lifecycle. + /// Occurs when an activation request is processed. /// - /// Conducted instances can optin to the lifecycle by impelenting any of the follosing , , . - public interface IConductor : IParent, INotifyPropertyChangedEx - { - /// - /// Activates the specified item. - /// - /// The item to activate. - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - Task ActivateItemAsync(object item, CancellationToken cancellationToken = default); + event EventHandler ActivationProcessed; - /// - /// Deactivates the specified item. - /// - /// The item to close. - /// Indicates whether or not to close the item after deactivating it. - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation. - Task DeactivateItemAsync(object item, bool close, CancellationToken cancellationToken = default); + /// + /// Activates the specified item. + /// + /// The item to activate. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + Task ActivateItemAsync(object item, CancellationToken cancellationToken = default); - /// - /// Occurs when an activation request is processed. - /// - event EventHandler ActivationProcessed; - } + /// + /// Deactivates the specified item. + /// + /// The item to close. + /// Indicates whether or not to close the item after deactivating it. + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation. + Task DeactivateItemAsync(object item, bool close, CancellationToken cancellationToken = default); } diff --git a/src/Caliburn.Micro.Core/Conductor/Contracts/IHaveActiveItem.cs b/src/Caliburn.Micro.Core/Conductor/Contracts/IHaveActiveItem.cs index 468811b82..d9a0195fb 100644 --- a/src/Caliburn.Micro.Core/Conductor/Contracts/IHaveActiveItem.cs +++ b/src/Caliburn.Micro.Core/Conductor/Contracts/IHaveActiveItem.cs @@ -1,13 +1,11 @@ -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Denotes an instance which maintains an active item. +/// +public interface IHaveActiveItem { /// - /// Denotes an instance which maintains an active item. + /// The currently active item. /// - public interface IHaveActiveItem - { - /// - /// The currently active item. - /// - object ActiveItem { get; set; } - } + object ActiveItem { get; set; } } diff --git a/src/Caliburn.Micro.Core/Conductor/Contracts/IParent.cs b/src/Caliburn.Micro.Core/Conductor/Contracts/IParent.cs index 9c2af28ac..f04815bf9 100644 --- a/src/Caliburn.Micro.Core/Conductor/Contracts/IParent.cs +++ b/src/Caliburn.Micro.Core/Conductor/Contracts/IParent.cs @@ -1,19 +1,17 @@ using System.Collections; using System.Collections.Generic; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Interface used to define an object associated to a collection of children. +/// +public interface IParent { /// - /// Interface used to define an object associated to a collection of children. + /// Gets the children. /// - public interface IParent - { - /// - /// Gets the children. - /// - /// - /// The collection of children. - /// - IEnumerable GetChildren(); - } + /// + /// The collection of children. + /// + IEnumerable GetChildren(); } diff --git a/src/Caliburn.Micro.Core/Conductor/Contracts/IParent{T}.cs b/src/Caliburn.Micro.Core/Conductor/Contracts/IParent{T}.cs index 0ce0ce5a1..200768874 100644 --- a/src/Caliburn.Micro.Core/Conductor/Contracts/IParent{T}.cs +++ b/src/Caliburn.Micro.Core/Conductor/Contracts/IParent{T}.cs @@ -1,20 +1,18 @@ using System.Collections; using System.Collections.Generic; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Interface used to define a specialized parent. +/// +/// The type of children. +public interface IParent : IParent { /// - /// Interface used to define a specialized parent. + /// Gets the children. /// - /// The type of children. - public interface IParent : IParent - { - /// - /// Gets the children. - /// - /// - /// The collection of children. - /// - new IEnumerable GetChildren(); - } + /// + /// The collection of children. + /// + new IEnumerable GetChildren(); } diff --git a/src/Caliburn.Micro.Core/Conductor/DefaultImpl/CloseResult.cs b/src/Caliburn.Micro.Core/Conductor/DefaultImpl/CloseResult.cs index 7897860d5..7257395f9 100644 --- a/src/Caliburn.Micro.Core/Conductor/DefaultImpl/CloseResult.cs +++ b/src/Caliburn.Micro.Core/Conductor/DefaultImpl/CloseResult.cs @@ -1,32 +1,29 @@ using System.Collections.Generic; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// The result of a test whether an instance can be closed. +/// +/// The type of the children of the instance. +public class CloseResult : ICloseResult { /// - /// The result of a test whether an instance can be closed. + /// Initializes a new instance of the class. /// - /// The type of the children of the instance. - public class CloseResult : ICloseResult - { - /// - /// Creates an instance of the - /// - /// Whether of not a close operation should occur. - /// The children of the instance that can be closed. - public CloseResult(bool closeCanOccur, IEnumerable children) - { - CloseCanOccur = closeCanOccur; - Children = children; - } - - /// - /// Whether of not a close operation should occur. - /// - public bool CloseCanOccur { get; } - - /// - /// The children of the instance that can be closed. - /// - public IEnumerable Children { get; } + /// Whether of not a close operation should occur. + /// The children of the instance that can be closed. + public CloseResult(bool closeCanOccur, IEnumerable children) { + CloseCanOccur = closeCanOccur; + Children = children; } + + /// + /// Gets a value indicating whether or not a close operation should occur. + /// + public bool CloseCanOccur { get; } + + /// + /// Gets the children of the instance that can be closed. + /// + public IEnumerable Children { get; } } diff --git a/src/Caliburn.Micro.Core/Conductor/DefaultImpl/DefaultCloseStrategy.cs b/src/Caliburn.Micro.Core/Conductor/DefaultImpl/DefaultCloseStrategy.cs index 4d15e09f0..aacd84f22 100644 --- a/src/Caliburn.Micro.Core/Conductor/DefaultImpl/DefaultCloseStrategy.cs +++ b/src/Caliburn.Micro.Core/Conductor/DefaultImpl/DefaultCloseStrategy.cs @@ -2,52 +2,44 @@ using System.Threading; using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Used to gather the results from multiple child elements which may or may not prevent closing. +/// +/// The type of child element. +public class DefaultCloseStrategy : ICloseStrategy { + private readonly bool _closeConductedItemsWhenConductorCannotClose; + /// - /// Used to gather the results from multiple child elements which may or may not prevent closing. + /// Initializes a new instance of the class. /// - /// The type of child element. - public class DefaultCloseStrategy : ICloseStrategy - { - readonly bool _closeConductedItemsWhenConductorCannotClose; - - /// - /// Creates an instance of the class. - /// - /// Indicates that even if all conducted items are not closable, those that are should be closed. The default is FALSE. - public DefaultCloseStrategy(bool closeConductedItemsWhenConductorCannotClose = false) - => _closeConductedItemsWhenConductorCannotClose = closeConductedItemsWhenConductorCannotClose; - - /// - public async Task> ExecuteAsync(IEnumerable toClose, CancellationToken cancellationToken = default) - { - var closeable = new List(); - var closeCanOccur = true; - foreach (T child in toClose) - { - if (child is not IGuardClose guard) - { - closeable.Add(child); - continue; - } - - - var canClose = await guard.CanCloseAsync(cancellationToken); - if (canClose) - { - closeable.Add(child); - } - - closeCanOccur = closeCanOccur && canClose; + /// Indicates that even if all conducted items are not closable, those that are should be closed. The default is FALSE. + public DefaultCloseStrategy(bool closeConductedItemsWhenConductorCannotClose = false) + => _closeConductedItemsWhenConductorCannotClose = closeConductedItemsWhenConductorCannotClose; + + /// + public async Task> ExecuteAsync(IEnumerable toClose, CancellationToken cancellationToken = default) { + var closeable = new List(); + bool closeCanOccur = true; + foreach (T child in toClose) { + if (child is not IGuardClose guard) { + closeable.Add(child); + continue; } - if (!_closeConductedItemsWhenConductorCannotClose && !closeCanOccur) - { - closeable.Clear(); + bool canClose = await guard.CanCloseAsync(cancellationToken); + if (canClose) { + closeable.Add(child); } - return new CloseResult(closeCanOccur, closeable); + closeCanOccur = closeCanOccur && canClose; } + + if (!_closeConductedItemsWhenConductorCannotClose && !closeCanOccur) { + closeable.Clear(); + } + + return new CloseResult(closeCanOccur, closeable); } } diff --git a/src/Caliburn.Micro.Core/Conductor/EventArgs/ActivationProcessedEventArgs.cs b/src/Caliburn.Micro.Core/Conductor/EventArgs/ActivationProcessedEventArgs.cs index 8e9fac7ae..441aa5341 100644 --- a/src/Caliburn.Micro.Core/Conductor/EventArgs/ActivationProcessedEventArgs.cs +++ b/src/Caliburn.Micro.Core/Conductor/EventArgs/ActivationProcessedEventArgs.cs @@ -1,21 +1,19 @@ using System; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Contains details about the success or failure of an item's activation through an . +/// +public class ActivationProcessedEventArgs : EventArgs { /// - /// Contains details about the success or failure of an item's activation through an . + /// The item whose activation was processed. /// - public class ActivationProcessedEventArgs : EventArgs - { - /// - /// The item whose activation was processed. - /// - public object Item { get; set; } + public object Item { get; set; } - /// - /// Gets or sets a value indicating whether the activation was a success. - /// - /// true if success; otherwise, false. - public bool Success { get; set; } - } + /// + /// Gets or sets a value indicating whether the activation was a success. + /// + /// true if success; otherwise, false. + public bool Success { get; set; } } diff --git a/src/Caliburn.Micro.Core/Conductor/Extensions/ConductorExtensions.cs b/src/Caliburn.Micro.Core/Conductor/Extensions/ConductorExtensions.cs index 2e439b482..3cc9b0dae 100644 --- a/src/Caliburn.Micro.Core/Conductor/Extensions/ConductorExtensions.cs +++ b/src/Caliburn.Micro.Core/Conductor/Extensions/ConductorExtensions.cs @@ -1,20 +1,18 @@ using System.Threading; using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Extension methods for the instance. +/// +public static class ConductorExtensions { /// - /// Extension methods for the instance. + /// Activates the specified item. /// - public static class ConductorExtensions - { - /// - /// Activates the specified item. - /// - /// The conductor to activate the item with. - /// The item to activate. - /// A task that represents the asynchronous operation. - public static Task ActivateItemAsync(this IConductor conductor, object item) - => conductor.ActivateItemAsync(item, default); - } + /// The conductor to activate the item with. + /// The item to activate. + /// A task that represents the asynchronous operation. + public static Task ActivateItemAsync(this IConductor conductor, object item) + => conductor.ActivateItemAsync(item, default); } diff --git a/src/Caliburn.Micro.Core/Coroutine/ExtensionPoints/Coroutine.cs b/src/Caliburn.Micro.Core/Coroutine/ExtensionPoints/Coroutine.cs index 992d112bb..3ae5c1191 100644 --- a/src/Caliburn.Micro.Core/Coroutine/ExtensionPoints/Coroutine.cs +++ b/src/Caliburn.Micro.Core/Coroutine/ExtensionPoints/Coroutine.cs @@ -2,118 +2,105 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Manages coroutine execution. +/// +public static class Coroutine { + private static readonly ILog Log + = LogManager.GetLog(typeof(Coroutine)); + /// - /// Manages coroutine execution. + /// Called upon completion of a coroutine. /// - public static class Coroutine - { - private static readonly ILog Log - = LogManager.GetLog(typeof(Coroutine)); - - /// - /// Creates the parent enumerator. - /// - public static Func, IResult> CreateParentEnumerator { get; set; } - = inner => new SequentialResult(inner); - - /// - /// Executes a coroutine. - /// - /// The coroutine to execute. - /// The context to execute the coroutine within. - /// /// The completion callback for the coroutine. - public static void BeginExecute( - IEnumerator coroutine, - CoroutineExecutionContext context = null, - EventHandler callback = null) - { - Log.Info("Executing coroutine."); - - IResult enumerator = CreateParentEnumerator(coroutine); - IoC.BuildUp(enumerator); - - if (callback != null) - { - ExecuteOnCompleted(enumerator, callback); - } + public static event EventHandler Completed + = (s, e) => { + if (e.Error != null) { + Log.Error(e.Error); - ExecuteOnCompleted(enumerator, Completed); - enumerator.Execute(context ?? new CoroutineExecutionContext()); - } + return; + } - /// - /// Executes a coroutine asynchronous. - /// - /// The coroutine to execute. - /// The context to execute the coroutine within. - /// A task that represents the asynchronous coroutine. - public static Task ExecuteAsync( - IEnumerator coroutine, - CoroutineExecutionContext context = null) - { - var taskSource = new TaskCompletionSource(); - - BeginExecute( - coroutine, - context, - (s, e) => - { - if (e.Error != null) - { - taskSource.SetException(e.Error); - - return; - } - - if (e.WasCancelled) - { - taskSource.SetCanceled(); - - return; - } - - taskSource.SetResult(null); - }); - - return taskSource.Task; - } + if (e.WasCancelled) { + Log.Info("Coroutine execution cancelled."); - private static void ExecuteOnCompleted( - IResult result, - EventHandler handler) - { - void OnCompledted(object s, ResultCompletionEventArgs e) - { - result.Completed -= OnCompledted; - handler(s, e); + return; } - result.Completed += OnCompledted; + Log.Info("Coroutine execution completed."); + }; + + /// + /// Gets or sets func to create the parent enumerator. + /// + public static Func, IResult> CreateParentEnumerator { get; set; } + = inner => new SequentialResult(inner); + + /// + /// Executes a coroutine. + /// + /// The coroutine to execute. + /// The context to execute the coroutine within. + /// /// The completion callback for the coroutine. + public static void BeginExecute( + IEnumerator coroutine, + CoroutineExecutionContext context = null, + EventHandler callback = null) { + Log.Info("Executing coroutine."); + + IResult enumerator = CreateParentEnumerator(coroutine); + IoC.BuildUp(enumerator); + + if (callback != null) { + ExecuteOnCompleted(enumerator, callback); } - /// - /// Called upon completion of a coroutine. - /// - public static event EventHandler Completed - = (s, e) => - { - if (e.Error != null) - { - Log.Error(e.Error); + ExecuteOnCompleted(enumerator, Completed); + enumerator.Execute(context ?? new CoroutineExecutionContext()); + } + + /// + /// Executes a coroutine asynchronous. + /// + /// The coroutine to execute. + /// The context to execute the coroutine within. + /// A task that represents the asynchronous coroutine. + public static Task ExecuteAsync( + IEnumerator coroutine, + CoroutineExecutionContext context = null) { + var taskSource = new TaskCompletionSource(); + + BeginExecute( + coroutine, + context, + (s, e) => { + if (e.Error != null) { + taskSource.SetException(e.Error); return; } - if (e.WasCancelled) - { - Log.Info("Coroutine execution cancelled."); + if (e.WasCancelled) { + taskSource.SetCanceled(); return; } - Log.Info("Coroutine execution completed."); - }; + taskSource.SetResult(null); + }); + + return taskSource.Task; + } + + private static void ExecuteOnCompleted( + IResult result, + EventHandler handler) { + void OnCompledted(object s, ResultCompletionEventArgs e) { + result.Completed -= OnCompledted; + handler(s, e); + } + + result.Completed += OnCompledted; } } diff --git a/src/Caliburn.Micro.Core/Coroutine/Models/CoroutineExecutionContext.cs b/src/Caliburn.Micro.Core/Coroutine/Models/CoroutineExecutionContext.cs index 9d3ae3af5..9f4df928a 100644 --- a/src/Caliburn.Micro.Core/Coroutine/Models/CoroutineExecutionContext.cs +++ b/src/Caliburn.Micro.Core/Coroutine/Models/CoroutineExecutionContext.cs @@ -1,23 +1,21 @@ -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// The context used during the execution of a Coroutine. +/// +public class CoroutineExecutionContext { /// - /// The context used during the execution of a Coroutine. + /// The source from which the message originates. /// - public class CoroutineExecutionContext - { - /// - /// The source from which the message originates. - /// - public object Source { get; set; } + public object Source { get; set; } - /// - /// The view associated with the target. - /// - public object View { get; set; } + /// + /// The view associated with the target. + /// + public object View { get; set; } - /// - /// The instance on which the action is invoked. - /// - public object Target { get; set; } - } + /// + /// The instance on which the action is invoked. + /// + public object Target { get; set; } } diff --git a/src/Caliburn.Micro.Core/EventAggregator/Contracts/IEventAggregator.cs b/src/Caliburn.Micro.Core/EventAggregator/Contracts/IEventAggregator.cs index 832cbda92..564a7757d 100644 --- a/src/Caliburn.Micro.Core/EventAggregator/Contracts/IEventAggregator.cs +++ b/src/Caliburn.Micro.Core/EventAggregator/Contracts/IEventAggregator.cs @@ -2,41 +2,39 @@ using System.Threading; using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Enables loosely-coupled publication of and subscription to events. +/// +public interface IEventAggregator { /// - /// Enables loosely-coupled publication of and subscription to events. + /// Searches the subscribed handlers to check if we have a handler for + /// the message type supplied. /// - public interface IEventAggregator - { - /// - /// Searches the subscribed handlers to check if we have a handler for - /// the message type supplied. - /// - /// The message type to check with - /// True if any handler is found, false if not. - bool HandlerExistsFor(Type messageType); + /// The message type to check with. + /// True if any handler is found, false if not. + bool HandlerExistsFor(Type messageType); - /// - /// Subscribes an instance to all events declared through implementations of - /// - /// The instance to subscribe for event publication. - /// Allows the subscriber to provide a custom thread marshaller for the message subscription. - void Subscribe(object subscriber, Func, Task> marshal); + /// + /// Subscribes an instance to all events declared through implementations of . + /// + /// The instance to subscribe for event publication. + /// Allows the subscriber to provide a custom thread marshaller for the message subscription. + void Subscribe(object subscriber, Func, Task> marshal); - /// - /// Unsubscribes the instance from all events. - /// - /// The instance to unsubscribe. - void Unsubscribe(object subscriber); + /// + /// Unsubscribes the instance from all events. + /// + /// The instance to unsubscribe. + void Unsubscribe(object subscriber); - /// - /// Publishes a message. - /// - /// The message instance. - /// Allows the publisher to provide a custom thread marshaller for the message publication. - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation. - Task PublishAsync(object message, Func, Task> marshal, CancellationToken cancellationToken = default); - } + /// + /// Publishes a message. + /// + /// The message instance. + /// Allows the publisher to provide a custom thread marshaller for the message publication. + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation. + Task PublishAsync(object message, Func, Task> marshal, CancellationToken cancellationToken = default); } diff --git a/src/Caliburn.Micro.Core/EventAggregator/Contracts/IHandle.cs b/src/Caliburn.Micro.Core/EventAggregator/Contracts/IHandle.cs index 281705708..311dccf5b 100644 --- a/src/Caliburn.Micro.Core/EventAggregator/Contracts/IHandle.cs +++ b/src/Caliburn.Micro.Core/EventAggregator/Contracts/IHandle.cs @@ -1,21 +1,19 @@ using System.Threading; using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Denotes a class which can handle a particular type of message. +/// +/// The type of message to handle. +// ReSharper disable once TypeParameterCanBeVariant +public interface IHandle { /// - /// Denotes a class which can handle a particular type of message. + /// Handles the message. /// - /// The type of message to handle. - // ReSharper disable once TypeParameterCanBeVariant - public interface IHandle - { - /// - /// Handles the message. - /// - /// The message. - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - /// A task that represents the asynchronous coroutine. - Task HandleAsync(TMessage message, CancellationToken cancellationToken); - } + /// The message. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A task that represents the asynchronous coroutine. + Task HandleAsync(TMessage message, CancellationToken cancellationToken); } diff --git a/src/Caliburn.Micro.Core/EventAggregator/EventAggregator.cs b/src/Caliburn.Micro.Core/EventAggregator/EventAggregator.cs index 567dd14b5..9fbc59d49 100644 --- a/src/Caliburn.Micro.Core/EventAggregator/EventAggregator.cs +++ b/src/Caliburn.Micro.Core/EventAggregator/EventAggregator.cs @@ -5,154 +5,126 @@ using System.Threading; using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +public class EventAggregator : IEventAggregator { + private readonly List _handlers = new(); + /// - public class EventAggregator : IEventAggregator - { - private readonly List _handlers = new(); - - /// - public virtual bool HandlerExistsFor(Type messageType) - { - lock (_handlers) - { - return _handlers.Any(handler => handler.Handles(messageType) && !handler.IsDead); - } + public virtual bool HandlerExistsFor(Type messageType) { + lock (_handlers) { + return _handlers.Any(handler => handler.Handles(messageType) && !handler.IsDead); } + } - /// - public virtual void Subscribe(object subscriber, Func, Task> marshal) - { - if (subscriber == null) - { - throw new ArgumentNullException(nameof(subscriber)); - } - - if (marshal == null) - { - throw new ArgumentNullException(nameof(marshal)); - } + /// + public virtual void Subscribe(object subscriber, Func, Task> marshal) { + if (subscriber == null) { + throw new ArgumentNullException(nameof(subscriber)); + } - lock (_handlers) - { - if (_handlers.Any(x => x.Matches(subscriber))) - { - return; - } + if (marshal == null) { + throw new ArgumentNullException(nameof(marshal)); + } - _handlers.Add(new Handler(subscriber, marshal)); + lock (_handlers) { + if (_handlers.Any(x => x.Matches(subscriber))) { + return; } + + _handlers.Add(new Handler(subscriber, marshal)); } + } - /// - public virtual void Unsubscribe(object subscriber) - { - if (subscriber == null) - { - throw new ArgumentNullException(nameof(subscriber)); - } + /// + public virtual void Unsubscribe(object subscriber) { + if (subscriber == null) { + throw new ArgumentNullException(nameof(subscriber)); + } - lock (_handlers) - { - Handler found = _handlers.FirstOrDefault(x => x.Matches(subscriber)); - if (found != null) - { - _handlers.Remove(found); - } + lock (_handlers) { + Handler found = _handlers.FirstOrDefault(x => x.Matches(subscriber)); + if (found != null) { + _handlers.Remove(found); } } + } - /// - public virtual Task PublishAsync(object message, Func, Task> marshal, CancellationToken cancellationToken = default) - { - if (message == null) - { - throw new ArgumentNullException(nameof(message)); - } + /// + public virtual Task PublishAsync(object message, Func, Task> marshal, CancellationToken cancellationToken = default) { + if (message == null) { + throw new ArgumentNullException(nameof(message)); + } - if (marshal == null) - { - throw new ArgumentNullException(nameof(marshal)); - } + if (marshal == null) { + throw new ArgumentNullException(nameof(marshal)); + } - Handler[] toNotify; + Handler[] toNotify; - lock (_handlers) - { - toNotify = _handlers.ToArray(); - } + lock (_handlers) { + toNotify = _handlers.ToArray(); + } - return marshal(async () => - { - Type messageType = message.GetType(); + return marshal(async () => { + Type messageType = message.GetType(); - IEnumerable tasks = toNotify.Select(h => h.Handle(messageType, message, cancellationToken)); + IEnumerable tasks = toNotify.Select(h => h.Handle(messageType, message, cancellationToken)); - await Task.WhenAll(tasks); + await Task.WhenAll(tasks); - var dead = toNotify.Where(h => h.IsDead).ToList(); + var dead = toNotify.Where(h => h.IsDead).ToList(); - if (dead.Any()) - { - lock (_handlers) - { - dead.Apply(x => _handlers.Remove(x)); - } + if (dead.Any()) { + lock (_handlers) { + dead.Apply(x => _handlers.Remove(x)); } - }); - } + } + }); + } - private sealed class Handler - { - private readonly Func, Task> _marshal; - private readonly WeakReference _reference; - private readonly Dictionary _supportedHandlers = new(); - - public Handler(object handler, Func, Task> marshal) - { - _marshal = marshal; - _reference = new WeakReference(handler); - - //var interfaces = handler.GetType().GetTypeInfo().ImplementedInterfaces - // .Where(x => typeof(IHandle).GetTypeInfo().IsAssignableFrom(x.GetTypeInfo()) && x.GetTypeInfo().IsGenericType); - - IEnumerable interfaces - = handler - .GetType() - .GetTypeInfo().ImplementedInterfaces - .Where(x => x.GetTypeInfo().IsGenericType && - x.GetGenericTypeDefinition() == typeof(IHandle<>)); - foreach (Type @interface in interfaces) - { - Type type = @interface.GetTypeInfo().GenericTypeArguments[0]; - MethodInfo method = @interface.GetRuntimeMethod("HandleAsync", new[] { type, typeof(CancellationToken) }); - if (method == null) - { - continue; - } - - _supportedHandlers[type] = method; + private sealed class Handler { + private readonly Func, Task> _marshal; + private readonly WeakReference _reference; + private readonly Dictionary _supportedHandlers = new(); + + public Handler(object handler, Func, Task> marshal) { + _marshal = marshal; + _reference = new WeakReference(handler); + + IEnumerable interfaces + = handler + .GetType() + .GetTypeInfo().ImplementedInterfaces + .Where(x => x.GetTypeInfo().IsGenericType && + x.GetGenericTypeDefinition() == typeof(IHandle<>)); + foreach (Type @interface in interfaces) { + Type type = @interface.GetTypeInfo().GenericTypeArguments[0]; + MethodInfo method = @interface.GetRuntimeMethod("HandleAsync", new[] { type, typeof(CancellationToken) }); + if (method == null) { + continue; } + + _supportedHandlers[type] = method; } + } - public bool IsDead - => _reference.Target == null; + public bool IsDead + => _reference.Target == null; - public bool Matches(object instance) - => _reference.Target == instance; + public bool Matches(object instance) + => _reference.Target == instance; - public Task Handle(Type messageType, object message, CancellationToken cancellationToken) - { - var target = _reference.Target; + public bool Handles(Type messageType) + => _supportedHandlers.Any(pair => pair.Key.GetTypeInfo().IsAssignableFrom(messageType.GetTypeInfo())); - if (target == null) - { - return Task.FromResult(false); - } + public Task Handle(Type messageType, object message, CancellationToken cancellationToken) { + object target = _reference.Target; - return _marshal(() => - { + return target == null + ? Task.FromResult(false) + : _marshal(() => { var tasks = _supportedHandlers .Where(handler => handler.Key.GetTypeInfo().IsAssignableFrom(messageType.GetTypeInfo())) .Select(pair => pair.Value.Invoke(target, new[] { message, cancellationToken })) @@ -161,10 +133,6 @@ public Task Handle(Type messageType, object message, CancellationToken cancellat return Task.WhenAll(tasks); }); - } - - public bool Handles(Type messageType) - => _supportedHandlers.Any(pair => pair.Key.GetTypeInfo().IsAssignableFrom(messageType.GetTypeInfo())); } } } diff --git a/src/Caliburn.Micro.Core/EventAggregator/Extensions/EventAggregatorExtensions.cs b/src/Caliburn.Micro.Core/EventAggregator/Extensions/EventAggregatorExtensions.cs index 5d8b8df4d..50263bb3d 100644 --- a/src/Caliburn.Micro.Core/EventAggregator/Extensions/EventAggregatorExtensions.cs +++ b/src/Caliburn.Micro.Core/EventAggregator/Extensions/EventAggregatorExtensions.cs @@ -2,155 +2,134 @@ using System.Threading; using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Extensions for . +/// +public static class EventAggregatorExtensions { /// - /// Extensions for . + /// Subscribes an instance to all events declared through implementations of . /// - public static class EventAggregatorExtensions - { - /// - /// Subscribes an instance to all events declared through implementations of . - /// - /// The subscription is invoked on the thread chosen by the publisher. - /// - /// The instance to subscribe for event publication. - public static void SubscribeOnPublishedThread(this IEventAggregator eventAggregator, object subscriber) - => eventAggregator.Subscribe(subscriber, f => f()); - - /// - /// Subscribes an instance to all events declared through implementations of . - /// - /// The subscription is invoked on the thread chosen by the publisher. - /// - /// The instance to subscribe for event publication. - [Obsolete("Use SubscribeOnPublishedThread")] - public static void Subscribe(this IEventAggregator eventAggregator, object subscriber) - => eventAggregator.SubscribeOnPublishedThread(subscriber); - - /// - /// Subscribes an instance to all events declared through implementations of . - /// - /// The subscription is invoked on a new background thread. - /// - /// The instance to subscribe for event publication. - public static void SubscribeOnBackgroundThread(this IEventAggregator eventAggregator, object subscriber) - => eventAggregator.Subscribe(subscriber, f => Task.Factory.StartNew(f, default, TaskCreationOptions.None, TaskScheduler.Default)); + /// The subscription is invoked on the thread chosen by the publisher. + /// The instance to subscribe for event publication. + public static void SubscribeOnPublishedThread(this IEventAggregator eventAggregator, object subscriber) + => eventAggregator.Subscribe(subscriber, f => f()); - /// - /// Subscribes an instance to all events declared through implementations of . - /// - /// The subscription is invoked on the UI thread. - /// - /// The instance to subscribe for event publication. - public static void SubscribeOnUIThread(this IEventAggregator eventAggregator, object subscriber) - => eventAggregator.Subscribe( - subscriber, - f => - { - var taskCompletionSource = new TaskCompletionSource(); - Execute.BeginOnUIThread(async () => - { - try - { - await f(); - - taskCompletionSource.SetResult(true); - } - catch (OperationCanceledException) - { - taskCompletionSource.SetCanceled(); - } - catch (Exception ex) - { - taskCompletionSource.SetException(ex); - } - }); + /// + /// Subscribes an instance to all events declared through implementations of . + /// + /// The subscription is invoked on the thread chosen by the publisher. + /// The instance to subscribe for event publication. + [Obsolete("Use SubscribeOnPublishedThread")] + public static void Subscribe(this IEventAggregator eventAggregator, object subscriber) + => eventAggregator.SubscribeOnPublishedThread(subscriber); - return taskCompletionSource.Task; + /// + /// Subscribes an instance to all events declared through implementations of . + /// + /// The subscription is invoked on a new background thread. + /// The instance to subscribe for event publication. + public static void SubscribeOnBackgroundThread(this IEventAggregator eventAggregator, object subscriber) + => eventAggregator.Subscribe(subscriber, f => Task.Factory.StartNew(f, default, TaskCreationOptions.None, TaskScheduler.Default)); + /// + /// Subscribes an instance to all events declared through implementations of . + /// + /// The subscription is invoked on the UI thread. + /// The instance to subscribe for event publication. + public static void SubscribeOnUIThread(this IEventAggregator eventAggregator, object subscriber) + => eventAggregator.Subscribe( + subscriber, + f => { + var taskCompletionSource = new TaskCompletionSource(); + Execute.BeginOnUIThread(async () => { + try { + await f(); + + taskCompletionSource.SetResult(true); + } catch (OperationCanceledException) { + taskCompletionSource.SetCanceled(); + } catch (Exception ex) { + taskCompletionSource.SetException(ex); + } }); - /// - /// Publishes a message on the current thread (synchrone). - /// - /// The event aggregator. - /// The message instance. - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - /// A task that represents the asynchronous operation. - public static Task PublishOnCurrentThreadAsync(this IEventAggregator eventAggregator, object message, CancellationToken cancellationToken) - => eventAggregator.PublishAsync(message, f => f(), cancellationToken); - - /// - /// Publishes a message on the current thread (synchrone). - /// - /// The event aggregator. - /// The message instance. - /// A task that represents the asynchronous operation. - public static Task PublishOnCurrentThreadAsync(this IEventAggregator eventAggregator, object message) - => eventAggregator.PublishOnCurrentThreadAsync(message, default); + return taskCompletionSource.Task; + }); - /// - /// Publishes a message on a background thread (async). - /// - /// The event aggregator. - /// The message instance. - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - /// A task that represents the asynchronous operation. - public static Task PublishOnBackgroundThreadAsync(this IEventAggregator eventAggregator, object message, CancellationToken cancellationToken) - => eventAggregator.PublishAsync(message, f => Task.Factory.StartNew(f, default, TaskCreationOptions.None, TaskScheduler.Default), cancellationToken); + /// + /// Publishes a message on the current thread (synchrone). + /// + /// The event aggregator. + /// The message instance. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A task that represents the asynchronous operation. + public static Task PublishOnCurrentThreadAsync(this IEventAggregator eventAggregator, object message, CancellationToken cancellationToken) + => eventAggregator.PublishAsync(message, f => f(), cancellationToken); - /// - /// Publishes a message on a background thread (async). - /// - /// The event aggregator. - /// The message instance. - /// A task that represents the asynchronous operation. - public static Task PublishOnBackgroundThreadAsync(this IEventAggregator eventAggregator, object message) - => eventAggregator.PublishOnBackgroundThreadAsync(message, default); + /// + /// Publishes a message on the current thread (synchrone). + /// + /// The event aggregator. + /// The message instance. + /// A task that represents the asynchronous operation. + public static Task PublishOnCurrentThreadAsync(this IEventAggregator eventAggregator, object message) + => eventAggregator.PublishOnCurrentThreadAsync(message, default); - /// - /// Publishes a message on the UI thread. - /// - /// The event aggregator. - /// The message instance. - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - /// A task that represents the asynchronous operation. - public static Task PublishOnUIThreadAsync(this IEventAggregator eventAggregator, object message, CancellationToken cancellationToken) - => eventAggregator.PublishAsync( - message, - f => - { - var taskCompletionSource = new TaskCompletionSource(); - Execute.BeginOnUIThread(async () => - { - try - { - await f(); + /// + /// Publishes a message on a background thread (async). + /// + /// The event aggregator. + /// The message instance. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A task that represents the asynchronous operation. + public static Task PublishOnBackgroundThreadAsync(this IEventAggregator eventAggregator, object message, CancellationToken cancellationToken) + => eventAggregator.PublishAsync(message, f => Task.Factory.StartNew(f, default, TaskCreationOptions.None, TaskScheduler.Default), cancellationToken); - taskCompletionSource.SetResult(true); - } - catch (OperationCanceledException) - { - taskCompletionSource.SetCanceled(); - } - catch (Exception ex) - { - taskCompletionSource.SetException(ex); - } - }); + /// + /// Publishes a message on a background thread (async). + /// + /// The event aggregator. + /// The message instance. + /// A task that represents the asynchronous operation. + public static Task PublishOnBackgroundThreadAsync(this IEventAggregator eventAggregator, object message) + => eventAggregator.PublishOnBackgroundThreadAsync(message, default); - return taskCompletionSource.Task; + /// + /// Publishes a message on the UI thread. + /// + /// The event aggregator. + /// The message instance. + /// A task that represents the asynchronous operation. + public static Task PublishOnUIThreadAsync(this IEventAggregator eventAggregator, object message) + => eventAggregator.PublishOnUIThreadAsync(message, default); - }, cancellationToken); + /// + /// Publishes a message on the UI thread. + /// + /// The event aggregator. + /// The message instance. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A task that represents the asynchronous operation. + public static Task PublishOnUIThreadAsync(this IEventAggregator eventAggregator, object message, CancellationToken cancellationToken) + => eventAggregator.PublishAsync( + message, + f => { + var taskCompletionSource = new TaskCompletionSource(); + Execute.BeginOnUIThread(async () => { + try { + await f(); + + taskCompletionSource.SetResult(true); + } catch (OperationCanceledException) { + taskCompletionSource.SetCanceled(); + } catch (Exception ex) { + taskCompletionSource.SetException(ex); + } + }); - /// - /// Publishes a message on the UI thread. - /// - /// The event aggregator. - /// The message instance. - /// A task that represents the asynchronous operation. - public static Task PublishOnUIThreadAsync(this IEventAggregator eventAggregator, object message) - => eventAggregator.PublishOnUIThreadAsync(message, default); - } + return taskCompletionSource.Task; + }, + cancellationToken); } diff --git a/src/Caliburn.Micro.Core/Extensions/EnumerableExtensions.cs b/src/Caliburn.Micro.Core/Extensions/EnumerableExtensions.cs index 727f3d34b..d718092f4 100644 --- a/src/Caliburn.Micro.Core/Extensions/EnumerableExtensions.cs +++ b/src/Caliburn.Micro.Core/Extensions/EnumerableExtensions.cs @@ -1,25 +1,21 @@ using System; using System.Collections.Generic; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Extension methods for . +/// +public static class EnumerableExtensions { /// - /// Extension methods for + /// Applies the action to each element in the list. /// - public static class EnumerableExtensions - { - /// - /// Applies the action to each element in the list. - /// - /// The enumerable item's type. - /// The elements to enumerate. - /// The action to apply to each item in the list. - public static void Apply(this IEnumerable enumerable, Action action) - { - foreach (T item in enumerable) - { - action(item); - } + /// The enumerable item's type. + /// The elements to enumerate. + /// The action to apply to each item in the list. + public static void Apply(this IEnumerable enumerable, Action action) { + foreach (T item in enumerable) { + action(item); } } } diff --git a/src/Caliburn.Micro.Core/Extensions/Execute.cs b/src/Caliburn.Micro.Core/Extensions/Execute.cs index 1449c302e..e3297b8bf 100644 --- a/src/Caliburn.Micro.Core/Extensions/Execute.cs +++ b/src/Caliburn.Micro.Core/Extensions/Execute.cs @@ -1,38 +1,36 @@ using System; using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Enables easy marshalling of code to the UI thread. +/// +public static class Execute { /// - /// Enables easy marshalling of code to the UI thread. + /// Indicates whether or not the framework is in design-time mode. /// - public static class Execute - { - /// - /// Indicates whether or not the framework is in design-time mode. - /// - public static bool InDesignMode - => PlatformProvider.Current.InDesignMode; + public static bool InDesignMode + => PlatformProvider.Current.InDesignMode; - /// - /// Executes the action on the UI thread asynchronously. - /// - /// The action to execute. - public static void BeginOnUIThread(this Action action) - => PlatformProvider.Current.BeginOnUIThread(action); + /// + /// Executes the action on the UI thread asynchronously. + /// + /// The action to execute. + public static void BeginOnUIThread(this Action action) + => PlatformProvider.Current.BeginOnUIThread(action); - /// - /// Executes the action on the UI thread asynchronously. - /// - /// The action to execute. - public static Task OnUIThreadAsync(this Func action) - => PlatformProvider.Current.OnUIThreadAsync(action); + /// + /// Executes the action on the UI thread asynchronously. + /// + /// The action to execute. + public static Task OnUIThreadAsync(this Func action) + => PlatformProvider.Current.OnUIThreadAsync(action); - /// - /// Executes the action on the UI thread. - /// - /// The action to execute. - public static void OnUIThread(this Action action) - => PlatformProvider.Current.OnUIThread(action); - } + /// + /// Executes the action on the UI thread. + /// + /// The action to execute. + public static void OnUIThread(this Action action) + => PlatformProvider.Current.OnUIThread(action); } diff --git a/src/Caliburn.Micro.Core/Extensions/ExpressionExtensions.cs b/src/Caliburn.Micro.Core/Extensions/ExpressionExtensions.cs index 08287430a..d49b3f4b3 100644 --- a/src/Caliburn.Micro.Core/Extensions/ExpressionExtensions.cs +++ b/src/Caliburn.Micro.Core/Extensions/ExpressionExtensions.cs @@ -1,27 +1,24 @@ using System.Linq.Expressions; using System.Reflection; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Extension for . +/// +public static class ExpressionExtensions { /// - /// Extension for . + /// Converts an expression into a . /// - public static class ExpressionExtensions - { - /// - /// Converts an expression into a . - /// - /// The expression to convert. - /// The member info. - public static MemberInfo GetMemberInfo(this Expression expression) - { - var lambda = (LambdaExpression)expression; - MemberExpression memberExpression - = lambda.Body is UnaryExpression unaryExpression - ? (MemberExpression)unaryExpression.Operand - : (MemberExpression)lambda.Body; + /// The expression to convert. + /// The member info. + public static MemberInfo GetMemberInfo(this Expression expression) { + var lambda = (LambdaExpression)expression; + MemberExpression memberExpression + = lambda.Body is UnaryExpression unaryExpression + ? (MemberExpression)unaryExpression.Operand + : (MemberExpression)lambda.Body; - return memberExpression.Member; - } + return memberExpression.Member; } } diff --git a/src/Caliburn.Micro.Core/IoC/ExtensionPoints/IoC.cs b/src/Caliburn.Micro.Core/IoC/ExtensionPoints/IoC.cs index 8f414a64a..db0cf9ab8 100644 --- a/src/Caliburn.Micro.Core/IoC/ExtensionPoints/IoC.cs +++ b/src/Caliburn.Micro.Core/IoC/ExtensionPoints/IoC.cs @@ -2,49 +2,47 @@ using System.Collections.Generic; using System.Linq; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Used by the framework to pull instances from an IoC container and to inject dependencies into certain existing classes. +/// +public static class IoC { /// - /// Used by the framework to pull instances from an IoC container and to inject dependencies into certain existing classes. + /// Gets an instance by type and key. /// - public static class IoC - { - /// - /// Gets an instance by type and key. - /// - public static Func GetInstance { get; set; } - = (service, key) - => throw new InvalidOperationException("IoC is not initialized."); + public static Func GetInstance { get; set; } + = (service, key) + => throw new InvalidOperationException("IoC is not initialized."); - /// - /// Gets all instances of a particular type. - /// - public static Func> GetAllInstances { get; set; } - = service - => throw new InvalidOperationException("IoC is not initialized."); + /// + /// Gets all instances of a particular type. + /// + public static Func> GetAllInstances { get; set; } + = service + => throw new InvalidOperationException("IoC is not initialized."); - /// - /// Passes an existing instance to the IoC container to enable dependencies to be injected. - /// - public static Action BuildUp { get; set; } - = instance - => throw new InvalidOperationException("IoC is not initialized."); + /// + /// Passes an existing instance to the IoC container to enable dependencies to be injected. + /// + public static Action BuildUp { get; set; } + = instance + => throw new InvalidOperationException("IoC is not initialized."); - /// - /// Gets an instance from the container. - /// - /// The type to resolve. - /// The key to look up. - /// The resolved instance. - public static T Get(string key = null) - => (T)GetInstance(typeof(T), key); + /// + /// Gets an instance from the container. + /// + /// The type to resolve. + /// The key to look up. + /// The resolved instance. + public static T Get(string key = null) + => (T)GetInstance(typeof(T), key); - /// - /// Gets all instances of a particular type. - /// - /// The type to resolve. - /// The resolved instances. - public static IEnumerable GetAll() - => GetAllInstances(typeof(T)).Cast(); - } + /// + /// Gets all instances of a particular type. + /// + /// The type to resolve. + /// The resolved instances. + public static IEnumerable GetAll() + => GetAllInstances(typeof(T)).Cast(); } diff --git a/src/Caliburn.Micro.Core/IoC/Extensions/ContainerExtensions.cs b/src/Caliburn.Micro.Core/IoC/Extensions/ContainerExtensions.cs index 8ba5b18c6..9d4490979 100644 --- a/src/Caliburn.Micro.Core/IoC/Extensions/ContainerExtensions.cs +++ b/src/Caliburn.Micro.Core/IoC/Extensions/ContainerExtensions.cs @@ -3,164 +3,157 @@ using System.Linq; using System.Reflection; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Extension methods for the . +/// +public static class ContainerExtensions { /// - /// Extension methods for the . + /// Registers a singleton. /// - public static class ContainerExtensions - { - /// - /// Registers a singleton. - /// - /// The type of the implementation. - /// The container. - /// The key. - /// The container. - public static SimpleContainer Singleton(this SimpleContainer container, string key = null) - => Singleton(container, key); - - /// - /// Registers a singleton. - /// - /// The type of the service. - /// The type of the implementation. - /// The container. - /// The key. - /// The container. - public static SimpleContainer Singleton(this SimpleContainer container, string key = null) - where TImplementation : TService - { - container.RegisterSingleton(typeof(TService), key, typeof(TImplementation)); - - return container; - } + /// The type of the implementation. + /// The container. + /// The key. + /// The container. + public static SimpleContainer Singleton(this SimpleContainer container, string key = null) + => Singleton(container, key); - /// - /// Registers an service to be created on each request. - /// - /// The type of the implementation. - /// The container. - /// The key. - /// The container. - public static SimpleContainer PerRequest(this SimpleContainer container, string key = null) - => PerRequest(container, key); - - /// - /// Registers an service to be created on each request. - /// - /// The type of the service. - /// The type of the implementation. - /// The container. - /// The key. - /// The container. - public static SimpleContainer PerRequest(this SimpleContainer container, string key = null) - where TImplementation : TService - { - container.RegisterPerRequest(typeof(TService), key, typeof(TImplementation)); - - return container; - } + /// + /// Registers a singleton. + /// + /// The type of the service. + /// The type of the implementation. + /// The container. + /// The key. + /// The container. + public static SimpleContainer Singleton(this SimpleContainer container, string key = null) + where TImplementation : TService { + container.RegisterSingleton(typeof(TService), key, typeof(TImplementation)); + + return container; + } - /// - /// Registers an instance with the container. - /// - /// The type of the service. - /// The container. - /// The instance. - /// The container. - public static SimpleContainer Instance(this SimpleContainer container, TService instance) - { - container.RegisterInstance(typeof(TService), null, instance); - - return container; - } + /// + /// Registers an service to be created on each request. + /// + /// The type of the implementation. + /// The container. + /// The key. + /// The container. + public static SimpleContainer PerRequest(this SimpleContainer container, string key = null) + => PerRequest(container, key); - /// - /// Registers a custom service handler with the container. - /// - /// The type of the service. - /// The container. - /// The handler. - /// The container. - public static SimpleContainer Handler(this SimpleContainer container, - Func handler) - { - container.RegisterHandler(typeof(TService), null, handler); - - return container; - } + /// + /// Registers an service to be created on each request. + /// + /// The type of the service. + /// The type of the implementation. + /// The container. + /// The key. + /// The container. + public static SimpleContainer PerRequest(this SimpleContainer container, string key = null) + where TImplementation : TService { + container.RegisterPerRequest(typeof(TService), key, typeof(TImplementation)); + + return container; + } - /// - /// Registers all specified types in an assembly as singleton in the container. - /// - /// The type of the service. - /// The container. - /// The assembly. - /// The type filter. - /// The container. - public static SimpleContainer AllTypesOf( - this SimpleContainer container, - Assembly assembly, - Func filter = null) - { - filter ??= type => true; - Type serviceType = typeof(TService); - IEnumerable types - = from type in assembly.DefinedTypes - where serviceType.GetTypeInfo().IsAssignableFrom(type) - && !type.IsAbstract - && !type.IsInterface - && filter(type.AsType()) - select type; - foreach (TypeInfo type in types) - { - container.RegisterSingleton(typeof(TService), null, type.AsType()); - } - - return container; + /// + /// Registers an instance with the container. + /// + /// The type of the service. + /// The container. + /// The instance. + /// The container. + public static SimpleContainer Instance(this SimpleContainer container, TService instance) { + container.RegisterInstance(typeof(TService), null, instance); + + return container; + } + + /// + /// Registers a custom service handler with the container. + /// + /// The type of the service. + /// The container. + /// The handler. + /// The container. + public static SimpleContainer Handler( + this SimpleContainer container, + Func handler) { + container.RegisterHandler(typeof(TService), null, handler); + + return container; + } + + /// + /// Registers all specified types in an assembly as singleton in the container. + /// + /// The type of the service. + /// The container. + /// The assembly. + /// The type filter. + /// The container. + public static SimpleContainer AllTypesOf( + this SimpleContainer container, + Assembly assembly, + Func filter = null) { + filter ??= type => true; + Type serviceType = typeof(TService); + IEnumerable types + = from type in assembly.DefinedTypes + where serviceType.GetTypeInfo().IsAssignableFrom(type) + && !type.IsAbstract + && !type.IsInterface + && filter(type.AsType()) + select type; + foreach (TypeInfo type in types) { + container.RegisterSingleton(typeof(TService), null, type.AsType()); } - /// - /// Requests an instance. - /// - /// The type of the service. - /// The container. - /// The key. - /// The instance. - public static TService GetInstance(this SimpleContainer container, string key = null) - => (TService)container - .GetInstance(typeof(TService), key); - - /// - /// Gets all instances of a particular type and the given key (default null). - /// - /// The type to resolve. - /// The container. - /// The key shared by those instances - /// The resolved instances. - public static IEnumerable GetAllInstances(this SimpleContainer container, string key = null) - => container - .GetAllInstances(typeof(TService), key) - .Cast(); - - /// - /// Determines if a handler for the service/key has previously been registered. - /// - /// The service type. - /// The container. - /// The key. - /// True if a handler is registere; false otherwise. - public static bool HasHandler(this SimpleContainer container, string key = null) - => container.HasHandler(typeof(TService), key); - - /// - /// Unregisters any handlers for the service/key that have previously been registered. - /// - /// The service type. - /// The container. - /// The key. - public static void UnregisterHandler(this SimpleContainer container, string key = null) - => container.UnregisterHandler(typeof(TService), key); + return container; } + + /// + /// Requests an instance. + /// + /// The type of the service. + /// The container. + /// The key. + /// The instance. + public static TService GetInstance(this SimpleContainer container, string key = null) + => (TService)container + .GetInstance(typeof(TService), key); + + /// + /// Gets all instances of a particular type and the given key (default null). + /// + /// The type to resolve. + /// The container. + /// The key shared by those instances. + /// The resolved instances. + public static IEnumerable GetAllInstances(this SimpleContainer container, string key = null) + => container + .GetAllInstances(typeof(TService), key) + .Cast(); + + /// + /// Determines if a handler for the service/key has previously been registered. + /// + /// The service type. + /// The container. + /// The key. + /// True if a handler is registere; false otherwise. + public static bool HasHandler(this SimpleContainer container, string key = null) + => container.HasHandler(typeof(TService), key); + + /// + /// Unregisters any handlers for the service/key that have previously been registered. + /// + /// The service type. + /// The container. + /// The key. + public static void UnregisterHandler(this SimpleContainer container, string key = null) + => container.UnregisterHandler(typeof(TService), key); } diff --git a/src/Caliburn.Micro.Core/IoC/SimpleContainer.cs b/src/Caliburn.Micro.Core/IoC/SimpleContainer.cs index b92e0850e..26700ba41 100644 --- a/src/Caliburn.Micro.Core/IoC/SimpleContainer.cs +++ b/src/Caliburn.Micro.Core/IoC/SimpleContainer.cs @@ -4,313 +4,279 @@ using System.Linq; using System.Reflection; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// A simple IoC container. +/// +public class SimpleContainer { + private static readonly Type DelegateType = typeof(Delegate); + private static readonly Type EnumerableType = typeof(IEnumerable); + private static readonly TypeInfo EnumerableTypeInfo = EnumerableType.GetTypeInfo(); + private static readonly TypeInfo DelegateTypeInfo = DelegateType.GetTypeInfo(); + private readonly Type _simpleContainerType = typeof(SimpleContainer); + private readonly List _entries; + /// - /// A simple IoC container. + /// Initializes a new instance of the class. /// - public class SimpleContainer - { - private static readonly Type DelegateType = typeof(Delegate); - private static readonly Type EnumerableType = typeof(IEnumerable); - private static readonly TypeInfo EnumerableTypeInfo = EnumerableType.GetTypeInfo(); - private static readonly TypeInfo DelegateTypeInfo = DelegateType.GetTypeInfo(); - private readonly Type _simpleContainerType = typeof(SimpleContainer); - private readonly List _entries; - - /// - /// Initializes a new instance of the class. - /// - public SimpleContainer() - => _entries = new List(); - - private SimpleContainer(IEnumerable entries) - => _entries = new List(entries); - - /// - /// Whether to enable recursive property injection for all resolutions. - /// - public bool EnablePropertyInjection { get; set; } - - /// - /// Registers the instance. - /// - /// The service. - /// The key. - /// The implementation. - public void RegisterInstance(Type service, string key, object implementation) - => RegisterHandler(service, key, container => implementation); - - /// - /// Registers the class so that a new instance is created on every request. - /// - /// The service. - /// The key. - /// The implementation. - public void RegisterPerRequest(Type service, string key, Type implementation) - => RegisterHandler(service, key, container => container.BuildInstance(implementation)); - - /// - /// Registers the class so that it is created once, on first request, and the same instance is returned to all requestors thereafter. - /// - /// The service. - /// The key. - /// The implementation. - public void RegisterSingleton(Type service, string key, Type implementation) - { - object singleton = null; - RegisterHandler(service, key, container => (singleton ??= container.BuildInstance(implementation))); - } + public SimpleContainer() + => _entries = new List(); - /// - /// Registers a custom handler for serving requests from the container. - /// - /// The service. - /// The key. - /// The handler. - public void RegisterHandler(Type service, string key, Func handler) - => GetOrCreateEntry(service, key).Add(handler); - - /// - /// Unregisters any handlers for the service/key that have previously been registered. - /// - /// The service. - /// The key. - public void UnregisterHandler(Type service, string key) - { - ContainerEntry entry = GetEntry(service, key); - if (entry == null) - { - return; - } + private SimpleContainer(IEnumerable entries) + => _entries = new List(entries); - _entries.Remove(entry); - } + /// + /// Occurs when a new instance is created. + /// + public event Action Activated + = obj => { }; - /// - /// Requests an instance. - /// - /// The service. - /// The key. - /// The instance, or null if a handler is not found. - public object GetInstance(Type service, string key) - { - ContainerEntry entry = GetEntry(service, key); - if (entry != null) - { - var instance = entry.Single()(this); - if (!EnablePropertyInjection || instance == null) - { - return instance; - } + /// + /// Gets or sets a value indicating whether to enable recursive property injection for all resolutions. + /// + public bool EnablePropertyInjection { get; set; } - BuildUp(instance); + /// + /// Registers the instance. + /// + /// The service. + /// The key. + /// The implementation. + public void RegisterInstance(Type service, string key, object implementation) + => RegisterHandler(service, key, container => implementation); - return instance; - } + /// + /// Registers the class so that a new instance is created on every request. + /// + /// The service. + /// The key. + /// The implementation. + public void RegisterPerRequest(Type service, string key, Type implementation) + => RegisterHandler(service, key, container => container.BuildInstance(implementation)); - if (service == null) - { - return null; - } + /// + /// Registers the class so that it is created once, on first request, and the same instance is returned to all requestors thereafter. + /// + /// The service. + /// The key. + /// The implementation. + public void RegisterSingleton(Type service, string key, Type implementation) { + object singleton = null; + RegisterHandler(service, key, container => (singleton ??= container.BuildInstance(implementation))); + } - TypeInfo serviceTypeInfo = service.GetTypeInfo(); - if (DelegateTypeInfo.IsAssignableFrom(serviceTypeInfo)) - { - Type typeToCreate = serviceTypeInfo.GenericTypeArguments[0]; - Type factoryFactoryType = typeof(FactoryFactory<>).MakeGenericType(typeToCreate); - var factoryFactoryHost = Activator.CreateInstance(factoryFactoryType); - MethodInfo factoryFactoryMethod = factoryFactoryType.GetRuntimeMethod("Create", new Type[] { _simpleContainerType }); + /// + /// Registers a custom handler for serving requests from the container. + /// + /// The service. + /// The key. + /// The handler. + public void RegisterHandler(Type service, string key, Func handler) + => GetOrCreateEntry(service, key).Add(handler); - return factoryFactoryMethod.Invoke(factoryFactoryHost, new object[] { this }); - } + /// + /// Unregisters any handlers for the service/key that have previously been registered. + /// + /// The service. + /// The key. + public void UnregisterHandler(Type service, string key) { + ContainerEntry entry = GetEntry(service, key); + if (entry == null) { + return; + } + + _entries.Remove(entry); + } - if (!EnumerableTypeInfo.IsAssignableFrom(serviceTypeInfo) || !serviceTypeInfo.IsGenericType) - { - return null; + /// + /// Requests an instance. + /// + /// The service. + /// The key. + /// The instance, or null if a handler is not found. + public object GetInstance(Type service, string key) { + ContainerEntry entry = GetEntry(service, key); + if (entry != null) { + object instance = entry.Single()(this); + if (!EnablePropertyInjection || instance == null) { + return instance; } - Type listType = serviceTypeInfo.GenericTypeArguments[0]; - var instances = GetAllInstances(listType).ToList(); - var array = Array.CreateInstance(listType, instances.Count); + BuildUp(instance); - for (var i = 0; i < array.Length; i++) - { - if (EnablePropertyInjection) - { - BuildUp(instances[i]); - } + return instance; + } - array.SetValue(instances[i], i); - } + if (service == null) { + return null; + } - return array; + TypeInfo serviceTypeInfo = service.GetTypeInfo(); + if (DelegateTypeInfo.IsAssignableFrom(serviceTypeInfo)) { + Type typeToCreate = serviceTypeInfo.GenericTypeArguments[0]; + Type factoryFactoryType = typeof(FactoryFactory<>).MakeGenericType(typeToCreate); + object factoryFactoryHost = Activator.CreateInstance(factoryFactoryType); + MethodInfo factoryFactoryMethod = factoryFactoryType.GetRuntimeMethod("Create", new Type[] { _simpleContainerType }); + + return factoryFactoryMethod.Invoke(factoryFactoryHost, new object[] { this }); } - /// - /// Determines if a handler for the service/key has previously been registered. - /// - /// The service. - /// The key. - /// True if a handler is registere; false otherwise. - public bool HasHandler(Type service, string key) - => GetEntry(service, key) != null; - - /// - /// Requests all instances of a given type and the given key (default null). - /// - /// The service. - /// The key shared by those instances - /// All the instances or an empty enumerable if none are found. - public IEnumerable GetAllInstances(Type service, string key = null) - { - ContainerEntry entries = GetEntry(service, key); - - if (entries == null) - { - return Array.Empty(); - } + if (!EnumerableTypeInfo.IsAssignableFrom(serviceTypeInfo) || !serviceTypeInfo.IsGenericType) { + return null; + } - IEnumerable instances = entries.Select(e => e(this)); + Type listType = serviceTypeInfo.GenericTypeArguments[0]; + var instances = GetAllInstances(listType).ToList(); + var array = Array.CreateInstance(listType, instances.Count); - foreach (var instance in instances) - { - if (EnablePropertyInjection && instance != null) - { - BuildUp(instance); - } + for (int i = 0; i < array.Length; i++) { + if (EnablePropertyInjection) { + BuildUp(instances[i]); } - return instances; + array.SetValue(instances[i], i); } - /// - /// Pushes dependencies into an existing instance based on interface properties with setters. - /// - /// The instance. - public void BuildUp(object instance) - { - IEnumerable properties = instance - .GetType() - .GetRuntimeProperties() - .Where(p => p.CanRead && p.CanWrite && p.PropertyType.GetTypeInfo().IsInterface); - - foreach (PropertyInfo property in properties) - { - var value = GetInstance(property.PropertyType, null); - if (value == null) - { - continue; - } - - property.SetValue(instance, value, null); - } - } + return array; + } - /// - /// Creates a child container. - /// - /// A new container. - public SimpleContainer CreateChildContainer() - => new(_entries); - - private ContainerEntry GetOrCreateEntry(Type service, string key) - { - ContainerEntry entry = GetEntry(service, key); - if (entry != null) - { - return entry; - } - - entry = new ContainerEntry { Service = service, Key = key }; - _entries.Add(entry); + /// + /// Determines if a handler for the service/key has previously been registered. + /// + /// The service. + /// The key. + /// True if a handler is registere; false otherwise. + public bool HasHandler(Type service, string key) + => GetEntry(service, key) != null; - return entry; + /// + /// Requests all instances of a given type and the given key (default null). + /// + /// The service. + /// The key shared by those instances. + /// All the instances or an empty enumerable if none are found. + public IEnumerable GetAllInstances(Type service, string key = null) { + ContainerEntry entries = GetEntry(service, key); + + if (entries == null) { + return Array.Empty(); } - private ContainerEntry GetEntry(Type service, string key) - { - if (service == null) - { - return _entries.FirstOrDefault(x => x.Key == key); + IEnumerable instances = entries.Select(e => e(this)); + + foreach (object instance in instances) { + if (EnablePropertyInjection && instance != null) { + BuildUp(instance); } + } + + return instances; + } - if (key == null) - { - return _entries.FirstOrDefault(x => x.Service == service && string.IsNullOrEmpty(x.Key)) - ?? _entries.FirstOrDefault(x => x.Service == service); + /// + /// Pushes dependencies into an existing instance based on interface properties with setters. + /// + /// The instance. + public void BuildUp(object instance) { + IEnumerable properties = instance + .GetType() + .GetRuntimeProperties() + .Where(p => p.CanRead && p.CanWrite && p.PropertyType.GetTypeInfo().IsInterface); + + foreach (PropertyInfo property in properties) { + object value = GetInstance(property.PropertyType, null); + if (value == null) { + continue; } - return _entries.FirstOrDefault(x => x.Service == service && x.Key == key); + property.SetValue(instance, value, null); } + } - /// - /// Actually does the work of creating the instance and satisfying it's constructor dependencies. - /// - /// The type. - /// - protected object BuildInstance(Type type) - { - var args = DetermineConstructorArgs(type); + /// + /// Creates a child container. + /// + /// A new container. + public SimpleContainer CreateChildContainer() + => new(_entries); - return ActivateInstance(type, args); - } + /// + /// Actually does the work of creating the instance and satisfying it's constructor dependencies. + /// + /// The type. + protected object BuildInstance(Type type) { + object[] args = DetermineConstructorArgs(type); - /// - /// Creates an instance of the type with the specified constructor arguments. - /// - /// The type. - /// The constructor args. - /// The created instance. - protected virtual object ActivateInstance(Type type, object[] args) - { - var instance = args.Length > 0 ? System.Activator.CreateInstance(type, args) : System.Activator.CreateInstance(type); - Activated(instance); + return ActivateInstance(type, args); + } - return instance; + /// + /// Creates an instance of the type with the specified constructor arguments. + /// + /// The type. + /// The constructor args. + /// The created instance. + protected virtual object ActivateInstance(Type type, object[] args) { + object instance = args.Length > 0 ? System.Activator.CreateInstance(type, args) : System.Activator.CreateInstance(type); + Activated(instance); + + return instance; + } + + private ContainerEntry GetOrCreateEntry(Type service, string key) { + ContainerEntry entry = GetEntry(service, key); + if (entry != null) { + return entry; } - /// - /// Occurs when a new instance is created. - /// - public event Action Activated = delegate { }; - - private object[] DetermineConstructorArgs(Type implementation) - { - var args = new List(); - ConstructorInfo constructor = SelectEligibleConstructor(implementation); - if (constructor == null) - { - return args.ToArray(); - } - - args.AddRange(constructor.GetParameters().Select(info => GetInstance(info.ParameterType, null))); + entry = new ContainerEntry { Service = service, Key = key }; + _entries.Add(entry); + + return entry; + } + private ContainerEntry GetEntry(Type service, string key) + => service == null + ? _entries.FirstOrDefault(x => x.Key == key) + : key == null + ? _entries.FirstOrDefault(x => x.Service == service && + string.IsNullOrEmpty(x.Key)) + ?? _entries.FirstOrDefault(x => x.Service == service) + : _entries.FirstOrDefault(x => x.Service == service && + x.Key == key); + + private object[] DetermineConstructorArgs(Type implementation) { + var args = new List(); + ConstructorInfo constructor = SelectEligibleConstructor(implementation); + if (constructor == null) { return args.ToArray(); } - private ConstructorInfo SelectEligibleConstructor(Type type) - => type.GetTypeInfo().DeclaredConstructors - .Where(c => c.IsPublic) - .Select(c => new - { - Constructor = c, - HandledParamters = c.GetParameters().Count(p => HasHandler(p.ParameterType, null)) - }) - .OrderByDescending(c => c.HandledParamters) - .Select(c => c.Constructor) - .FirstOrDefault(); - - private sealed class ContainerEntry : List> - { - public string Key; - public Type Service; - } + args.AddRange(constructor.GetParameters().Select(info => GetInstance(info.ParameterType, null))); - private sealed class FactoryFactory - { - public Func Create(SimpleContainer container) - => () => (T)container.GetInstance(typeof(T), null); - } + return args.ToArray(); + } + + private ConstructorInfo SelectEligibleConstructor(Type type) + => type.GetTypeInfo().DeclaredConstructors + .Where(c => c.IsPublic) + .Select(c => new { + Constructor = c, + HandledParamters = c.GetParameters().Count(p => HasHandler(p.ParameterType, null)), + }) + .OrderByDescending(c => c.HandledParamters) + .Select(c => c.Constructor) + .FirstOrDefault(); + + private sealed class ContainerEntry : List> { + public string Key { get; set; } + + public Type Service { get; set; } + } + + private sealed class FactoryFactory { + public Func Create(SimpleContainer container) + => () => (T)container.GetInstance(typeof(T), null); } } diff --git a/src/Caliburn.Micro.Core/Logging/Contracts/ILog.cs b/src/Caliburn.Micro.Core/Logging/Contracts/ILog.cs index d23b5719d..9ba1fa333 100644 --- a/src/Caliburn.Micro.Core/Logging/Contracts/ILog.cs +++ b/src/Caliburn.Micro.Core/Logging/Contracts/ILog.cs @@ -1,30 +1,28 @@ using System; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// A logger. +/// +public interface ILog { /// - /// A logger. + /// Logs the message as info. /// - public interface ILog - { - /// - /// Logs the message as info. - /// - /// A formatted message. - /// Parameters to be injected into the formatted message. - void Info(string format, params object[] args); + /// A formatted message. + /// Parameters to be injected into the formatted message. + void Info(string format, params object[] args); - /// - /// Logs the message as a warning. - /// - /// A formatted message. - /// Parameters to be injected into the formatted message. - void Warn(string format, params object[] args); + /// + /// Logs the message as a warning. + /// + /// A formatted message. + /// Parameters to be injected into the formatted message. + void Warn(string format, params object[] args); - /// - /// Logs the exception. - /// - /// The exception. - void Error(Exception exception); - } + /// + /// Logs the exception. + /// + /// The exception. + void Error(Exception exception); } diff --git a/src/Caliburn.Micro.Core/Logging/ExtensionPoints/LogManager.cs b/src/Caliburn.Micro.Core/Logging/ExtensionPoints/LogManager.cs index 0d0a5b917..3c5084e4a 100644 --- a/src/Caliburn.Micro.Core/Logging/ExtensionPoints/LogManager.cs +++ b/src/Caliburn.Micro.Core/Logging/ExtensionPoints/LogManager.cs @@ -1,26 +1,28 @@ using System; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Used to manage logging. +/// +public static class LogManager { + private static readonly ILog NullLogInstance = new NullLog(); + /// - /// Used to manage logging. + /// Gets or sets func to create an for the provided type. /// - public static class LogManager - { - private static readonly ILog NullLogInstance = new NullLog(); + public static Func GetLog { get; set; } + = type + => NullLogInstance; - /// - /// Creates an for the provided type. - /// - public static Func GetLog { get; set; } - = type - => NullLogInstance; + private sealed class NullLog : ILog { + public void Info(string format, params object[] args) { + } + + public void Warn(string format, params object[] args) { + } - private sealed class NullLog : ILog - { - public void Info(string format, params object[] args) { } - public void Warn(string format, params object[] args) { } - public void Error(Exception exception) { } + public void Error(Exception exception) { } } } diff --git a/src/Caliburn.Micro.Core/Logging/Impl/DebugLog.cs b/src/Caliburn.Micro.Core/Logging/Impl/DebugLog.cs index a9014d33e..09e15db93 100644 --- a/src/Caliburn.Micro.Core/Logging/Impl/DebugLog.cs +++ b/src/Caliburn.Micro.Core/Logging/Impl/DebugLog.cs @@ -4,43 +4,41 @@ using System.Diagnostics; using System.Globalization; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// A simple logger thats logs everything to the debugger. +/// +public class DebugLog : ILog { + private readonly string _typeName; + /// - /// A simple logger thats logs everything to the debugger. + /// Initializes a new instance of the class. /// - public class DebugLog : ILog - { - private readonly string _typeName; - - /// - /// Initializes a new instance of the class. - /// - /// The type. - public DebugLog(Type type) - => _typeName = type.FullName; + /// The type. + public DebugLog(Type type) + => _typeName = type.FullName; - /// - /// Logs the message as info. - /// - /// A formatted message. - /// Parameters to be injected into the formatted message. - public void Info(string format, params object[] args) - => Debug.WriteLine("[{1}] INFO: {0}", string.Format(CultureInfo.InvariantCulture, format, args), _typeName); + /// + /// Logs the message as info. + /// + /// A formatted message. + /// Parameters to be injected into the formatted message. + public void Info(string format, params object[] args) + => Debug.WriteLine("[{1}] INFO: {0}", string.Format(CultureInfo.InvariantCulture, format, args), _typeName); - /// - /// Logs the message as a warning. - /// - /// A formatted message. - /// Parameters to be injected into the formatted message. - public void Warn(string format, params object[] args) - => Debug.WriteLine("[{1}] WARN: {0}", string.Format(CultureInfo.InvariantCulture, format, args), _typeName); + /// + /// Logs the message as a warning. + /// + /// A formatted message. + /// Parameters to be injected into the formatted message. + public void Warn(string format, params object[] args) + => Debug.WriteLine("[{1}] WARN: {0}", string.Format(CultureInfo.InvariantCulture, format, args), _typeName); - /// - /// Logs the exception. - /// - /// The exception. - public void Error(Exception exception) - => Debug.WriteLine("[{1}] ERROR: {0}", exception, _typeName); - } + /// + /// Logs the exception. + /// + /// The exception. + public void Error(Exception exception) + => Debug.WriteLine("[{1}] ERROR: {0}", exception, _typeName); } diff --git a/src/Caliburn.Micro.Core/PlatformProvider/Contracts/IPlatformProvider.cs b/src/Caliburn.Micro.Core/PlatformProvider/Contracts/IPlatformProvider.cs index e314efc9e..cc5609661 100644 --- a/src/Caliburn.Micro.Core/PlatformProvider/Contracts/IPlatformProvider.cs +++ b/src/Caliburn.Micro.Core/PlatformProvider/Contracts/IPlatformProvider.cs @@ -3,74 +3,72 @@ using System.Threading; using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Interface for platform specific operations that need enlightenment. +/// +public interface IPlatformProvider { /// - /// Interface for platform specific operations that need enlightenment. + /// Indicates whether or not the framework is in design-time mode. /// - public interface IPlatformProvider - { - /// - /// Indicates whether or not the framework is in design-time mode. - /// - bool InDesignMode { get; } + bool InDesignMode { get; } - /// - /// Whether or not classes should execute property change notications on the UI thread. - /// - bool PropertyChangeNotificationsOnUIThread { get; } + /// + /// Whether or not classes should execute property change notications on the UI thread. + /// + bool PropertyChangeNotificationsOnUIThread { get; } - /// - /// Executes the action on the UI thread asynchronously. - /// - /// The action to execute. - void BeginOnUIThread(Action action); + /// + /// Executes the action on the UI thread asynchronously. + /// + /// The action to execute. + void BeginOnUIThread(Action action); - /// - /// Executes the action on the UI thread asynchronously. - /// - /// The action to execute. - Task OnUIThreadAsync(Func action); + /// + /// Executes the action on the UI thread asynchronously. + /// + /// The action to execute. + Task OnUIThreadAsync(Func action); - /// - /// Executes the action on the UI thread. - /// - /// The action to execute. - void OnUIThread(Action action); + /// + /// Executes the action on the UI thread. + /// + /// The action to execute. + void OnUIThread(Action action); - /// - /// Used to retrieve the root, non-framework-created view. - /// - /// The view to search. - /// The root element that was not created by the framework. - /// In certain instances the services create UI elements. - /// For example, if you ask the window manager to show a UserControl as a dialog, it creates a window to host the UserControl in. - /// The WindowManager marks that element as a framework-created element so that it can determine what it created vs. what was intended by the developer. - /// Calling GetFirstNonGeneratedView allows the framework to discover what the original element was. - /// - object GetFirstNonGeneratedView(object view); + /// + /// Used to retrieve the root, non-framework-created view. + /// + /// The view to search. + /// The root element that was not created by the framework. + /// In certain instances the services create UI elements. + /// For example, if you ask the window manager to show a UserControl as a dialog, it creates a window to host the UserControl in. + /// The WindowManager marks that element as a framework-created element so that it can determine what it created vs. what was intended by the developer. + /// Calling GetFirstNonGeneratedView allows the framework to discover what the original element was. + /// + object GetFirstNonGeneratedView(object view); - /// - /// Executes the handler the fist time the view is loaded. - /// - /// The view. - /// The handler. - void ExecuteOnFirstLoad(object view, Action handler); + /// + /// Executes the handler the fist time the view is loaded. + /// + /// The view. + /// The handler. + void ExecuteOnFirstLoad(object view, Action handler); - /// - /// Executes the handler the next time the view's LayoutUpdated event fires. - /// - /// The view. - /// The handler. - void ExecuteOnLayoutUpdated(object view, Action handler); + /// + /// Executes the handler the next time the view's LayoutUpdated event fires. + /// + /// The view. + /// The handler. + void ExecuteOnLayoutUpdated(object view, Action handler); - /// - /// Get the close action for the specified view model. - /// - /// The view model to close. - /// The associated views. - /// The dialog result. - /// An to close the view model. - Func GetViewCloseAction(object viewModel, ICollection views, bool? dialogResult); - } + /// + /// Get the close action for the specified view model. + /// + /// The view model to close. + /// The associated views. + /// The dialog result. + /// An to close the view model. + Func GetViewCloseAction(object viewModel, ICollection views, bool? dialogResult); } diff --git a/src/Caliburn.Micro.Core/PlatformProvider/DefaultImpl/DefaultPlatformProvider.cs b/src/Caliburn.Micro.Core/PlatformProvider/DefaultImpl/DefaultPlatformProvider.cs index e93ff1166..712c4feed 100644 --- a/src/Caliburn.Micro.Core/PlatformProvider/DefaultImpl/DefaultPlatformProvider.cs +++ b/src/Caliburn.Micro.Core/PlatformProvider/DefaultImpl/DefaultPlatformProvider.cs @@ -3,90 +3,86 @@ using System.Threading; using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Default implementation for that does no platform enlightenment. +/// +public class DefaultPlatformProvider : IPlatformProvider { /// - /// Default implementation for that does no platform enlightenment. + /// Gets a value indicating whether or not the framework is in design-time mode. /// - public class DefaultPlatformProvider : IPlatformProvider - { - /// - /// Indicates whether or not the framework is in design-time mode. - /// - public virtual bool InDesignMode - => true; + public virtual bool InDesignMode + => true; - /// - /// Executes the action on the UI thread asynchronously. - /// - /// The action to execute. - public virtual void BeginOnUIThread(Action action) - => action(); + /// + /// Gets a value indicating whether or not classes should execute property change notications on the UI thread. + /// + public virtual bool PropertyChangeNotificationsOnUIThread + => true; - /// - /// Executes the action on the UI thread asynchronously. - /// - /// The action to execute. - /// - public virtual Task OnUIThreadAsync(Func action) - => Task.Factory.StartNew(action); + /// + /// Executes the action on the UI thread asynchronously. + /// + /// The action to execute. + public virtual void BeginOnUIThread(Action action) + => action(); - /// - /// Executes the action on the UI thread. - /// - /// The action to execute. - public virtual void OnUIThread(Action action) - => action(); + /// + /// Executes the action on the UI thread asynchronously. + /// + /// The action to execute. + public virtual Task OnUIThreadAsync(Func action) + => Task.Factory.StartNew(action); - /// - /// Whether or not classes should execute property change notications on the UI thread. - /// - public virtual bool PropertyChangeNotificationsOnUIThread - => true; + /// + /// Executes the action on the UI thread. + /// + /// The action to execute. + public virtual void OnUIThread(Action action) + => action(); - /// - /// Used to retrieve the root, non-framework-created view. - /// - /// The view to search. - /// - /// The root element that was not created by the framework. - /// - /// - /// In certain instances the services create UI elements. - /// For example, if you ask the window manager to show a UserControl as a dialog, it creates a window to host the UserControl in. - /// The WindowManager marks that element as a framework-created element so that it can determine what it created vs. what was intended by the developer. - /// Calling GetFirstNonGeneratedView allows the framework to discover what the original element was. - /// - public virtual object GetFirstNonGeneratedView(object view) - => view; + /// + /// Used to retrieve the root, non-framework-created view. + /// + /// The view to search. + /// + /// The root element that was not created by the framework. + /// + /// + /// In certain instances the services create UI elements. + /// For example, if you ask the window manager to show a UserControl as a dialog, it creates a window to host the UserControl in. + /// The WindowManager marks that element as a framework-created element so that it can determine what it created vs. what was intended by the developer. + /// Calling GetFirstNonGeneratedView allows the framework to discover what the original element was. + /// + public virtual object GetFirstNonGeneratedView(object view) + => view; - /// - /// Executes the handler the fist time the view is loaded. - /// - /// The view. - /// The handler. - /// true if the handler was executed immediately; false otherwise - public virtual void ExecuteOnFirstLoad(object view, Action handler) - => handler(view); + /// + /// Executes the handler the fist time the view is loaded. + /// + /// The view. + /// The handler. + public virtual void ExecuteOnFirstLoad(object view, Action handler) + => handler(view); - /// - /// Executes the handler the next time the view's LayoutUpdated event fires. - /// - /// The view. - /// The handler. - public virtual void ExecuteOnLayoutUpdated(object view, Action handler) - => handler(view); + /// + /// Executes the handler the next time the view's LayoutUpdated event fires. + /// + /// The view. + /// The handler. + public virtual void ExecuteOnLayoutUpdated(object view, Action handler) + => handler(view); - /// - /// Get the close action for the specified view model. - /// - /// The view model to close. - /// The associated views. - /// The dialog result. - /// - /// An to close the view model. - /// - public virtual Func GetViewCloseAction(object viewModel, ICollection views, bool? dialogResult) - => ct => Task.FromResult(true); - } + /// + /// Get the close action for the specified view model. + /// + /// The view model to close. + /// The associated views. + /// The dialog result. + /// + /// An to close the view model. + /// + public virtual Func GetViewCloseAction(object viewModel, ICollection views, bool? dialogResult) + => ct => Task.FromResult(true); } diff --git a/src/Caliburn.Micro.Core/PlatformProvider/ExtensionPoints/PlatformProvider.cs b/src/Caliburn.Micro.Core/PlatformProvider/ExtensionPoints/PlatformProvider.cs index 72d795504..a6f1b5363 100644 --- a/src/Caliburn.Micro.Core/PlatformProvider/ExtensionPoints/PlatformProvider.cs +++ b/src/Caliburn.Micro.Core/PlatformProvider/ExtensionPoints/PlatformProvider.cs @@ -1,14 +1,12 @@ -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Access the current . +/// +public static class PlatformProvider { /// - /// Access the current . + /// Gets or sets the current . /// - public static class PlatformProvider - { - /// - /// Gets or sets the current . - /// - public static IPlatformProvider Current { get; set; } - = new DefaultPlatformProvider(); - } + public static IPlatformProvider Current { get; set; } + = new DefaultPlatformProvider(); } diff --git a/src/Caliburn.Micro.Core/Result/Contracts/IResult.cs b/src/Caliburn.Micro.Core/Result/Contracts/IResult.cs index 3294ca9b4..2dadaed03 100644 --- a/src/Caliburn.Micro.Core/Result/Contracts/IResult.cs +++ b/src/Caliburn.Micro.Core/Result/Contracts/IResult.cs @@ -1,21 +1,19 @@ using System; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Allows custom code to execute after the return of a action. +/// +public interface IResult { /// - /// Allows custom code to execute after the return of a action. + /// Occurs when execution has completed. /// - public interface IResult - { - /// - /// Executes the result using the specified context. - /// - /// The context. - void Execute(CoroutineExecutionContext context); + event EventHandler Completed; - /// - /// Occurs when execution has completed. - /// - event EventHandler Completed; - } + /// + /// Executes the result using the specified context. + /// + /// The context. + void Execute(CoroutineExecutionContext context); } diff --git a/src/Caliburn.Micro.Core/Result/Contracts/IResult{TResult}.cs b/src/Caliburn.Micro.Core/Result/Contracts/IResult{TResult}.cs index 1a00c9c75..bf5b344a1 100644 --- a/src/Caliburn.Micro.Core/Result/Contracts/IResult{TResult}.cs +++ b/src/Caliburn.Micro.Core/Result/Contracts/IResult{TResult}.cs @@ -1,16 +1,14 @@ using System; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Allows custom code to execute after the return of a action. +/// +/// The type of the result. +public interface IResult : IResult { /// - /// Allows custom code to execute after the return of a action. + /// Gets the result of the asynchronous operation. /// - /// The type of the result. - public interface IResult : IResult - { - /// - /// Gets the result of the asynchronous operation. - /// - TResult Result { get; } - } + TResult Result { get; } } diff --git a/src/Caliburn.Micro.Core/Result/EventArgs/ResultCompletionEventArgs.cs b/src/Caliburn.Micro.Core/Result/EventArgs/ResultCompletionEventArgs.cs index 8c43dbbcb..3b00ebffd 100644 --- a/src/Caliburn.Micro.Core/Result/EventArgs/ResultCompletionEventArgs.cs +++ b/src/Caliburn.Micro.Core/Result/EventArgs/ResultCompletionEventArgs.cs @@ -1,22 +1,20 @@ using System; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// The event args for the Completed event of an . +/// +public class ResultCompletionEventArgs : EventArgs { /// - /// The event args for the Completed event of an . + /// Gets or sets the error if one occurred. /// - public class ResultCompletionEventArgs : EventArgs - { - /// - /// Gets or sets the error if one occurred. - /// - /// The error. - public Exception Error { get; set; } + /// The error. + public Exception Error { get; set; } - /// - /// Gets or sets a value indicating whether the result was cancelled. - /// - /// true if cancelled; otherwise, false. - public bool WasCancelled { get; set; } - } + /// + /// Gets or sets a value indicating whether the result was cancelled. + /// + /// true if cancelled; otherwise, false. + public bool WasCancelled { get; set; } } diff --git a/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs b/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs index 59f000cb6..25193dc1c 100644 --- a/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs +++ b/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs @@ -1,127 +1,117 @@ using System; using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Extension methods for instances. +/// +public static class ResultExtensions { /// - /// Extension methods for instances. + /// Adds behavior to the result which is executed when the was cancelled. /// - public static class ResultExtensions - { - /// - /// Adds behavior to the result which is executed when the was cancelled. - /// - /// The result to decorate. - /// The coroutine to execute when was canceled. - /// - public static IResult WhenCancelled(this IResult result, Func coroutine) - => new ContinueResultDecorator(result, coroutine); - - /// - /// Overrides of the decorated instance. - /// - /// The result to decorate. - /// - public static IResult OverrideCancel(this IResult result) - => new OverrideCancelResultDecorator(result); - - /// - /// Rescues from the decorated by executing a coroutine. - /// - /// The type of the exception we want to perform the rescue on. - /// The result to decorate. - /// The rescue coroutine. - /// Set to true to cancel the result after executing rescue. - /// - public static IResult Rescue(this IResult result, Func rescue, bool cancelResult = true) - where TException : Exception - => new RescueResultDecorator(result, rescue, cancelResult); - - /// - /// Rescues any exception from the decorated by executing a coroutine. - /// - /// The result to decorate. - /// The rescue coroutine. - /// Set to true to cancel the result after executing rescue. - /// - public static IResult Rescue(this IResult result, Func rescue, bool cancelResult = true) - => Rescue(result, rescue, cancelResult); - - /// - /// Executes an asynchronous. - /// - /// The coroutine to execute. - /// The context to execute the coroutine within. - /// A task that represents the asynchronous coroutine. - public static Task ExecuteAsync(this IResult result, CoroutineExecutionContext context = null) - => InternalExecuteAsync(result, context); - - /// - /// Executes an asynchronous. - /// - /// The type of the result. - /// The coroutine to execute. - /// The context to execute the coroutine within. - /// A task that represents the asynchronous coroutine. - public static Task ExecuteAsync(this IResult result, CoroutineExecutionContext context = null) - => InternalExecuteAsync(result, context); - - - /// - /// Encapsulates a task inside a couroutine. - /// - /// The task. - /// The coroutine that encapsulates the task. - public static TaskResult AsResult(this Task task) - => new(task); - - /// - /// Encapsulates a task inside a couroutine. - /// - /// The type of the result. - /// The task. - /// The coroutine that encapsulates the task. - public static TaskResult AsResult(this Task task) - => new(task); - - private static Task InternalExecuteAsync(IResult result, CoroutineExecutionContext context) - { - var taskSource = new TaskCompletionSource(); - - void OnCompleted(object s, ResultCompletionEventArgs e) - { - result.Completed -= OnCompleted; - - if (e.Error != null) - { - taskSource.SetException(e.Error); - - return; - } - - if (e.WasCancelled) - { - taskSource.SetCanceled(); - - return; - } - - taskSource.SetResult(result is IResult rr ? rr.Result : default); - } + /// The result to decorate. + /// The coroutine to execute when was canceled. + /// + public static IResult WhenCancelled(this IResult result, Func coroutine) + => new ContinueResultDecorator(result, coroutine); + + /// + /// Overrides of the decorated instance. + /// + /// The result to decorate. + /// + public static IResult OverrideCancel(this IResult result) + => new OverrideCancelResultDecorator(result); + + /// + /// Rescues from the decorated by executing a coroutine. + /// + /// The type of the exception we want to perform the rescue on. + /// The result to decorate. + /// The rescue coroutine. + /// Set to true to cancel the result after executing rescue. + /// + public static IResult Rescue(this IResult result, Func rescue, bool cancelResult = true) + where TException : Exception + => new RescueResultDecorator(result, rescue, cancelResult); - try - { - IoC.BuildUp(result); - result.Completed += OnCompleted; - result.Execute(context ?? new CoroutineExecutionContext()); + /// + /// Rescues any exception from the decorated by executing a coroutine. + /// + /// The result to decorate. + /// The rescue coroutine. + /// Set to true to cancel the result after executing rescue. + /// + public static IResult Rescue(this IResult result, Func rescue, bool cancelResult = true) + => Rescue(result, rescue, cancelResult); + + /// + /// Executes an asynchronous. + /// + /// The coroutine to execute. + /// The context to execute the coroutine within. + /// A task that represents the asynchronous coroutine. + public static Task ExecuteAsync(this IResult result, CoroutineExecutionContext context = null) + => InternalExecuteAsync(result, context); + + /// + /// Executes an asynchronous. + /// + /// The type of the result. + /// The coroutine to execute. + /// The context to execute the coroutine within. + /// A task that represents the asynchronous coroutine. + public static Task ExecuteAsync(this IResult result, CoroutineExecutionContext context = null) + => InternalExecuteAsync(result, context); + + /// + /// Encapsulates a task inside a couroutine. + /// + /// The task. + /// The coroutine that encapsulates the task. + public static TaskResult AsResult(this Task task) + => new(task); + + /// + /// Encapsulates a task inside a couroutine. + /// + /// The type of the result. + /// The task. + /// The coroutine that encapsulates the task. + public static TaskResult AsResult(this Task task) + => new(task); + + private static Task InternalExecuteAsync(IResult result, CoroutineExecutionContext context) { + var taskSource = new TaskCompletionSource(); + + void OnCompleted(object s, ResultCompletionEventArgs e) { + result.Completed -= OnCompleted; + + if (e.Error != null) { + taskSource.SetException(e.Error); + + return; } - catch (Exception ex) - { - result.Completed -= OnCompleted; - taskSource.SetException(ex); + + if (e.WasCancelled) { + taskSource.SetCanceled(); + + return; } - return taskSource.Task; + taskSource.SetResult(result is IResult rr ? rr.Result : default); } + + try { + IoC.BuildUp(result); + result.Completed += OnCompleted; + result.Execute(context ?? new CoroutineExecutionContext()); + } catch (Exception ex) { + result.Completed -= OnCompleted; + taskSource.SetException(ex); + } + + return taskSource.Task; } } diff --git a/src/Caliburn.Micro.Core/Result/Impl/ContinueResultDecorator.cs b/src/Caliburn.Micro.Core/Result/Impl/ContinueResultDecorator.cs index 3e18f20ce..658852816 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/ContinueResultDecorator.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/ContinueResultDecorator.cs @@ -1,77 +1,64 @@ using System; using System.Globalization; -namespace Caliburn.Micro -{ - /// - /// A result decorator which executes a coroutine when the wrapped result was cancelled. - /// - public class ContinueResultDecorator : ResultDecoratorBase - { - private static readonly ILog Log = LogManager.GetLog(typeof(ContinueResultDecorator)); - private readonly Func _coroutine; +namespace Caliburn.Micro; - /// - /// Initializes a new instance of the class. - /// - /// The result to decorate. - /// The coroutine to execute when was canceled. - public ContinueResultDecorator(IResult result, Func coroutine) - : base(result) - => _coroutine = coroutine ?? throw new ArgumentNullException(nameof(coroutine)); +/// +/// A result decorator which executes a coroutine when the wrapped result was cancelled. +/// +public class ContinueResultDecorator : ResultDecoratorBase { + private static readonly ILog Log = LogManager.GetLog(typeof(ContinueResultDecorator)); + private readonly Func _coroutine; - /// - /// Called when the execution of the decorated result has completed. - /// - /// The context. - /// The decorated result. - /// The instance containing the event data. - protected override void OnInnerResultCompleted(CoroutineExecutionContext context, IResult innerResult, ResultCompletionEventArgs args) - { - if (args.Error != null || !args.WasCancelled) - { - OnCompleted(new ResultCompletionEventArgs { Error = args.Error }); + /// + /// Initializes a new instance of the class. + /// + /// The result to decorate. + /// The coroutine to execute when was canceled. + public ContinueResultDecorator(IResult result, Func coroutine) + : base(result) + => _coroutine = coroutine ?? throw new ArgumentNullException(nameof(coroutine)); - return; - } + /// + /// Called when the execution of the decorated result has completed. + /// + /// The context. + /// The decorated result. + /// The instance containing the event data. + protected override void OnInnerResultCompleted(CoroutineExecutionContext context, IResult innerResult, ResultCompletionEventArgs args) { + if (args.Error != null || !args.WasCancelled) { + OnCompleted(new ResultCompletionEventArgs { Error = args.Error }); - Log.Info(string.Format(CultureInfo.InvariantCulture, "Executing coroutine because {0} was cancelled.", innerResult.GetType().Name)); - Continue(context); + return; } - private void Continue(CoroutineExecutionContext context) - { - IResult continueResult; - try - { - continueResult = _coroutine(); - } - catch (Exception ex) - { - OnCompleted(new ResultCompletionEventArgs { Error = ex }); - return; - } + Log.Info(string.Format(CultureInfo.InvariantCulture, "Executing coroutine because {0} was cancelled.", innerResult.GetType().Name)); + Continue(context); + } - try - { - continueResult.Completed += ContinueCompleted; - IoC.BuildUp(continueResult); - continueResult.Execute(context); - } - catch (Exception ex) - { - ContinueCompleted(continueResult, new ResultCompletionEventArgs { Error = ex }); - } + private void Continue(CoroutineExecutionContext context) { + IResult continueResult; + try { + continueResult = _coroutine(); + } catch (Exception ex) { + OnCompleted(new ResultCompletionEventArgs { Error = ex }); + return; } - private void ContinueCompleted(object sender, ResultCompletionEventArgs args) - { - ((IResult)sender).Completed -= ContinueCompleted; - OnCompleted(new ResultCompletionEventArgs - { - Error = args.Error, - WasCancelled = args.Error == null, - }); + try { + continueResult.Completed += ContinueCompleted; + IoC.BuildUp(continueResult); + continueResult.Execute(context); + } catch (Exception ex) { + ContinueCompleted(continueResult, new ResultCompletionEventArgs { Error = ex }); } } + + private void ContinueCompleted(object sender, ResultCompletionEventArgs args) { + ((IResult)sender).Completed -= ContinueCompleted; + OnCompleted(new ResultCompletionEventArgs { + Error = args.Error, + WasCancelled = args.Error == null, + }); + } } diff --git a/src/Caliburn.Micro.Core/Result/Impl/DelegateResult.cs b/src/Caliburn.Micro.Core/Result/Impl/DelegateResult.cs index 6187a580e..7730609c8 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/DelegateResult.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/DelegateResult.cs @@ -1,44 +1,38 @@ using System; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// A result that executes an . +/// +public class DelegateResult : IResult { + private readonly Action _toExecute; + /// - /// A result that executes an . + /// Initializes a new instance of the class. /// - public class DelegateResult : IResult - { - private readonly Action _toExecute; + /// The action. + public DelegateResult(Action action) + => _toExecute = action; - /// - /// Initializes a new instance of the class. - /// - /// The action. - public DelegateResult(Action action) - => _toExecute = action; - - /// - /// Executes the result using the specified context. - /// - /// The context. - public void Execute(CoroutineExecutionContext context) - { - var eventArgs = new ResultCompletionEventArgs(); - try - { - _toExecute(); - } - catch (Exception ex) - { - eventArgs.Error = ex; - } + /// + /// Occurs when execution has completed. + /// + public event EventHandler Completed + = (sender, e) => { }; - Completed(this, eventArgs); + /// + /// Executes the result using the specified context. + /// + /// The context. + public void Execute(CoroutineExecutionContext context) { + var eventArgs = new ResultCompletionEventArgs(); + try { + _toExecute(); + } catch (Exception ex) { + eventArgs.Error = ex; } - /// - /// Occurs when execution has completed. - /// - public event EventHandler Completed - = delegate { }; + Completed(this, eventArgs); } } diff --git a/src/Caliburn.Micro.Core/Result/Impl/DelegateResult{TResult}.cs b/src/Caliburn.Micro.Core/Result/Impl/DelegateResult{TResult}.cs index 395605bbe..150994621 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/DelegateResult{TResult}.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/DelegateResult{TResult}.cs @@ -1,51 +1,44 @@ using System; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// A result that executes a . +/// +/// The type of the result. +public class DelegateResult : IResult { + private readonly Func _toExecute; + /// - /// A result that executes a + /// Initializes a new instance of the class. /// - /// The type of the result. - public class DelegateResult : IResult - { - private readonly Func _toExecute; - - /// - /// Initializes a new instance of the class. - /// - /// The action. - public DelegateResult(Func action) - => _toExecute = action; + /// The action. + public DelegateResult(Func action) + => _toExecute = action; - /// - /// Executes the result using the specified context. - /// - /// The context. - public void Execute(CoroutineExecutionContext context) - { - var eventArgs = new ResultCompletionEventArgs(); + /// + /// Occurs when execution has completed. + /// + public event EventHandler Completed + = (sender, e) => { }; - try - { - Result = _toExecute(); - } - catch (Exception ex) - { - eventArgs.Error = ex; - } + /// + /// Gets the result. + /// + public TResult Result { get; private set; } - Completed(this, eventArgs); + /// + /// Executes the result using the specified context. + /// + /// The context. + public void Execute(CoroutineExecutionContext context) { + var eventArgs = new ResultCompletionEventArgs(); + try { + Result = _toExecute(); + } catch (Exception ex) { + eventArgs.Error = ex; } - /// - /// Gets the result. - /// - public TResult Result { get; private set; } - - /// - /// Occurs when execution has completed. - /// - public event EventHandler Completed - = delegate { }; + Completed(this, eventArgs); } } diff --git a/src/Caliburn.Micro.Core/Result/Impl/OverrideCancelResultDecorator.cs b/src/Caliburn.Micro.Core/Result/Impl/OverrideCancelResultDecorator.cs index 34c893ece..00544890f 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/OverrideCancelResultDecorator.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/OverrideCancelResultDecorator.cs @@ -1,41 +1,35 @@ using System.Globalization; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// A result decorator that overrides of the decorated instance. +/// +public class OverrideCancelResultDecorator : ResultDecoratorBase { + private static readonly ILog Log + = LogManager.GetLog(typeof(OverrideCancelResultDecorator)); + /// - /// A result decorator that overrides of the decorated instance. + /// Initializes a new instance of the class. /// - public class OverrideCancelResultDecorator : ResultDecoratorBase - { - private static readonly ILog Log - = LogManager.GetLog(typeof(OverrideCancelResultDecorator)); + /// The result to decorate. + public OverrideCancelResultDecorator(IResult result) + : base(result) { + } - /// - /// Initializes a new instance of the class. - /// - /// The result to decorate. - public OverrideCancelResultDecorator(IResult result) - : base(result) - { + /// + /// Called when the execution of the decorated result has completed. + /// + /// The context. + /// The decorated result. + /// The instance containing the event data. + protected override void OnInnerResultCompleted(CoroutineExecutionContext context, IResult innerResult, ResultCompletionEventArgs args) { + if (args.WasCancelled) { + Log.Info(string.Format(CultureInfo.InvariantCulture, "Overriding WasCancelled from {0}.", innerResult.GetType().Name)); } - /// - /// Called when the execution of the decorated result has completed. - /// - /// The context. - /// The decorated result. - /// The instance containing the event data. - protected override void OnInnerResultCompleted(CoroutineExecutionContext context, IResult innerResult, ResultCompletionEventArgs args) - { - if (args.WasCancelled) - { - Log.Info(string.Format(CultureInfo.InvariantCulture, "Overriding WasCancelled from {0}.", innerResult.GetType().Name)); - } - - OnCompleted(new ResultCompletionEventArgs - { - Error = args.Error, - }); - } + OnCompleted(new ResultCompletionEventArgs { + Error = args.Error, + }); } } diff --git a/src/Caliburn.Micro.Core/Result/Impl/RescueResultDecorator.cs b/src/Caliburn.Micro.Core/Result/Impl/RescueResultDecorator.cs index 06fa2325f..281f5cfd8 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/RescueResultDecorator.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/RescueResultDecorator.cs @@ -1,84 +1,72 @@ using System; using System.Globalization; -namespace Caliburn.Micro -{ - /// - /// A result decorator which rescues errors from the decorated result by executing a rescue coroutine. - /// - /// The type of the exception we want to perform the rescue on - public class RescueResultDecorator : ResultDecoratorBase where TException : Exception - { - private static readonly ILog Log = LogManager.GetLog(typeof(RescueResultDecorator<>)); - private readonly bool _cancelResult; - private readonly Func _coroutine; +namespace Caliburn.Micro; - /// - /// Initializes a new instance of the class. - /// - /// The result to decorate. - /// The rescue coroutine. - /// Set to true to cancel the result after executing rescue. - public RescueResultDecorator(IResult result, Func coroutine, bool cancelResult = true) : base(result) - { - _coroutine = coroutine ?? throw new ArgumentNullException(nameof(coroutine)); - _cancelResult = cancelResult; - } +/// +/// A result decorator which rescues errors from the decorated result by executing a rescue coroutine. +/// +/// The type of the exception we want to perform the rescue on. +public class RescueResultDecorator : ResultDecoratorBase + where TException : Exception { + private static readonly ILog Log = LogManager.GetLog(typeof(RescueResultDecorator<>)); + private readonly bool _cancelResult; + private readonly Func _coroutine; - /// - /// Called when the execution of the decorated result has completed. - /// - /// The context. - /// The decorated result. - /// The instance containing the event data. - protected override void OnInnerResultCompleted(CoroutineExecutionContext context, IResult innerResult, ResultCompletionEventArgs args) - { - if (args.Error is not TException error) - { - OnCompleted(args); + /// + /// Initializes a new instance of the class. + /// + /// The result to decorate. + /// The rescue coroutine. + /// Set to true to cancel the result after executing rescue. + public RescueResultDecorator(IResult result, Func coroutine, bool cancelResult = true) + : base(result) { + _coroutine = coroutine ?? throw new ArgumentNullException(nameof(coroutine)); + _cancelResult = cancelResult; + } - return; - } + /// + /// Called when the execution of the decorated result has completed. + /// + /// The context. + /// The decorated result. + /// The instance containing the event data. + protected override void OnInnerResultCompleted(CoroutineExecutionContext context, IResult innerResult, ResultCompletionEventArgs args) { + if (args.Error is not TException error) { + OnCompleted(args); - Log.Error(error); - Log.Info(string.Format(CultureInfo.InvariantCulture, "Executing coroutine because {0} threw an exception.", innerResult.GetType().Name)); - Rescue(context, error); + return; } - private void Rescue(CoroutineExecutionContext context, TException exception) - { - IResult rescueResult; - try - { - rescueResult = _coroutine(exception); - } - catch (Exception ex) - { - OnCompleted(new ResultCompletionEventArgs { Error = ex }); - return; - } + Log.Error(error); + Log.Info(string.Format(CultureInfo.InvariantCulture, "Executing coroutine because {0} threw an exception.", innerResult.GetType().Name)); + Rescue(context, error); + } - try - { - rescueResult.Completed += RescueCompleted; - IoC.BuildUp(rescueResult); - rescueResult.Execute(context); - } - catch (Exception ex) - { - RescueCompleted(rescueResult, new ResultCompletionEventArgs { Error = ex }); - } + private void Rescue(CoroutineExecutionContext context, TException exception) { + IResult rescueResult; + try { + rescueResult = _coroutine(exception); + } catch (Exception ex) { + OnCompleted(new ResultCompletionEventArgs { Error = ex }); + return; } - private void RescueCompleted(object sender, ResultCompletionEventArgs args) - { - ((IResult)sender).Completed -= RescueCompleted; - OnCompleted(new ResultCompletionEventArgs - { - Error = args.Error, - WasCancelled = args.Error == null && - (args.WasCancelled || _cancelResult) - }); + try { + rescueResult.Completed += RescueCompleted; + IoC.BuildUp(rescueResult); + rescueResult.Execute(context); + } catch (Exception ex) { + RescueCompleted(rescueResult, new ResultCompletionEventArgs { Error = ex }); } } + + private void RescueCompleted(object sender, ResultCompletionEventArgs args) { + ((IResult)sender).Completed -= RescueCompleted; + OnCompleted(new ResultCompletionEventArgs { + Error = args.Error, + WasCancelled = args.Error == null && + (args.WasCancelled || _cancelResult), + }); + } } diff --git a/src/Caliburn.Micro.Core/Result/Impl/ResultDecoratorBase.cs b/src/Caliburn.Micro.Core/Result/Impl/ResultDecoratorBase.cs index 919855031..3b26cc91e 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/ResultDecoratorBase.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/ResultDecoratorBase.cs @@ -1,68 +1,61 @@ using System; -namespace Caliburn.Micro -{ - /// - /// Base class for all decorators. - /// - public abstract class ResultDecoratorBase : IResult - { - private readonly IResult _innerResult; - private CoroutineExecutionContext _context; +namespace Caliburn.Micro; - /// - /// Initializes a new instance of the class. - /// - /// The result to decorate. - protected ResultDecoratorBase(IResult result) - => _innerResult = result ?? throw new ArgumentNullException(nameof(result)); +/// +/// Base class for all decorators. +/// +public abstract class ResultDecoratorBase : IResult { + private readonly IResult _innerResult; + private CoroutineExecutionContext _context; - /// - /// Executes the result using the specified context. - /// - /// The context. - public void Execute(CoroutineExecutionContext context) - { - _context = context; + /// + /// Initializes a new instance of the class. + /// + /// The result to decorate. + protected ResultDecoratorBase(IResult result) + => _innerResult = result ?? throw new ArgumentNullException(nameof(result)); - try - { - _innerResult.Completed += InnerResultCompleted; - IoC.BuildUp(_innerResult); - _innerResult.Execute(_context); - } - catch (Exception ex) - { - InnerResultCompleted(_innerResult, new ResultCompletionEventArgs { Error = ex }); - } - } + /// + /// Occurs when execution has completed. + /// + public event EventHandler Completed + = (sender, e) => { }; - private void InnerResultCompleted(object sender, ResultCompletionEventArgs args) - { - _innerResult.Completed -= InnerResultCompleted; - OnInnerResultCompleted(_context, _innerResult, args); - _context = null; + /// + /// Executes the result using the specified context. + /// + /// The context. + public void Execute(CoroutineExecutionContext context) { + _context = context; + + try { + _innerResult.Completed += InnerResultCompleted; + IoC.BuildUp(_innerResult); + _innerResult.Execute(_context); + } catch (Exception ex) { + InnerResultCompleted(_innerResult, new ResultCompletionEventArgs { Error = ex }); } + } - /// - /// Called when the execution of the decorated result has completed. - /// - /// The context. - /// The decorated result. - /// The instance containing the event data. - protected abstract void OnInnerResultCompleted(CoroutineExecutionContext context, IResult innerResult, ResultCompletionEventArgs args); - - /// - /// Occurs when execution has completed. - /// - public event EventHandler Completed - = delegate { }; + /// + /// Called when the execution of the decorated result has completed. + /// + /// The context. + /// The decorated result. + /// The instance containing the event data. + protected abstract void OnInnerResultCompleted(CoroutineExecutionContext context, IResult innerResult, ResultCompletionEventArgs args); - /// - /// Raises the event. - /// - /// The instance containing the event data. - protected void OnCompleted(ResultCompletionEventArgs args) - => Completed(this, args); + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected void OnCompleted(ResultCompletionEventArgs args) + => Completed(this, args); + + private void InnerResultCompleted(object sender, ResultCompletionEventArgs args) { + _innerResult.Completed -= InnerResultCompleted; + OnInnerResultCompleted(_context, _innerResult, args); + _context = null; } } diff --git a/src/Caliburn.Micro.Core/Result/Impl/SequentialResult.cs b/src/Caliburn.Micro.Core/Result/Impl/SequentialResult.cs index d8386639e..12acbf6a3 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/SequentialResult.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/SequentialResult.cs @@ -1,97 +1,81 @@ using System; using System.Collections.Generic; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// An implementation of that enables sequential execution of multiple results. +/// +public class SequentialResult : IResult { + private readonly IEnumerator _enumerator; + private CoroutineExecutionContext _context; + /// - /// An implementation of that enables sequential execution of multiple results. + /// Initializes a new instance of the class. /// - public class SequentialResult : IResult - { - private readonly IEnumerator _enumerator; - private CoroutineExecutionContext _context; + /// The enumerator. + public SequentialResult(IEnumerator enumerator) + => _enumerator = enumerator; - /// - /// Initializes a new instance of the class. - /// - /// The enumerator. - public SequentialResult(IEnumerator enumerator) - => _enumerator = enumerator; + /// + /// Occurs when execution has completed. + /// + public event EventHandler Completed + = (sender, e) => { }; - /// - /// Occurs when execution has completed. - /// - public event EventHandler Completed - = delegate - { }; + /// + /// Executes the result using the specified context. + /// + /// The context. + public void Execute(CoroutineExecutionContext context) { + _context = context; + ChildCompleted(null, new ResultCompletionEventArgs()); + } - /// - /// Executes the result using the specified context. - /// - /// The context. - public void Execute(CoroutineExecutionContext context) - { - _context = context; - ChildCompleted(null, new ResultCompletionEventArgs()); + private void ChildCompleted(object sender, ResultCompletionEventArgs args) { + if (sender is IResult previous) { + previous.Completed -= ChildCompleted; } - private void ChildCompleted(object sender, ResultCompletionEventArgs args) - { - if (sender is IResult previous) - { - previous.Completed -= ChildCompleted; - } + if (args.Error != null || args.WasCancelled) { + OnComplete(args.Error, args.WasCancelled); - if (args.Error != null || args.WasCancelled) - { - OnComplete(args.Error, args.WasCancelled); - - return; - } + return; + } - var moveNextSucceeded = false; - try - { - moveNextSucceeded = _enumerator.MoveNext(); - } - catch (Exception ex) - { - OnComplete(ex, false); - return; - } + bool moveNextSucceeded = false; + try { + moveNextSucceeded = _enumerator.MoveNext(); + } catch (Exception ex) { + OnComplete(ex, false); + return; + } - if (!moveNextSucceeded) - { - OnComplete(null, false); + if (!moveNextSucceeded) { + OnComplete(null, false); - return; - } + return; + } - try - { - IResult next = _enumerator.Current; - IoC.BuildUp(next); - next.Completed += ChildCompleted; - next.Execute(_context); - } - catch (Exception ex) - { - OnComplete(ex, false); + try { + IResult next = _enumerator.Current; + IoC.BuildUp(next); + next.Completed += ChildCompleted; + next.Execute(_context); + } catch (Exception ex) { + OnComplete(ex, false); - return; - } + return; } + } - private void OnComplete(Exception error, bool wasCancelled) - { - _enumerator.Dispose(); - Completed( - this, - new ResultCompletionEventArgs - { - Error = error, - WasCancelled = wasCancelled, - }); - } + private void OnComplete(Exception error, bool wasCancelled) { + _enumerator.Dispose(); + Completed( + this, + new ResultCompletionEventArgs { + Error = error, + WasCancelled = wasCancelled, + }); } } diff --git a/src/Caliburn.Micro.Core/Result/Impl/SimpleResult.cs b/src/Caliburn.Micro.Core/Result/Impl/SimpleResult.cs index 571b32840..55e85a466 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/SimpleResult.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/SimpleResult.cs @@ -1,57 +1,53 @@ using System; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// A simple result. +/// +public sealed class SimpleResult : IResult { + private readonly bool _wasCancelled; + private readonly Exception _error; + + private SimpleResult(bool wasCancelled, Exception error) { + _wasCancelled = wasCancelled; + _error = error; + } + /// - /// A simple result. + /// Occurs when execution has completed. /// - public sealed class SimpleResult : IResult - { - private readonly bool _wasCancelled; - private readonly Exception _error; - - private SimpleResult(bool wasCancelled, Exception error) - { - _wasCancelled = wasCancelled; - _error = error; - } - - /// - /// A result that is always succeeded. - /// - public static IResult Succeeded() - => new SimpleResult(false, null); - - /// - /// A result that is always canceled. - /// - /// The result. - public static IResult Cancelled() - => new SimpleResult(true, null); - - /// - /// A result that is always failed. - /// - public static IResult Failed(Exception error) - => new SimpleResult(false, error); - - /// - /// Executes the result using the specified context. - /// - /// The context. - public void Execute(CoroutineExecutionContext context) - => Completed( - this, - new ResultCompletionEventArgs - { - WasCancelled = _wasCancelled, - Error = _error, - }); - - /// - /// Occurs when execution has completed. - /// - public event EventHandler Completed - = delegate { }; - } + public event EventHandler Completed + = (sender, e) => { }; + + /// + /// A result that is always succeeded. + /// + public static IResult Succeeded() + => new SimpleResult(false, null); + + /// + /// A result that is always canceled. + /// + /// The result. + public static IResult Cancelled() + => new SimpleResult(true, null); + + /// + /// A result that is always failed. + /// + public static IResult Failed(Exception error) + => new SimpleResult(false, error); + + /// + /// Executes the result using the specified context. + /// + /// The context. + public void Execute(CoroutineExecutionContext context) + => Completed( + this, + new ResultCompletionEventArgs { + WasCancelled = _wasCancelled, + Error = _error, + }); } diff --git a/src/Caliburn.Micro.Core/Result/Impl/TaskResult.cs b/src/Caliburn.Micro.Core/Result/Impl/TaskResult.cs index 9e9405cb4..27e43f507 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/TaskResult.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/TaskResult.cs @@ -1,58 +1,52 @@ using System; using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// A couroutine that encapsulates an . +/// +public class TaskResult : IResult { + private readonly Task _innerTask; + + /// + /// Initializes a new instance of the class. + /// + /// The task. + public TaskResult(Task task) + => _innerTask = task; + + /// + /// Occurs when execution has completed. + /// + public event EventHandler Completed + = (sender, e) => { }; + /// - /// A couroutine that encapsulates an . + /// Executes the result using the specified context. /// - public class TaskResult : IResult - { - private readonly Task _innerTask; - - /// - /// Initializes a new instance of the class. - /// - /// The task. - public TaskResult(Task task) - => _innerTask = task; - - /// - /// Executes the result using the specified context. - /// - /// The context. - public void Execute(CoroutineExecutionContext context) - { - if (_innerTask.IsCompleted) - { - OnCompleted(_innerTask); - - return; - } - - _innerTask.ContinueWith(OnCompleted, - System.Threading.SynchronizationContext.Current != null - ? TaskScheduler.FromCurrentSynchronizationContext() - : TaskScheduler.Current); + /// The context. + public void Execute(CoroutineExecutionContext context) { + if (_innerTask.IsCompleted) { + OnCompleted(_innerTask); + + return; } - /// - /// Called when the asynchronous task has completed. - /// - /// The completed task. - protected virtual void OnCompleted(Task task) - => Completed( - this, - new ResultCompletionEventArgs - { - WasCancelled = task.IsCanceled, - Error = task.Exception, - }); - - /// - /// Occurs when execution has completed. - /// - public event EventHandler Completed - = delegate { }; + _innerTask.ContinueWith( + OnCompleted, + System.Threading.SynchronizationContext.Current != null ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Current); } + + /// + /// Called when the asynchronous task has completed. + /// + /// The completed task. + protected virtual void OnCompleted(Task task) + => Completed( + this, + new ResultCompletionEventArgs { + WasCancelled = task.IsCanceled, + Error = task.Exception, + }); } diff --git a/src/Caliburn.Micro.Core/Result/Impl/TaskResult{TResult}.cs b/src/Caliburn.Micro.Core/Result/Impl/TaskResult{TResult}.cs index 910b8025c..588f70cb2 100644 --- a/src/Caliburn.Micro.Core/Result/Impl/TaskResult{TResult}.cs +++ b/src/Caliburn.Micro.Core/Result/Impl/TaskResult{TResult}.cs @@ -1,44 +1,39 @@ using System; using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// A couroutine that encapsulates an . +/// +/// The type of the result. +public class TaskResult : TaskResult, IResult { /// - /// A couroutine that encapsulates an . + /// Initializes a new instance of the class. /// - /// The type of the result. - public class TaskResult : TaskResult, IResult - { - /// - /// Initializes a new instance of the class. - /// - /// The task. - public TaskResult(Task task) - : base(task) - { - } + /// The task. + public TaskResult(Task task) + : base(task) { + } - /// - /// Gets the result of the asynchronous operation. - /// - public TResult Result { get; private set; } + /// + /// Gets the result of the asynchronous operation. + /// + public TResult Result { get; private set; } - /// - /// Called when the asynchronous task has completed. - /// - /// The completed task. - protected override void OnCompleted(Task task) - { - if (task.IsFaulted || task.IsCanceled) - { - base.OnCompleted(task); + /// + /// Called when the asynchronous task has completed. + /// + /// The completed task. + protected override void OnCompleted(Task task) { + if (task.IsFaulted || task.IsCanceled) { + base.OnCompleted(task); - return; - } + return; + } - Result = ((Task)task).Result; + Result = ((Task)task).Result; - base.OnCompleted(task); - } + base.OnCompleted(task); } } diff --git a/src/Caliburn.Micro.Core/Screen/Contracts/IActivate.cs b/src/Caliburn.Micro.Core/Screen/Contracts/IActivate.cs index d59318d97..53411f516 100644 --- a/src/Caliburn.Micro.Core/Screen/Contracts/IActivate.cs +++ b/src/Caliburn.Micro.Core/Screen/Contracts/IActivate.cs @@ -2,28 +2,26 @@ using System.Threading; using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Denotes an instance which requires activation. +/// +public interface IActivate { /// - /// Denotes an instance which requires activation. + /// Raised after activation occurs. /// - public interface IActivate - { - /// - /// Indicates whether or not this instance is active. - /// - bool IsActive { get; } + event AsyncEventHandler Activated; - /// - /// Activates this instance. - /// - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation. - Task ActivateAsync(CancellationToken cancellationToken = default); + /// + /// Gets a value indicating whether or not this instance is active. + /// + bool IsActive { get; } - /// - /// Raised after activation occurs. - /// - event AsyncEventHandler Activated; - } + /// + /// Activates this instance. + /// + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation. + Task ActivateAsync(CancellationToken cancellationToken = default); } diff --git a/src/Caliburn.Micro.Core/Screen/Contracts/IChild.cs b/src/Caliburn.Micro.Core/Screen/Contracts/IChild.cs index a28c88127..57c2c23e7 100644 --- a/src/Caliburn.Micro.Core/Screen/Contracts/IChild.cs +++ b/src/Caliburn.Micro.Core/Screen/Contracts/IChild.cs @@ -1,13 +1,11 @@ -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Denotes a node within a parent/child hierarchy. +/// +public interface IChild { /// - /// Denotes a node within a parent/child hierarchy. + /// Gets or Sets the Parent. /// - public interface IChild - { - /// - /// Gets or Sets the Parent - /// - object Parent { get; set; } - } + object Parent { get; set; } } diff --git a/src/Caliburn.Micro.Core/Screen/Contracts/IChild{TParent}.cs b/src/Caliburn.Micro.Core/Screen/Contracts/IChild{TParent}.cs index 70b62c079..5a5c963c9 100644 --- a/src/Caliburn.Micro.Core/Screen/Contracts/IChild{TParent}.cs +++ b/src/Caliburn.Micro.Core/Screen/Contracts/IChild{TParent}.cs @@ -1,14 +1,12 @@ -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Denotes a node within a parent/child hierarchy. +/// +/// The type of parent. +public interface IChild : IChild { /// - /// Denotes a node within a parent/child hierarchy. + /// Gets or Sets the Parent. /// - /// The type of parent. - public interface IChild : IChild - { - /// - /// Gets or Sets the Parent - /// - new TParent Parent { get; set; } - } + new TParent Parent { get; set; } } diff --git a/src/Caliburn.Micro.Core/Screen/Contracts/IClose.cs b/src/Caliburn.Micro.Core/Screen/Contracts/IClose.cs index e7fef0801..b321ad7e4 100644 --- a/src/Caliburn.Micro.Core/Screen/Contracts/IClose.cs +++ b/src/Caliburn.Micro.Core/Screen/Contracts/IClose.cs @@ -1,17 +1,15 @@ using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Denotes an object that can be closed. +/// +public interface IClose { /// - /// Denotes an object that can be closed. + /// Tries to close this instance. + /// Also provides an opportunity to pass a dialog result to it's corresponding view. /// - public interface IClose - { - /// - /// Tries to close this instance. - /// Also provides an opportunity to pass a dialog result to it's corresponding view. - /// - /// The dialog result. - Task TryCloseAsync(bool? dialogResult = null); - } + /// The dialog result. + Task TryCloseAsync(bool? dialogResult = null); } diff --git a/src/Caliburn.Micro.Core/Screen/Contracts/IDeactivate.cs b/src/Caliburn.Micro.Core/Screen/Contracts/IDeactivate.cs index 3c99f4b79..f5f48ae83 100644 --- a/src/Caliburn.Micro.Core/Screen/Contracts/IDeactivate.cs +++ b/src/Caliburn.Micro.Core/Screen/Contracts/IDeactivate.cs @@ -2,29 +2,27 @@ using System.Threading; using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Denotes an instance which requires deactivation. +/// +public interface IDeactivate { /// - /// Denotes an instance which requires deactivation. + /// Raised before deactivation. /// - public interface IDeactivate - { - /// - /// Raised before deactivation. - /// - event EventHandler AttemptingDeactivation; + event EventHandler AttemptingDeactivation; - /// - /// Deactivates this instance. - /// - /// Indicates whether or not this instance is being closed. - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation. - Task DeactivateAsync(bool close, CancellationToken cancellationToken = default); + /// + /// Raised after deactivation. + /// + event AsyncEventHandler Deactivated; - /// - /// Raised after deactivation. - /// - event AsyncEventHandler Deactivated; - } + /// + /// Deactivates this instance. + /// + /// Indicates whether or not this instance is being closed. + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation. + Task DeactivateAsync(bool close, CancellationToken cancellationToken = default); } diff --git a/src/Caliburn.Micro.Core/Screen/Contracts/IGuardClose.cs b/src/Caliburn.Micro.Core/Screen/Contracts/IGuardClose.cs index 286651c6a..183b3b0c5 100644 --- a/src/Caliburn.Micro.Core/Screen/Contracts/IGuardClose.cs +++ b/src/Caliburn.Micro.Core/Screen/Contracts/IGuardClose.cs @@ -1,18 +1,16 @@ using System.Threading; using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Denotes an instance which may prevent closing. +/// +public interface IGuardClose : IClose { /// - /// Denotes an instance which may prevent closing. + /// Called to check whether or not this instance can close. /// - public interface IGuardClose : IClose - { - /// - /// Called to check whether or not this instance can close. - /// - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation and contains the result of the close. - Task CanCloseAsync(CancellationToken cancellationToken = default); - } + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation and contains the result of the close. + Task CanCloseAsync(CancellationToken cancellationToken = default); } diff --git a/src/Caliburn.Micro.Core/Screen/Contracts/IHaveDisplayName.cs b/src/Caliburn.Micro.Core/Screen/Contracts/IHaveDisplayName.cs index 563ba9241..7365a4188 100644 --- a/src/Caliburn.Micro.Core/Screen/Contracts/IHaveDisplayName.cs +++ b/src/Caliburn.Micro.Core/Screen/Contracts/IHaveDisplayName.cs @@ -1,13 +1,11 @@ -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Denotes an instance which has a display name. +/// +public interface IHaveDisplayName { /// - /// Denotes an instance which has a display name. + /// Gets or Sets the Display Name. /// - public interface IHaveDisplayName - { - /// - /// Gets or Sets the Display Name - /// - string DisplayName { get; set; } - } + string DisplayName { get; set; } } diff --git a/src/Caliburn.Micro.Core/Screen/Contracts/IScreen.cs b/src/Caliburn.Micro.Core/Screen/Contracts/IScreen.cs index 1999bbece..8b21c184f 100644 --- a/src/Caliburn.Micro.Core/Screen/Contracts/IScreen.cs +++ b/src/Caliburn.Micro.Core/Screen/Contracts/IScreen.cs @@ -1,10 +1,8 @@ -namespace Caliburn.Micro -{ - /// - /// Denotes an instance which implements , , - /// , and - /// - public interface IScreen : IHaveDisplayName, IActivate, IDeactivate, IGuardClose, INotifyPropertyChangedEx - { - } +namespace Caliburn.Micro; + +/// +/// Denotes an instance which implements , , +/// , and . +/// +public interface IScreen : IHaveDisplayName, IActivate, IDeactivate, IGuardClose, INotifyPropertyChangedEx { } diff --git a/src/Caliburn.Micro.Core/Screen/EventArgs/ActivationEventArgs.cs b/src/Caliburn.Micro.Core/Screen/EventArgs/ActivationEventArgs.cs index d05fef6d4..b9ae16c48 100644 --- a/src/Caliburn.Micro.Core/Screen/EventArgs/ActivationEventArgs.cs +++ b/src/Caliburn.Micro.Core/Screen/EventArgs/ActivationEventArgs.cs @@ -1,15 +1,13 @@ using System; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// EventArgs sent during activation. +/// +public class ActivationEventArgs : EventArgs { /// - /// EventArgs sent during activation. + /// Indicates whether the sender was initialized in addition to being activated. /// - public class ActivationEventArgs : EventArgs - { - /// - /// Indicates whether the sender was initialized in addition to being activated. - /// - public bool WasInitialized { get; set; } - } + public bool WasInitialized { get; set; } } diff --git a/src/Caliburn.Micro.Core/Screen/EventArgs/DeactivationEventArgs.cs b/src/Caliburn.Micro.Core/Screen/EventArgs/DeactivationEventArgs.cs index 52089bbda..e5c587ab9 100644 --- a/src/Caliburn.Micro.Core/Screen/EventArgs/DeactivationEventArgs.cs +++ b/src/Caliburn.Micro.Core/Screen/EventArgs/DeactivationEventArgs.cs @@ -1,15 +1,13 @@ using System; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// EventArgs sent during deactivation. +/// +public class DeactivationEventArgs : EventArgs { /// - /// EventArgs sent during deactivation. + /// Indicates whether the sender was closed in addition to being deactivated. /// - public class DeactivationEventArgs : EventArgs - { - /// - /// Indicates whether the sender was closed in addition to being deactivated. - /// - public bool WasClosed { get; set; } - } + public bool WasClosed { get; set; } } diff --git a/src/Caliburn.Micro.Core/Screen/EventHandlers/AsyncEventHandler.cs b/src/Caliburn.Micro.Core/Screen/EventHandlers/AsyncEventHandler.cs index de17ff44c..3b3b9551c 100644 --- a/src/Caliburn.Micro.Core/Screen/EventHandlers/AsyncEventHandler.cs +++ b/src/Caliburn.Micro.Core/Screen/EventHandlers/AsyncEventHandler.cs @@ -1,8 +1,7 @@ using System; using System.Threading.Tasks; -namespace Caliburn.Micro -{ - public delegate Task AsyncEventHandler(object sender, TEventArgs e) - where TEventArgs : EventArgs; -} +namespace Caliburn.Micro; + +public delegate Task AsyncEventHandler(object sender, TEventArgs e) + where TEventArgs : EventArgs; diff --git a/src/Caliburn.Micro.Core/Screen/Extensions/ActivateExtensions.cs b/src/Caliburn.Micro.Core/Screen/Extensions/ActivateExtensions.cs index f56af8e8d..2ecc15ace 100644 --- a/src/Caliburn.Micro.Core/Screen/Extensions/ActivateExtensions.cs +++ b/src/Caliburn.Micro.Core/Screen/Extensions/ActivateExtensions.cs @@ -1,18 +1,16 @@ using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Extension methods for the instance. +/// +public static class ActivateExtensions { /// - /// Extension methods for the instance. + /// Activates this instance. /// - public static class ActivateExtensions - { - /// - /// Activates this instance. - /// - /// The instance to activate - /// A task that represents the asynchronous operation. - public static Task ActivateAsync(this IActivate activate) - => activate.ActivateAsync(default); - } + /// The instance to activate. + /// A task that represents the asynchronous operation. + public static Task ActivateAsync(this IActivate activate) + => activate.ActivateAsync(default); } diff --git a/src/Caliburn.Micro.Core/Screen/Extensions/AsyncEventHandlerExtensions.cs b/src/Caliburn.Micro.Core/Screen/Extensions/AsyncEventHandlerExtensions.cs index f84402d86..49288c938 100644 --- a/src/Caliburn.Micro.Core/Screen/Extensions/AsyncEventHandlerExtensions.cs +++ b/src/Caliburn.Micro.Core/Screen/Extensions/AsyncEventHandlerExtensions.cs @@ -3,18 +3,16 @@ using System.Linq; using System.Threading.Tasks; -namespace Caliburn.Micro -{ - public static class AsyncEventHandlerExtensions - { - public static IEnumerable> GetHandlers(this AsyncEventHandler handler) - where TEventArgs : EventArgs - => handler.GetInvocationList().Cast>(); +namespace Caliburn.Micro; - public static Task InvokeAllAsync(this AsyncEventHandler handler, object sender, TEventArgs e) - where TEventArgs : EventArgs - => Task.WhenAll( - handler.GetHandlers() - .Select(handleAsync => handleAsync(sender, e))); - } +public static class AsyncEventHandlerExtensions { + public static IEnumerable> GetHandlers(this AsyncEventHandler handler) + where TEventArgs : EventArgs + => handler.GetInvocationList().Cast>(); + + public static Task InvokeAllAsync(this AsyncEventHandler handler, object sender, TEventArgs e) + where TEventArgs : EventArgs + => Task.WhenAll( + handler.GetHandlers() + .Select(handleAsync => handleAsync(sender, e))); } diff --git a/src/Caliburn.Micro.Core/Screen/Extensions/DeactivateExtensions.cs b/src/Caliburn.Micro.Core/Screen/Extensions/DeactivateExtensions.cs index acf51002c..280da723f 100644 --- a/src/Caliburn.Micro.Core/Screen/Extensions/DeactivateExtensions.cs +++ b/src/Caliburn.Micro.Core/Screen/Extensions/DeactivateExtensions.cs @@ -1,19 +1,17 @@ using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Extension methods for the instance. +/// +public static class DeactivateExtensions { /// - /// Extension methods for the instance. + /// Deactivates this instance. /// - public static class DeactivateExtensions - { - /// - /// Deactivates this instance. - /// - /// The instance to deactivate - /// Indicates whether or not this instance is being closed. - /// A task that represents the asynchronous operation. - public static Task DeactivateAsync(this IDeactivate deactivate, bool close) - => deactivate.DeactivateAsync(close, default); - } + /// The instance to deactivate. + /// Indicates whether or not this instance is being closed. + /// A task that represents the asynchronous operation. + public static Task DeactivateAsync(this IDeactivate deactivate, bool close) + => deactivate.DeactivateAsync(close, default); } diff --git a/src/Caliburn.Micro.Core/Screen/Extensions/ScreenExtensions.cs b/src/Caliburn.Micro.Core/Screen/Extensions/ScreenExtensions.cs index 648c8b121..e86ecf418 100644 --- a/src/Caliburn.Micro.Core/Screen/Extensions/ScreenExtensions.cs +++ b/src/Caliburn.Micro.Core/Screen/Extensions/ScreenExtensions.cs @@ -2,141 +2,136 @@ using System.Threading; using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Hosts extension methods for classes. +/// +public static class ScreenExtensions { /// - /// Hosts extension methods for classes. + /// Activates the item if it implements , otherwise does nothing. /// - public static class ScreenExtensions - { - /// - /// Activates the item if it implements , otherwise does nothing. - /// - /// The potential activatable. - public static Task TryActivateAsync(object potentialActivatable) - => potentialActivatable is IActivate activator ? activator.ActivateAsync(CancellationToken.None) : Task.FromResult(true); - - /// - /// Activates the item if it implements , otherwise does nothing. - /// - /// The potential activatable. - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation. - public static Task TryActivateAsync(object potentialActivatable, CancellationToken cancellationToken) - => potentialActivatable is IActivate activator ? activator.ActivateAsync(cancellationToken) : Task.FromResult(true); - - /// - /// Deactivates the item if it implements , otherwise does nothing. - /// - /// The potential deactivatable. - /// Indicates whether or not to close the item after deactivating it. - /// A task that represents the asynchronous operation. - public static Task TryDeactivateAsync(object potentialDeactivatable, bool close) - => potentialDeactivatable is IDeactivate deactivator ? deactivator.DeactivateAsync(close, CancellationToken.None) : Task.FromResult(true); - - /// - /// Deactivates the item if it implements , otherwise does nothing. - /// - /// The potential deactivatable. - /// Indicates whether or not to close the item after deactivating it. - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation. - public static Task TryDeactivateAsync(object potentialDeactivatable, bool close, CancellationToken cancellationToken) - => potentialDeactivatable is IDeactivate deactivator ? deactivator.DeactivateAsync(close, cancellationToken) : Task.FromResult(true); - - /// - /// Closes the specified item. - /// - /// The conductor. - /// The item to close. - /// A task that represents the asynchronous operation. - public static Task CloseItemAsync(this IConductor conductor, object item) - => conductor.DeactivateItemAsync(item, true, CancellationToken.None); - - /// - /// Closes the specified item. - /// - /// The conductor. - /// The item to close. - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation. - public static Task CloseItemAsync(this IConductor conductor, object item, CancellationToken cancellationToken) - => conductor.DeactivateItemAsync(item, true, cancellationToken); - - /// - /// Closes the specified item. - /// - /// The conductor. - /// The item to close. - /// A task that represents the asynchronous operation. - public static Task CloseItemAsync(this ConductorBase conductor, T item) - where T : class - => conductor.DeactivateItemAsync(item, true, CancellationToken.None); - - /// - /// Closes the specified item. - /// - /// The conductor. - /// The item to close. - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation. - public static Task CloseItemAsync(this ConductorBase conductor, T item, CancellationToken cancellationToken) - where T : class - => conductor.DeactivateItemAsync(item, true, cancellationToken); - - /// - /// Activates a child whenever the specified parent is activated. - /// - ///The child to activate. - ///The parent whose activation triggers the child's activation. - public static void ActivateWith(this IActivate child, IActivate parent) - { - var childReference = new WeakReference(child); - - async Task OnParentActivated(object s, ActivationEventArgs e) - { - var activatable = (IActivate)childReference.Target; - if (activatable == null) - ((IActivate)s).Activated -= OnParentActivated; - else - await activatable.ActivateAsync(CancellationToken.None); - } + /// The potential activatable. + public static Task TryActivateAsync(object potentialActivatable) + => potentialActivatable is IActivate activator ? activator.ActivateAsync(CancellationToken.None) : Task.FromResult(true); - parent.Activated += OnParentActivated; - } + /// + /// Activates the item if it implements , otherwise does nothing. + /// + /// The potential activatable. + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation. + public static Task TryActivateAsync(object potentialActivatable, CancellationToken cancellationToken) + => potentialActivatable is IActivate activator ? activator.ActivateAsync(cancellationToken) : Task.FromResult(true); - /// - /// Deactivates a child whenever the specified parent is deactivated. - /// - ///The child to deactivate. - ///The parent whose deactivation triggers the child's deactivation. - public static void DeactivateWith(this IDeactivate child, IDeactivate parent) - { - var childReference = new WeakReference(child); - - async Task OnParentDeactivated(object s, DeactivationEventArgs e) - { - var deactivatable = (IDeactivate)childReference.Target; - if (deactivatable == null) - ((IDeactivate)s).Deactivated -= OnParentDeactivated; - else - await deactivatable.DeactivateAsync(e.WasClosed, CancellationToken.None); - } + /// + /// Deactivates the item if it implements , otherwise does nothing. + /// + /// The potential deactivatable. + /// Indicates whether or not to close the item after deactivating it. + /// A task that represents the asynchronous operation. + public static Task TryDeactivateAsync(object potentialDeactivatable, bool close) + => potentialDeactivatable is IDeactivate deactivator ? deactivator.DeactivateAsync(close, CancellationToken.None) : Task.FromResult(true); + + /// + /// Deactivates the item if it implements , otherwise does nothing. + /// + /// The potential deactivatable. + /// Indicates whether or not to close the item after deactivating it. + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation. + public static Task TryDeactivateAsync(object potentialDeactivatable, bool close, CancellationToken cancellationToken) + => potentialDeactivatable is IDeactivate deactivator ? deactivator.DeactivateAsync(close, cancellationToken) : Task.FromResult(true); + + /// + /// Closes the specified item. + /// + /// The conductor. + /// The item to close. + /// A task that represents the asynchronous operation. + public static Task CloseItemAsync(this IConductor conductor, object item) + => conductor.DeactivateItemAsync(item, true, CancellationToken.None); + + /// + /// Closes the specified item. + /// + /// The conductor. + /// The item to close. + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation. + public static Task CloseItemAsync(this IConductor conductor, object item, CancellationToken cancellationToken) + => conductor.DeactivateItemAsync(item, true, cancellationToken); + + /// + /// Closes the specified item. + /// + /// The conductor. + /// The item to close. + /// A task that represents the asynchronous operation. + public static Task CloseItemAsync(this ConductorBase conductor, T item) + where T : class + => conductor.DeactivateItemAsync(item, true, CancellationToken.None); + + /// + /// Closes the specified item. + /// + /// The conductor. + /// The item to close. + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation. + public static Task CloseItemAsync(this ConductorBase conductor, T item, CancellationToken cancellationToken) + where T : class + => conductor.DeactivateItemAsync(item, true, cancellationToken); + + /// + /// Activates a child whenever the specified parent is activated. + /// + ///The child to activate. + ///The parent whose activation triggers the child's activation. + public static void ActivateWith(this IActivate child, IActivate parent) { + var childReference = new WeakReference(child); - parent.Deactivated += OnParentDeactivated; + async Task OnParentActivated(object s, ActivationEventArgs e) { + var activatable = (IActivate)childReference.Target; + if (activatable == null) { + ((IActivate)s).Activated -= OnParentActivated; + } else { + await activatable.ActivateAsync(CancellationToken.None); + } } - /// - /// Activates and Deactivates a child whenever the specified parent is Activated or Deactivated. - /// - ///The child to activate/deactivate. - ///The parent whose activation/deactivation triggers the child's activation/deactivation. - public static void ConductWith(this TChild child, TParent parent) - where TChild : IActivate, IDeactivate - where TParent : IActivate, IDeactivate - { - child.ActivateWith(parent); - child.DeactivateWith(parent); + parent.Activated += OnParentActivated; + } + + /// + /// Deactivates a child whenever the specified parent is deactivated. + /// + ///The child to deactivate. + ///The parent whose deactivation triggers the child's deactivation. + public static void DeactivateWith(this IDeactivate child, IDeactivate parent) { + var childReference = new WeakReference(child); + + async Task OnParentDeactivated(object s, DeactivationEventArgs e) { + var deactivatable = (IDeactivate)childReference.Target; + if (deactivatable == null) { + ((IDeactivate)s).Deactivated -= OnParentDeactivated; + } else { + await deactivatable.DeactivateAsync(e.WasClosed, CancellationToken.None); + } } + + parent.Deactivated += OnParentDeactivated; + } + + /// + /// Activates and Deactivates a child whenever the specified parent is Activated or Deactivated. + /// + ///The child to activate/deactivate. + ///The parent whose activation/deactivation triggers the child's activation/deactivation. + public static void ConductWith(this TChild child, TParent parent) + where TChild : IActivate, IDeactivate + where TParent : IActivate, IDeactivate { + child.ActivateWith(parent); + child.DeactivateWith(parent); } } diff --git a/src/Caliburn.Micro.Core/Screen/Screen.cs b/src/Caliburn.Micro.Core/Screen/Screen.cs index 58ce608c6..99806ca52 100644 --- a/src/Caliburn.Micro.Core/Screen/Screen.cs +++ b/src/Caliburn.Micro.Core/Screen/Screen.cs @@ -2,210 +2,183 @@ using System.Threading; using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// A base implementation of . +/// +public class Screen : ViewAware, IScreen, IChild { + private static readonly ILog Log = LogManager.GetLog(typeof(Screen)); + private string _displayName; + + private bool _isActive; + private bool _isInitialized; + private object _parent; + + /// + /// Initializes a new instance of the class. + /// + public Screen() + => _displayName = GetType().FullName; + + /// + /// Raised after activation occurs. + /// + public virtual event AsyncEventHandler Activated + = (sender, e) => Task.FromResult(true); + + /// + /// Raised before deactivation. + /// + public virtual event EventHandler AttemptingDeactivation + = (sender, e) => { }; + + /// + /// Raised after deactivation. + /// + public virtual event AsyncEventHandler Deactivated + = (sender, e) => Task.FromResult(true); + + /// + /// Gets a value indicating whether or not this instance is currently initialized. + /// Virtualized in order to help with document oriented view models. + /// + public virtual bool IsInitialized { + get => _isInitialized; + private set { + _isInitialized = value; + NotifyOfPropertyChange(); + } + } + + /// + /// Gets or Sets the Parent . + /// + public virtual object Parent { + get => _parent; + set { + _parent = value; + NotifyOfPropertyChange(); + } + } + /// - /// A base implementation of . + /// Gets or Sets the Display Name. /// - public class Screen : ViewAware, IScreen, IChild - { - private static readonly ILog Log = LogManager.GetLog(typeof(Screen)); - private string _displayName; - - private bool _isActive; - private bool _isInitialized; - private object _parent; - - /// - /// Creates an instance of the screen. - /// - public Screen() - => _displayName = GetType().FullName; - - /// - /// Indicates whether or not this instance is currently initialized. - /// Virtualized in order to help with document oriented view models. - /// - public virtual bool IsInitialized - { - get => _isInitialized; - private set - { - _isInitialized = value; - NotifyOfPropertyChange(); - } + public virtual string DisplayName { + get => _displayName; + set { + _displayName = value; + NotifyOfPropertyChange(); } + } - /// - /// Gets or Sets the Parent - /// - public virtual object Parent - { - get => _parent; - set - { - _parent = value; - NotifyOfPropertyChange(); - } + /// + /// Gets a value indicating whether or not this instance is currently active. + /// Virtualized in order to help with document oriented view models. + /// + public virtual bool IsActive { + get => _isActive; + private set { + _isActive = value; + NotifyOfPropertyChange(); } + } - /// - /// Gets or Sets the Display Name - /// - public virtual string DisplayName - { - get => _displayName; - set - { - _displayName = value; - NotifyOfPropertyChange(); - } + async Task IActivate.ActivateAsync(CancellationToken cancellationToken) { + if (IsActive) { + return; } - /// - /// Indicates whether or not this instance is currently active. - /// Virtualized in order to help with document oriented view models. - /// - public virtual bool IsActive - { - get => _isActive; - private set - { - _isActive = value; - NotifyOfPropertyChange(); - } + bool initialized = false; + + if (!IsInitialized) { + await OnInitializeAsync(cancellationToken); + IsInitialized = initialized = true; } - /// - /// Raised after activation occurs. - /// - public virtual event AsyncEventHandler Activated - = delegate - { - return Task.FromResult(true); - }; - - /// - /// Raised before deactivation. - /// - public virtual event EventHandler AttemptingDeactivation - = delegate - { }; - - /// - /// Raised after deactivation. - /// - public virtual event AsyncEventHandler Deactivated - = delegate - { - return Task.FromResult(true); - }; - - async Task IActivate.ActivateAsync(CancellationToken cancellationToken) - { - if (IsActive) - return; - - var initialized = false; - - if (!IsInitialized) - { - await OnInitializeAsync(cancellationToken); - IsInitialized = initialized = true; - } - - Log.Info("Activating {0}.", this); - await OnActivateAsync(cancellationToken); - IsActive = true; - await OnActivatedAsync(cancellationToken); - - await (Activated?.InvokeAllAsync(this, new ActivationEventArgs - { - WasInitialized = initialized - }) ?? Task.FromResult(true)); + Log.Info("Activating {0}.", this); + await OnActivateAsync(cancellationToken); + IsActive = true; + await OnActivatedAsync(cancellationToken); + + await (Activated?.InvokeAllAsync(this, new ActivationEventArgs { + WasInitialized = initialized, + }) ?? Task.FromResult(true)); + } + + async Task IDeactivate.DeactivateAsync(bool close, CancellationToken cancellationToken) { + if (!IsActive && (!IsInitialized || !close)) { + return; } - async Task IDeactivate.DeactivateAsync(bool close, CancellationToken cancellationToken) - { - if (!IsActive && (!IsInitialized || !close)) - { - return; - } - - AttemptingDeactivation?.Invoke(this, new DeactivationEventArgs - { - WasClosed = close - }); - - Log.Info("Deactivating {0}.", this); - await OnDeactivateAsync(close, cancellationToken); - IsActive = false; - - await (Deactivated?.InvokeAllAsync(this, new DeactivationEventArgs - { - WasClosed = close - }) ?? Task.FromResult(true)); - - if (!close) - { - return; - } - - Views.Clear(); - Log.Info("Closed {0}.", this); + AttemptingDeactivation?.Invoke(this, new DeactivationEventArgs { + WasClosed = close, + }); + + Log.Info("Deactivating {0}.", this); + await OnDeactivateAsync(close, cancellationToken); + IsActive = false; + + await (Deactivated?.InvokeAllAsync(this, new DeactivationEventArgs { + WasClosed = close, + }) ?? Task.FromResult(true)); + + if (!close) { + return; } - /// - /// Called to check whether or not this instance can close. - /// - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation and holds the value of the close check.. - public virtual Task CanCloseAsync(CancellationToken cancellationToken = default) - => Task.FromResult(true); - - /// - /// Tries to close this instance by asking its Parent to initiate shutdown or by asking its corresponding view to close. - /// Also provides an opportunity to pass a dialog result to it's corresponding view. - /// - /// The dialog result. - public virtual async Task TryCloseAsync(bool? dialogResult = null) - { - if (Parent is IConductor conductor) - { - await conductor.CloseItemAsync(this, CancellationToken.None); - } - - Func closeAction = PlatformProvider.Current.GetViewCloseAction(this, Views.Values, dialogResult); - - await Execute.OnUIThreadAsync(async () => await closeAction(CancellationToken.None)); + Views.Clear(); + Log.Info("Closed {0}.", this); + } + + /// + /// Called to check whether or not this instance can close. + /// + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation and holds the value of the close check.. + public virtual Task CanCloseAsync(CancellationToken cancellationToken = default) + => Task.FromResult(true); + + /// + /// Tries to close this instance by asking its Parent to initiate shutdown or by asking its corresponding view to close. + /// Also provides an opportunity to pass a dialog result to it's corresponding view. + /// + /// The dialog result. + public virtual async Task TryCloseAsync(bool? dialogResult = null) { + if (Parent is IConductor conductor) { + await conductor.CloseItemAsync(this, CancellationToken.None); } - /// - /// Called when initializing. - /// - protected virtual Task OnInitializeAsync(CancellationToken cancellationToken) - => Task.FromResult(true); - - /// - /// Called when activating. - /// - protected virtual Task OnActivateAsync(CancellationToken cancellationToken) - => Task.FromResult(true); - - - /// - /// Called when view has been activated. - /// - protected virtual Task OnActivatedAsync(CancellationToken cancellationToken) - => Task.FromResult(true); - - /// - /// Called when deactivating. - /// - /// Indicates whether this instance will be closed. - /// The cancellation token to cancel operation. - /// A task that represents the asynchronous operation. - protected virtual Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) - => Task.FromResult(true); + Func closeAction = PlatformProvider.Current.GetViewCloseAction(this, Views.Values, dialogResult); + + await Execute.OnUIThreadAsync(async () => await closeAction(CancellationToken.None)); } + + /// + /// Called when initializing. + /// + protected virtual Task OnInitializeAsync(CancellationToken cancellationToken) + => Task.FromResult(true); + + /// + /// Called when activating. + /// + protected virtual Task OnActivateAsync(CancellationToken cancellationToken) + => Task.FromResult(true); + + /// + /// Called when view has been activated. + /// + protected virtual Task OnActivatedAsync(CancellationToken cancellationToken) + => Task.FromResult(true); + + /// + /// Called when deactivating. + /// + /// Indicates whether this instance will be closed. + /// The cancellation token to cancel operation. + /// A task that represents the asynchronous operation. + protected virtual Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) + => Task.FromResult(true); } diff --git a/src/Caliburn.Micro.Core/Types/BindableCollection.cs b/src/Caliburn.Micro.Core/Types/BindableCollection.cs index 1fbe1495b..8dda7987e 100644 --- a/src/Caliburn.Micro.Core/Types/BindableCollection.cs +++ b/src/Caliburn.Micro.Core/Types/BindableCollection.cs @@ -4,275 +4,249 @@ using System.Collections.Specialized; using System.ComponentModel; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// A base collection class that supports automatic UI thread marshalling. +/// +/// The type of elements contained in the collection. +public class BindableCollection : ObservableCollection, IObservableCollection { /// - /// A base collection class that supports automatic UI thread marshalling. + /// Initializes a new instance of the class. /// - /// The type of elements contained in the collection. - public class BindableCollection : ObservableCollection, IObservableCollection - { - /// - /// Initializes a new instance of the class. - /// - public BindableCollection() - => IsNotifying = true; - - /// - /// Initializes a new instance of the class. - /// - /// The collection from which the elements are copied. - public BindableCollection(IEnumerable collection) - : base(collection) - => IsNotifying = true; - - /// - /// Enables/Disables property change notification. - /// - public bool IsNotifying { get; set; } - - /// - /// Notifies subscribers of the property change. - /// - /// Name of the property. - public virtual void NotifyOfPropertyChange(string propertyName) - { - if (!IsNotifying) - { - return; - } + public BindableCollection() + => IsNotifying = true; - if (!PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) - { - OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); + /// + /// Initializes a new instance of the class. + /// + /// The collection from which the elements are copied. + public BindableCollection(IEnumerable collection) + : base(collection) + => IsNotifying = true; - return; - } + /// + /// Gets or sets a value indicating whether to Enable/Disable property change notification. + /// + public bool IsNotifying { get; set; } - OnUIThread(() => OnPropertyChanged(new PropertyChangedEventArgs(propertyName))); + /// + /// Notifies subscribers of the property change. + /// + /// Name of the property. + public virtual void NotifyOfPropertyChange(string propertyName) { + if (!IsNotifying) { + return; } - /// - /// Raises a change notification indicating that all bindings should be refreshed. - /// - public void Refresh() - { - if (!PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) - { - OnPropertyChanged(new PropertyChangedEventArgs("Count")); - OnPropertyChanged(new PropertyChangedEventArgs("Item[]")); - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); - - return; - } + if (!PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) { + OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); - OnUIThread(() => - { - OnPropertyChanged(new PropertyChangedEventArgs("Count")); - OnPropertyChanged(new PropertyChangedEventArgs("Item[]")); - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); - }); + return; } - /// - /// Inserts the item to the specified position. - /// - /// The index to insert at. - /// The item to be inserted. - protected override sealed void InsertItem(int index, T item) - { - if (!PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) - { - InsertItemBase(index, item); + OnUIThread(() => OnPropertyChanged(new PropertyChangedEventArgs(propertyName))); + } - return; - } + /// + /// Raises a change notification indicating that all bindings should be refreshed. + /// + public void Refresh() { + if (!PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) { + OnPropertyChanged(new PropertyChangedEventArgs("Count")); + OnPropertyChanged(new PropertyChangedEventArgs("Item[]")); + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); - OnUIThread(() => InsertItemBase(index, item)); + return; } - /// - /// Exposes the base implementation of the function. - /// - /// The index. - /// The item. - /// - /// Used to avoid compiler warning regarding unverifiable code. - /// - protected virtual void InsertItemBase(int index, T item) - => base.InsertItem(index, item); - - /// - /// Sets the item at the specified position. - /// - /// The index to set the item at. - /// The item to set. - protected override sealed void SetItem(int index, T item) - { - if (!PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) - { - SetItemBase(index, item); - - return; + OnUIThread(() => { + OnPropertyChanged(new PropertyChangedEventArgs("Count")); + OnPropertyChanged(new PropertyChangedEventArgs("Item[]")); + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); + }); + } + + /// + /// Adds the range. + /// + /// The items. + public virtual void AddRange(IEnumerable items) { + void AddRange() { + bool previousNotificationSetting = IsNotifying; + IsNotifying = false; + int index = Count; + foreach (T item in items) { + InsertItemBase(index, item); + index++; } - OnUIThread(() => SetItemBase(index, item)); + IsNotifying = previousNotificationSetting; + + OnPropertyChanged(new PropertyChangedEventArgs("Count")); + OnPropertyChanged(new PropertyChangedEventArgs("Item[]")); + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } - /// - /// Exposes the base implementation of the function. - /// - /// The index. - /// The item. - /// - /// Used to avoid compiler warning regarding unverifiable code. - /// - protected virtual void SetItemBase(int index, T item) - => base.SetItem(index, item); - - /// - /// Removes the item at the specified position. - /// - /// The position used to identify the item to remove. - protected override sealed void RemoveItem(int index) - { - if (!PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) - { - RemoveItemBase(index); - - return; - } + if (!PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) { + AddRange(); - OnUIThread(() => RemoveItemBase(index)); + return; } - /// - /// Exposes the base implementation of the function. - /// - /// The index. - /// - /// Used to avoid compiler warning regarding unverifiable code. - /// - protected virtual void RemoveItemBase(int index) - => base.RemoveItem(index); - - /// - /// Clears the items contained by the collection. - /// - protected override sealed void ClearItems() - => OnUIThread(ClearItemsBase); - - /// - /// Exposes the base implementation of the function. - /// - /// - /// Used to avoid compiler warning regarding unverifiable code. - /// - protected virtual void ClearItemsBase() - => base.ClearItems(); - - /// - /// Raises the event with the provided arguments. - /// - /// Arguments of the event being raised. - protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) - { - if (!IsNotifying) - { - return; + OnUIThread(AddRange); + } + + /// + /// Removes the range. + /// + /// The items. + public virtual void RemoveRange(IEnumerable items) { + void RemoveRange() { + bool previousNotificationSetting = IsNotifying; + IsNotifying = false; + foreach (T item in items) { + int index = IndexOf(item); + if (index >= 0) { + RemoveItemBase(index); + } } - base.OnCollectionChanged(e); + IsNotifying = previousNotificationSetting; + + OnPropertyChanged(new PropertyChangedEventArgs("Count")); + OnPropertyChanged(new PropertyChangedEventArgs("Item[]")); + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } - /// - /// Raises the PropertyChanged event with the provided arguments. - /// - /// The event data to report in the event. - protected override void OnPropertyChanged(PropertyChangedEventArgs e) - { - if (!IsNotifying) - { - return; - } + if (!PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) { + RemoveRange(); - base.OnPropertyChanged(e); + return; } - /// - /// Adds the range. - /// - /// The items. - public virtual void AddRange(IEnumerable items) - { - void AddRange() - { - var previousNotificationSetting = IsNotifying; - IsNotifying = false; - var index = Count; - foreach (T item in items) - { - InsertItemBase(index, item); - index++; - } - IsNotifying = previousNotificationSetting; + OnUIThread(RemoveRange); + } - OnPropertyChanged(new PropertyChangedEventArgs("Count")); - OnPropertyChanged(new PropertyChangedEventArgs("Item[]")); - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); - } + /// + /// Executes the given action on the UI thread. + /// + /// An extension point for subclasses to customise how property change notifications are handled. + protected virtual void OnUIThread(System.Action action) + => action.OnUIThread(); - if (!PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) - { - AddRange(); + /// + /// Inserts the item to the specified position. + /// + /// The index to insert at. + /// The item to be inserted. + protected sealed override void InsertItem(int index, T item) { + if (!PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) { + InsertItemBase(index, item); - return; - } + return; + } + + OnUIThread(() => InsertItemBase(index, item)); + } + + /// + /// Exposes the base implementation of the function. + /// + /// The index. + /// The item. + /// + /// Used to avoid compiler warning regarding unverifiable code. + /// + protected virtual void InsertItemBase(int index, T item) + => base.InsertItem(index, item); - OnUIThread(AddRange); + /// + /// Sets the item at the specified position. + /// + /// The index to set the item at. + /// The item to set. + protected sealed override void SetItem(int index, T item) { + if (!PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) { + SetItemBase(index, item); + + return; } - /// - /// Removes the range. - /// - /// The items. - public virtual void RemoveRange(IEnumerable items) - { - void RemoveRange() - { - var previousNotificationSetting = IsNotifying; - IsNotifying = false; - foreach (T item in items) - { - var index = IndexOf(item); - if (index >= 0) - { - RemoveItemBase(index); - } - } - IsNotifying = previousNotificationSetting; + OnUIThread(() => SetItemBase(index, item)); + } - OnPropertyChanged(new PropertyChangedEventArgs("Count")); - OnPropertyChanged(new PropertyChangedEventArgs("Item[]")); - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); - } + /// + /// Exposes the base implementation of the function. + /// + /// The index. + /// The item. + /// + /// Used to avoid compiler warning regarding unverifiable code. + /// + protected virtual void SetItemBase(int index, T item) + => base.SetItem(index, item); - if (!PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) - { - RemoveRange(); + /// + /// Removes the item at the specified position. + /// + /// The position used to identify the item to remove. + protected sealed override void RemoveItem(int index) { + if (!PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) { + RemoveItemBase(index); - return; - } + return; + } - OnUIThread(RemoveRange); + OnUIThread(() => RemoveItemBase(index)); + } + + /// + /// Exposes the base implementation of the function. + /// + /// The index. + /// + /// Used to avoid compiler warning regarding unverifiable code. + /// + protected virtual void RemoveItemBase(int index) + => base.RemoveItem(index); + + /// + /// Clears the items contained by the collection. + /// + protected sealed override void ClearItems() + => OnUIThread(ClearItemsBase); + + /// + /// Exposes the base implementation of the function. + /// + /// + /// Used to avoid compiler warning regarding unverifiable code. + /// + protected virtual void ClearItemsBase() + => base.ClearItems(); + + /// + /// Raises the event with the provided arguments. + /// + /// Arguments of the event being raised. + protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) { + if (!IsNotifying) { + return; + } + + base.OnCollectionChanged(e); + } + + /// + /// Raises the PropertyChanged event with the provided arguments. + /// + /// The event data to report in the event. + protected override void OnPropertyChanged(PropertyChangedEventArgs e) { + if (!IsNotifying) { + return; } - /// - /// Executes the given action on the UI thread - /// - /// An extension point for subclasses to customise how property change notifications are handled. - /// - protected virtual void OnUIThread(System.Action action) - => action.OnUIThread(); + base.OnPropertyChanged(e); } } diff --git a/src/Caliburn.Micro.Core/Types/INotifyPropertyChangedEx.cs b/src/Caliburn.Micro.Core/Types/INotifyPropertyChangedEx.cs index 93c5960ed..af3954b4e 100644 --- a/src/Caliburn.Micro.Core/Types/INotifyPropertyChangedEx.cs +++ b/src/Caliburn.Micro.Core/Types/INotifyPropertyChangedEx.cs @@ -1,26 +1,24 @@ using System.ComponentModel; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Extends such that the change event can be raised by external parties. +/// +public interface INotifyPropertyChangedEx : INotifyPropertyChanged { /// - /// Extends such that the change event can be raised by external parties. + /// Enables/Disables property change notification. /// - public interface INotifyPropertyChangedEx : INotifyPropertyChanged - { - /// - /// Enables/Disables property change notification. - /// - bool IsNotifying { get; set; } + bool IsNotifying { get; set; } - /// - /// Notifies subscribers of the property change. - /// - /// Name of the property. - void NotifyOfPropertyChange(string propertyName); + /// + /// Notifies subscribers of the property change. + /// + /// Name of the property. + void NotifyOfPropertyChange(string propertyName); - /// - /// Raises a change notification indicating that all bindings should be refreshed. - /// - void Refresh(); - } + /// + /// Raises a change notification indicating that all bindings should be refreshed. + /// + void Refresh(); } diff --git a/src/Caliburn.Micro.Core/Types/IObservableCollection.cs b/src/Caliburn.Micro.Core/Types/IObservableCollection.cs index 1f1af4870..ae8148c6f 100644 --- a/src/Caliburn.Micro.Core/Types/IObservableCollection.cs +++ b/src/Caliburn.Micro.Core/Types/IObservableCollection.cs @@ -1,24 +1,22 @@ using System.Collections.Generic; using System.Collections.Specialized; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Represents a collection that is observable. +/// +/// The type of elements contained in the collection. +public interface IObservableCollection : IList, INotifyPropertyChangedEx, INotifyCollectionChanged { /// - /// Represents a collection that is observable. + /// Adds the range. /// - /// The type of elements contained in the collection. - public interface IObservableCollection : IList, INotifyPropertyChangedEx, INotifyCollectionChanged - { - /// - /// Adds the range. - /// - /// The items. - void AddRange(IEnumerable items); + /// The items. + void AddRange(IEnumerable items); - /// - /// Removes the range. - /// - /// The items. - void RemoveRange(IEnumerable items); - } + /// + /// Removes the range. + /// + /// The items. + void RemoveRange(IEnumerable items); } diff --git a/src/Caliburn.Micro.Core/Types/PropertyChangedBase.cs b/src/Caliburn.Micro.Core/Types/PropertyChangedBase.cs index 5f9bc62ad..52a690a82 100644 --- a/src/Caliburn.Micro.Core/Types/PropertyChangedBase.cs +++ b/src/Caliburn.Micro.Core/Types/PropertyChangedBase.cs @@ -4,102 +4,93 @@ using System.Linq.Expressions; using System.Runtime.Serialization; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// A base class that implements the infrastructure for property change notification and automatically performs UI thread marshalling. +/// +[DataContract] +public class PropertyChangedBase : INotifyPropertyChangedEx { + /// + /// Initializes a new instance of the class. + /// + public PropertyChangedBase() + => IsNotifying = true; + + /// + /// Occurs when a property value changes. + /// + public virtual event PropertyChangedEventHandler PropertyChanged; + + /// + /// Gets or sets a value indicating whether to Enable/Disable property change notification. + /// Virtualized in order to help with document oriented view models. + /// + public virtual bool IsNotifying { get; set; } + + /// + /// Raises a change notification indicating that all bindings should be refreshed. + /// + public virtual void Refresh() + => NotifyOfPropertyChange(string.Empty); + /// - /// A base class that implements the infrastructure for property change notification and automatically performs UI thread marshalling. + /// Notifies subscribers of the property change. /// - [DataContract] - public class PropertyChangedBase : INotifyPropertyChangedEx - { - /// - /// Creates an instance of . - /// - public PropertyChangedBase() - => IsNotifying = true; - - /// - /// Occurs when a property value changes. - /// - public virtual event PropertyChangedEventHandler PropertyChanged; - - /// - /// Enables/Disables property change notification. - /// Virtualized in order to help with document oriented view models. - /// - public virtual bool IsNotifying { get; set; } - - /// - /// Raises a change notification indicating that all bindings should be refreshed. - /// - public virtual void Refresh() - => NotifyOfPropertyChange(string.Empty); - - /// - /// Notifies subscribers of the property change. - /// - /// Name of the property. - public virtual void NotifyOfPropertyChange([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) - { - if (!IsNotifying || PropertyChanged == null) - { - return; - } - - if (!PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) - { - OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); - - return; - } - - OnUIThread(() => OnPropertyChanged(new PropertyChangedEventArgs(propertyName))); + /// Name of the property. + public virtual void NotifyOfPropertyChange([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) { + if (!IsNotifying || PropertyChanged == null) { + return; + } + + if (!PlatformProvider.Current.PropertyChangeNotificationsOnUIThread) { + OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); + + return; } - /// - /// Notifies subscribers of the property change. - /// - /// The type of the property. - /// The property expression. - public void NotifyOfPropertyChange(Expression> property) - => NotifyOfPropertyChange(property.GetMemberInfo().Name); - - /// - /// Raises the event directly. - /// - /// The instance containing the event data. - [EditorBrowsable(EditorBrowsableState.Never)] - protected void OnPropertyChanged(PropertyChangedEventArgs e) - => PropertyChanged?.Invoke(this, e); - - /// - /// Executes the given action on the UI thread - /// - /// An extension point for subclasses to customise how property change notifications are handled. - /// - protected virtual void OnUIThread(System.Action action) - => action.OnUIThread(); - - /// - /// Sets a backing field value and if it's changed raise a notification. - /// - /// The type of the value being set. - /// A reference to the field to update. - /// The new value. - /// The name of the property for change notifications. - /// - public virtual bool Set(ref T oldValue, T newValue, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) - { - if (EqualityComparer.Default.Equals(oldValue, newValue)) - { - return false; - } - - oldValue = newValue; - - NotifyOfPropertyChange(propertyName ?? string.Empty); - - return true; + OnUIThread(() => OnPropertyChanged(new PropertyChangedEventArgs(propertyName))); + } + + /// + /// Notifies subscribers of the property change. + /// + /// The type of the property. + /// The property expression. + public void NotifyOfPropertyChange(Expression> property) + => NotifyOfPropertyChange(property.GetMemberInfo().Name); + + /// + /// Sets a backing field value and if it's changed raise a notification. + /// + /// The type of the value being set. + /// A reference to the field to update. + /// The new value. + /// The name of the property for change notifications. + public virtual bool Set(ref T oldValue, T newValue, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) { + if (EqualityComparer.Default.Equals(oldValue, newValue)) { + return false; } + + oldValue = newValue; + + NotifyOfPropertyChange(propertyName ?? string.Empty); + + return true; } + + /// + /// Raises the event directly. + /// + /// The instance containing the event data. + [EditorBrowsable(EditorBrowsableState.Never)] + protected void OnPropertyChanged(PropertyChangedEventArgs e) + => PropertyChanged?.Invoke(this, e); + + /// + /// Executes the given action on the UI thread. + /// + /// An extension point for subclasses to customise how property change notifications are handled. + protected virtual void OnUIThread(System.Action action) + => action.OnUIThread(); } diff --git a/src/Caliburn.Micro.Core/Types/WeakValueDictionary.cs b/src/Caliburn.Micro.Core/Types/WeakValueDictionary.cs index ab514704a..d611a2704 100644 --- a/src/Caliburn.Micro.Core/Types/WeakValueDictionary.cs +++ b/src/Caliburn.Micro.Core/Types/WeakValueDictionary.cs @@ -3,338 +3,292 @@ using System.Collections.Generic; using System.Linq; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// A dictionary in which the values are weak references. +/// +/// The type of keys in the dictionary. +/// The type of values in the dictionary. +internal sealed class WeakValueDictionary : IDictionary + where TValue : class { + private readonly Dictionary _inner; + private readonly WeakReference _gcSentinel = new(new object()); + /// - /// A dictionary in which the values are weak references. + /// Initializes a new instance of the class that is empty, has the default initial capacity, and uses the default equality comparer for the key type. /// - /// The type of keys in the dictionary. - /// The type of values in the dictionary. - internal sealed class WeakValueDictionary : IDictionary - where TValue : class - { - private readonly Dictionary _inner; - private readonly WeakReference _gcSentinel = new(new object()); - - private bool IsCleanupNeeded() - { - if (_gcSentinel.Target != null) - { - return false; - } + public WeakValueDictionary() + => _inner = new Dictionary(); - _gcSentinel.Target = new object(); - - return true; - } - - private void CleanAbandonedItems() - { - var keysToRemove = _inner.Where(pair => !pair.Value.IsAlive) - .Select(pair => pair.Key) - .ToList(); + /// + /// Initializes a new instance of the class that contains elements copied from the specified and uses the default equality comparer for the key type. + /// + /// The whose elements are copied to the new . + public WeakValueDictionary(IDictionary dictionary) { + _inner = new Dictionary(); + dictionary.Apply(item => _inner.Add(item.Key, new WeakReference(item.Value))); + } - keysToRemove.Apply(key => _inner.Remove(key)); - } + /// + /// Initializes a new instance of the class that contains elements copied from the specified and uses the specified . + /// + /// The whose elements are copied to the new . + /// The implementation to use when comparing keys, or null to use the default for the type of the key. + public WeakValueDictionary(IDictionary dictionary, IEqualityComparer comparer) { + _inner = new Dictionary(comparer); + dictionary.Apply(item => _inner.Add(item.Key, new WeakReference(item.Value))); + } - private void CleanIfNeeded() - { - if (!IsCleanupNeeded()) - { - return; - } - - CleanAbandonedItems(); - } + /// + /// Initializes a new instance of the class that is empty, has the default initial capacity, and uses the specified . + /// + /// The implementation to use when comparing keys, or null to use the default for the type of the key. + public WeakValueDictionary(IEqualityComparer comparer) + => _inner = new Dictionary(comparer); - /// - /// Initializes a new instance of the class that is empty, has the default initial capacity, and uses the default equality comparer for the key type. - /// - public WeakValueDictionary() - => _inner = new Dictionary(); - - /// - /// Initializes a new instance of the class that contains elements copied from the specified and uses the default equality comparer for the key type. - /// - /// The whose elements are copied to the new . - public WeakValueDictionary(IDictionary dictionary) - { - _inner = new Dictionary(); - dictionary.Apply(item => _inner.Add(item.Key, new WeakReference(item.Value))); - } + /// + /// Initializes a new instance of the class that is empty, has the specified initial capacity, and uses the default equality comparer for the key type. + /// + /// The initial number of elements that the can contain. + public WeakValueDictionary(int capacity) + => _inner = new Dictionary(capacity); - /// - /// Initializes a new instance of the class that contains elements copied from the specified and uses the specified . - /// - /// The whose elements are copied to the new . - /// The implementation to use when comparing keys, or null to use the default for the type of the key. - public WeakValueDictionary(IDictionary dictionary, IEqualityComparer comparer) - { - _inner = new Dictionary(comparer); - dictionary.Apply(item => _inner.Add(item.Key, new WeakReference(item.Value))); - } + /// + /// Initializes a new instance of the class that is empty, has the specified initial capacity, and uses the specified . + /// + /// The initial number of elements that the can contain. + /// The implementation to use when comparing keys, or null to use the default for the type of the key. + public WeakValueDictionary(int capacity, IEqualityComparer comparer) + => _inner = new Dictionary(capacity, comparer); - /// - /// Initializes a new instance of the class that is empty, has the default initial capacity, and uses the specified . - /// - /// The implementation to use when comparing keys, or null to use the default for the type of the key. - public WeakValueDictionary(IEqualityComparer comparer) - => _inner = new Dictionary(comparer); - - /// - /// Initializes a new instance of the class that is empty, has the specified initial capacity, and uses the default equality comparer for the key type. - /// - /// The initial number of elements that the can contain. - public WeakValueDictionary(int capacity) - => _inner = new Dictionary(capacity); - - /// - /// Initializes a new instance of the class that is empty, has the specified initial capacity, and uses the specified . - /// - /// The initial number of elements that the can contain. - /// The implementation to use when comparing keys, or null to use the default for the type of the key. - public WeakValueDictionary(int capacity, IEqualityComparer comparer) - => _inner = new Dictionary(capacity, comparer); - - /// - /// Returns an enumerator that iterates through the . - /// - /// The enumerator. - public IEnumerator> GetEnumerator() - { + /// + /// Gets the number of key/value pairs contained in the . + /// + /// + /// Since the items in the dictionary are held by weak reference, the count value + /// cannot be relied upon to guarantee the number of objects that would be discovered via + /// enumeration. Treat the Count as an estimate only. + /// + public int Count { + get { CleanIfNeeded(); - IEnumerable> enumerable - = _inner - .Select(pair => new KeyValuePair(pair.Key, (TValue)pair.Value.Target)) - .Where(pair => pair.Value != null); - return enumerable.GetEnumerator(); - } - IEnumerator IEnumerable.GetEnumerator() - => GetEnumerator(); + return _inner.Count; + } + } - void ICollection>.Add(KeyValuePair item) - => Add(item.Key, item.Value); + /// + /// Gets a collection containing the keys in the . + /// + public ICollection Keys + => _inner.Keys; - /// - /// Removes all keys and values from the . - /// - public void Clear() - => _inner.Clear(); + /// + /// Gets a collection containing the values in the . + /// + public ICollection Values + => new ValueCollection(this); - bool ICollection>.Contains(KeyValuePair item) - { - if (!TryGetValue(item.Key, out TValue value)) - { - return false; - } + bool ICollection>.IsReadOnly + => false; - return value == item.Value; + /// + /// Gets or sets the value associated with the specified key. + /// + /// The key of the value to get or set. + /// + /// The value associated with the specified key. If the specified key is not found, a get operation throws a , + /// and a set operation creates a new element with the specified key. + /// + public TValue this[TKey key] { + get => TryGetValue(key, out TValue result) + ? result + : throw new KeyNotFoundException(); + set { + CleanIfNeeded(); + _inner[key] = new WeakReference(value); } + } - void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) - { - if (array == null) - { - throw new ArgumentNullException(nameof(array)); - } - - if (arrayIndex < 0 || arrayIndex >= array.Length) - { - throw new ArgumentOutOfRangeException(nameof(arrayIndex)); - } + /// + /// Returns an enumerator that iterates through the . + /// + /// The enumerator. + public IEnumerator> GetEnumerator() { + CleanIfNeeded(); + IEnumerable> enumerable + = _inner + .Select(pair => new KeyValuePair(pair.Key, (TValue)pair.Value.Target)) + .Where(pair => pair.Value != null); + return enumerable.GetEnumerator(); + } - if ((arrayIndex + Count) > array.Length) - { - throw new ArgumentException("The number of elements in the source collection is greater than the available space from arrayIndex to the end of the destination array."); - } + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); - this.ToArray().CopyTo(array, arrayIndex); - } + void ICollection>.Add(KeyValuePair item) + => Add(item.Key, item.Value); - bool ICollection>.Remove(KeyValuePair item) - { - if (!TryGetValue(item.Key, out TValue value)) - { - return false; - } + /// + /// Removes all keys and values from the . + /// + public void Clear() + => _inner.Clear(); - if (value != item.Value) - { - return false; - } + bool ICollection>.Contains(KeyValuePair item) + => TryGetValue(item.Key, out TValue value) && value == item.Value; - return _inner.Remove(item.Key); + void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) { + if (array == null) { + throw new ArgumentNullException(nameof(array)); } - /// - /// Gets the number of key/value pairs contained in the . - /// - /// - /// Since the items in the dictionary are held by weak reference, the count value - /// cannot be relied upon to guarantee the number of objects that would be discovered via - /// enumeration. Treat the Count as an estimate only. - /// - public int Count - { - get - { - CleanIfNeeded(); - - return _inner.Count; - } + if (arrayIndex < 0 || arrayIndex >= array.Length) { + throw new ArgumentOutOfRangeException(nameof(arrayIndex)); } - bool ICollection>.IsReadOnly - => false; - - /// - /// Adds the specified key and value to the dictionary. - /// - /// The key of the element to add. - /// The value of the element to add. The value can be null for reference types. - public void Add(TKey key, TValue value) - { - CleanIfNeeded(); - _inner.Add(key, new WeakReference(value)); + if ((arrayIndex + Count) > array.Length) { + throw new ArgumentException("The number of elements in the source collection is greater than the available space from arrayIndex to the end of the destination array."); } - /// - /// Determines whether the contains the specified key. - /// - /// The key to locate in the . - /// - public bool ContainsKey(TKey key) - => TryGetValue(key, out _); - - /// - /// Removes the value with the specified key from the . - /// - /// The key of the element to remove. - /// true if the element is successfully found and removed; otherwise, false. This method returns false if key is not found in the . - public bool Remove(TKey key) - { - CleanIfNeeded(); + this.ToArray().CopyTo(array, arrayIndex); + } - return _inner.Remove(key); - } + bool ICollection>.Remove(KeyValuePair item) + => TryGetValue(item.Key, out TValue value) && + value == item.Value && + _inner.Remove(item.Key); - /// - /// Gets the value associated with the specified key. - /// - /// The key of the value to get. - /// - /// When this method returns, contains the value associated with the specified key, - /// if the key is found; otherwise, the default value for the type of the value parameter. - /// This parameter is passed uninitialized. - /// true if the contains an element with the specified key; otherwise, false. - public bool TryGetValue(TKey key, out TValue value) - { - CleanIfNeeded(); - if (!_inner.TryGetValue(key, out WeakReference wr)) - { - value = null; + /// + /// Adds the specified key and value to the dictionary. + /// + /// The key of the element to add. + /// The value of the element to add. The value can be null for reference types. + public void Add(TKey key, TValue value) { + CleanIfNeeded(); + _inner.Add(key, new WeakReference(value)); + } - return false; - } + /// + /// Determines whether the contains the specified key. + /// + /// The key to locate in the . + public bool ContainsKey(TKey key) + => TryGetValue(key, out _); - var result = (TValue)wr.Target; - if (result != null) - { - value = result; + /// + /// Removes the value with the specified key from the . + /// + /// The key of the element to remove. + /// true if the element is successfully found and removed; otherwise, false. This method returns false if key is not found in the . + public bool Remove(TKey key) { + CleanIfNeeded(); - return true; - } + return _inner.Remove(key); + } - _inner.Remove(key); + /// + /// Gets the value associated with the specified key. + /// + /// The key of the value to get. + /// + /// When this method returns, contains the value associated with the specified key, + /// if the key is found; otherwise, the default value for the type of the value parameter. + /// This parameter is passed uninitialized. + /// true if the contains an element with the specified key; otherwise, false. + public bool TryGetValue(TKey key, out TValue value) { + CleanIfNeeded(); + if (!_inner.TryGetValue(key, out WeakReference wr)) { value = null; return false; } - /// - /// Gets or sets the value associated with the specified key. - /// - /// The key of the value to get or set. - /// - /// The value associated with the specified key. If the specified key is not found, a get operation throws a , - /// and a set operation creates a new element with the specified key. - /// - public TValue this[TKey key] - { - get => TryGetValue(key, out TValue result) - ? result - : throw new KeyNotFoundException(); - set - { - CleanIfNeeded(); - _inner[key] = new WeakReference(value); - } + var result = (TValue)wr.Target; + if (result != null) { + value = result; + + return true; } - /// - /// Gets a collection containing the keys in the . - /// - public ICollection Keys - => _inner.Keys; + _inner.Remove(key); + value = null; - /// - /// Gets a collection containing the values in the . - /// - public ICollection Values - => new ValueCollection(this); + return false; + } - private sealed class ValueCollection : ICollection - { - private readonly WeakValueDictionary _inner; + private bool IsCleanupNeeded() { + if (_gcSentinel.Target != null) { + return false; + } - public ValueCollection(WeakValueDictionary dictionary) - => _inner = dictionary; + _gcSentinel.Target = new object(); - public IEnumerator GetEnumerator() - => _inner.Select(pair => pair.Value).GetEnumerator(); + return true; + } - IEnumerator IEnumerable.GetEnumerator() - => GetEnumerator(); + private void CleanAbandonedItems() { + var keysToRemove = _inner.Where(pair => !pair.Value.IsAlive) + .Select(pair => pair.Key) + .ToList(); - void ICollection.Add(TValue item) - => throw new NotSupportedException(); + keysToRemove.Apply(key => _inner.Remove(key)); + } + + private void CleanIfNeeded() { + if (!IsCleanupNeeded()) { + return; + } - void ICollection.Clear() - => throw new NotSupportedException(); + CleanAbandonedItems(); + } + + private sealed class ValueCollection : ICollection { + private readonly WeakValueDictionary _inner; - bool ICollection.Contains(TValue item) - => _inner.Any(pair => pair.Value == item); + public ValueCollection(WeakValueDictionary dictionary) + => _inner = dictionary; - public void CopyTo(TValue[] array, int arrayIndex) - { - if (array == null) - { - throw new ArgumentNullException(nameof(array)); - } + public int Count + => _inner.Count; - if (arrayIndex < 0 || arrayIndex >= array.Length) - { - throw new ArgumentOutOfRangeException(nameof(arrayIndex)); - } + bool ICollection.IsReadOnly + => true; - if ((arrayIndex + Count) > array.Length) - { - throw new ArgumentException( - "The number of elements in the source collection is greater than the available space from arrayIndex to the end of the destination array."); - } + public IEnumerator GetEnumerator() + => _inner.Select(pair => pair.Value).GetEnumerator(); - this.ToArray().CopyTo(array, arrayIndex); + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + void ICollection.Add(TValue item) + => throw new NotSupportedException(); + + void ICollection.Clear() + => throw new NotSupportedException(); + + bool ICollection.Contains(TValue item) + => _inner.Any(pair => pair.Value == item); + + public void CopyTo(TValue[] array, int arrayIndex) { + if (array == null) { + throw new ArgumentNullException(nameof(array)); } - bool ICollection.Remove(TValue item) - => throw new NotSupportedException(); + if (arrayIndex < 0 || arrayIndex >= array.Length) { + throw new ArgumentOutOfRangeException(nameof(arrayIndex)); + } - public int Count - => _inner.Count; + if ((arrayIndex + Count) > array.Length) { + throw new ArgumentException( + "The number of elements in the source collection is greater than the available space from arrayIndex to the end of the destination array."); + } - bool ICollection.IsReadOnly - => true; + this.ToArray().CopyTo(array, arrayIndex); } + + bool ICollection.Remove(TValue item) + => throw new NotSupportedException(); } } diff --git a/src/Caliburn.Micro.Core/ViewAware/Contracts/IViewAware.cs b/src/Caliburn.Micro.Core/ViewAware/Contracts/IViewAware.cs index 5b82017a3..e1a7b5a37 100644 --- a/src/Caliburn.Micro.Core/ViewAware/Contracts/IViewAware.cs +++ b/src/Caliburn.Micro.Core/ViewAware/Contracts/IViewAware.cs @@ -1,29 +1,27 @@ using System; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// Denotes a class which is aware of its view(s). +/// +public interface IViewAware { /// - /// Denotes a class which is aware of its view(s). + /// Raised when a view is attached. /// - public interface IViewAware - { - /// - /// Attaches a view to this instance. - /// - /// The view. - /// The context in which the view appears. - void AttachView(object view, object context = null); + event EventHandler ViewAttached; - /// - /// Gets a view previously attached to this instance. - /// - /// The context denoting which view to retrieve. - /// The view. - object GetView(object context = null); + /// + /// Attaches a view to this instance. + /// + /// The view. + /// The context in which the view appears. + void AttachView(object view, object context = null); - /// - /// Raised when a view is attached. - /// - event EventHandler ViewAttached; - } + /// + /// Gets a view previously attached to this instance. + /// + /// The context denoting which view to retrieve. + /// The view. + object GetView(object context = null); } diff --git a/src/Caliburn.Micro.Core/ViewAware/EventArgs/ViewAttachedEventArgs.cs b/src/Caliburn.Micro.Core/ViewAware/EventArgs/ViewAttachedEventArgs.cs index 6a4e7cf42..7b695ade3 100644 --- a/src/Caliburn.Micro.Core/ViewAware/EventArgs/ViewAttachedEventArgs.cs +++ b/src/Caliburn.Micro.Core/ViewAware/EventArgs/ViewAttachedEventArgs.cs @@ -1,20 +1,18 @@ using System; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// The event args for the event. +/// +public class ViewAttachedEventArgs : EventArgs { /// - /// The event args for the event. + /// The view. /// - public class ViewAttachedEventArgs : EventArgs - { - /// - /// The view. - /// - public object View { get; set; } + public object View { get; set; } - /// - /// The context. - /// - public object Context { get; set; } - } + /// + /// The context. + /// + public object Context { get; set; } } diff --git a/src/Caliburn.Micro.Core/ViewAware/ViewAware.cs b/src/Caliburn.Micro.Core/ViewAware/ViewAware.cs index 059ddc461..5b94600e9 100644 --- a/src/Caliburn.Micro.Core/ViewAware/ViewAware.cs +++ b/src/Caliburn.Micro.Core/ViewAware/ViewAware.cs @@ -2,114 +2,97 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro; + +/// +/// A base implementation of which is capable of caching views by context. +/// +public class ViewAware : PropertyChangedBase, IViewAware { /// - /// A base implementation of which is capable of caching views by context. + /// The default view context. /// - public class ViewAware : PropertyChangedBase, IViewAware - { - private readonly IDictionary _views; - - /// - /// The default view context. - /// - public static readonly object DefaultContext - = new(); - - /// - /// The view chache for this instance. - /// - protected IDictionary Views - => _views; - - /// - /// Creates an instance of . - /// - public ViewAware() - => _views = new WeakValueDictionary(); - - /// - /// Raised when a view is attached. - /// - public event EventHandler ViewAttached - = delegate - { }; - - void IViewAware.AttachView(object view, object context) - { - Views[context ?? DefaultContext] = view; - - var nonGeneratedView = PlatformProvider.Current.GetFirstNonGeneratedView(view); - PlatformProvider.Current.ExecuteOnFirstLoad(nonGeneratedView, OnViewLoaded); - OnViewAttached(nonGeneratedView, context); - ViewAttached(this, new ViewAttachedEventArgs { View = nonGeneratedView, Context = context }); - - if (this is IActivate activatable && !activatable.IsActive) - { - AttachViewReadyOnActivated(activatable, nonGeneratedView); - - return; - } + public static readonly object DefaultContext + = new(); - PlatformProvider.Current.ExecuteOnLayoutUpdated(nonGeneratedView, OnViewReady); - } + /// + /// Initializes a new instance of the class. + /// + public ViewAware() + => Views = new WeakValueDictionary(); - private static void AttachViewReadyOnActivated(IActivate activatable, object nonGeneratedView) - { - var viewReference = new WeakReference(nonGeneratedView); - Task OnActivated(object s, ActivationEventArgs e) - { - ((IActivate)s).Activated -= OnActivated; - var view = viewReference.Target; - if (view == null) - { - return Task.CompletedTask; - } - - PlatformProvider.Current.ExecuteOnLayoutUpdated(view, ((ViewAware)s).OnViewReady); + /// + /// Raised when a view is attached. + /// + public event EventHandler ViewAttached + = (sender, e) => { }; - return Task.CompletedTask; - } + /// + /// Gets the view chache for this instance. + /// + protected IDictionary Views { get; } - activatable.Activated += OnActivated; - } + /// + /// Gets a view previously attached to this instance. + /// + /// The context denoting which view to retrieve. + /// The view. + public virtual object GetView(object context = null) { + Views.TryGetValue(context ?? DefaultContext, out object view); - /// - /// Called when a view is attached. - /// - /// The view. - /// The context in which the view appears. - protected virtual void OnViewAttached(object view, object context) - { - } + return view; + } - /// - /// Called when an attached view's Loaded event fires. - /// - /// - protected virtual void OnViewLoaded(object view) - { - } + void IViewAware.AttachView(object view, object context) { + Views[context ?? DefaultContext] = view; + + object nonGeneratedView = PlatformProvider.Current.GetFirstNonGeneratedView(view); + PlatformProvider.Current.ExecuteOnFirstLoad(nonGeneratedView, OnViewLoaded); + OnViewAttached(nonGeneratedView, context); + ViewAttached(this, new ViewAttachedEventArgs { View = nonGeneratedView, Context = context }); + + if (this is IActivate activatable && !activatable.IsActive) { + AttachViewReadyOnActivated(activatable, nonGeneratedView); - /// - /// Called the first time the page's LayoutUpdated event fires after it is navigated to. - /// - /// - protected virtual void OnViewReady(object view) - { + return; } - /// - /// Gets a view previously attached to this instance. - /// - /// The context denoting which view to retrieve. - /// The view. - public virtual object GetView(object context = null) - { - Views.TryGetValue(context ?? DefaultContext, out object view); + PlatformProvider.Current.ExecuteOnLayoutUpdated(nonGeneratedView, OnViewReady); + } + + /// + /// Called when a view is attached. + /// + /// The view. + /// The context in which the view appears. + protected virtual void OnViewAttached(object view, object context) { + } + + /// + /// Called when an attached view's Loaded event fires. + /// + protected virtual void OnViewLoaded(object view) { + } - return view; + /// + /// Called the first time the page's LayoutUpdated event fires after it is navigated to. + /// + protected virtual void OnViewReady(object view) { + } + + private static void AttachViewReadyOnActivated(IActivate activatable, object nonGeneratedView) { + var viewReference = new WeakReference(nonGeneratedView); + Task OnActivated(object s, ActivationEventArgs e) { + ((IActivate)s).Activated -= OnActivated; + object view = viewReference.Target; + if (view == null) { + return Task.CompletedTask; + } + + PlatformProvider.Current.ExecuteOnLayoutUpdated(view, ((ViewAware)s).OnViewReady); + + return Task.CompletedTask; } + + activatable.Activated += OnActivated; } } diff --git a/src/stylecop.json b/src/stylecop.json new file mode 100644 index 000000000..98173fc34 --- /dev/null +++ b/src/stylecop.json @@ -0,0 +1,68 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "indentation": { + "indentationSize": 4, + "tabSize": 4, + "useTabs": false + }, + "spacingRules": { + }, + "readabilityRules": { + "allowBuiltInTypeAliases": false + }, + "orderingRules": { + "systemUsingDirectivesFirst": true, + "blankLinesBetweenUsingGroups": "require", + "usingDirectivesPlacement": "outsideNamespace", + "elementOrder": [ + "kind", + "accessibility", + "constant", + "static", + "readonly" + ] + }, + "namingRules": { + "allowCommonHungarianPrefixes": true, + "allowedHungarianPrefixes": [ + ], + "allowedNamespaceComponents": [ + ], + "includeInferredTupleElementNames": true, + "tupleElementNameCasing": "camelCase" + }, + "maintainabilityRules": { + "topLevelTypes": [ + "class", + "interface", + "struct", + "enum", + "delegate" + ] + }, + "layoutRules": { + "newlineAtEndOfFile": "require", + "allowConsecutiveUsings": false + }, + "documentationRules": { + "xmlHeader": false, + "documentInterfaces": false, + "documentExposedElements": false, + "documentInternalElements": false, + "documentPrivateElements": false, + "documentPrivateFields": false, + "documentationCulture": "en-US", + "fileNamingConvention": "stylecop", + "excludeFromPunctuationCheck": [ "seealso" ], + "copyrightText": "Copyright (c) {Year} {companyName}. All rights reserved.\nLicensed under the {licenseName} license. See {licenseFile} file in the project root for full license information.", + "headerDecoration": "--------------------------------------------------------------------------------------------------", + "companyName": "Caliburn.Micro", + "variables": { + "Year": "2023", + "licenseName": "MIT", + "licenseFile": "License.txt" + } + } + } +} From 53b2f1dd1cfd85cc3cd2a4d234841814a817425d Mon Sep 17 00:00:00 2001 From: khaled Date: Sat, 7 Oct 2023 11:59:16 +0200 Subject: [PATCH 09/14] Added the missing xml documentation because previous commits failed to build because of them. --- .../Base/ConductorBaseWithActiveItem.cs | 8 ++++--- .../Conductor/Contracts/ICloseResult.cs | 4 ++-- .../Conductor/Contracts/IHaveActiveItem.cs | 2 +- .../EventArgs/ActivationProcessedEventArgs.cs | 2 +- .../Models/CoroutineExecutionContext.cs | 6 ++--- .../Extensions/EventAggregatorExtensions.cs | 4 ++++ src/Caliburn.Micro.Core/Extensions/Execute.cs | 2 +- .../IoC/ExtensionPoints/IoC.cs | 6 ++--- .../IoC/Extensions/ContainerExtensions.cs | 14 +++++------ .../Contracts/IPlatformProvider.cs | 4 ++-- .../Result/Extensions/ResultExtensions.cs | 4 ---- .../Screen/EventArgs/ActivationEventArgs.cs | 2 +- .../Screen/EventArgs/DeactivationEventArgs.cs | 2 +- .../Screen/EventHandlers/AsyncEventHandler.cs | 7 ++++++ .../Extensions/AsyncEventHandlerExtensions.cs | 17 +++++++++++++ .../Screen/Extensions/ScreenExtensions.cs | 24 +++++++++---------- .../Types/INotifyPropertyChangedEx.cs | 2 +- .../EventArgs/ViewAttachedEventArgs.cs | 4 ++-- .../ViewAware/ViewAware.cs | 1 + 19 files changed, 71 insertions(+), 44 deletions(-) diff --git a/src/Caliburn.Micro.Core/Conductor/Base/ConductorBaseWithActiveItem.cs b/src/Caliburn.Micro.Core/Conductor/Base/ConductorBaseWithActiveItem.cs index 657badf04..780042e80 100644 --- a/src/Caliburn.Micro.Core/Conductor/Base/ConductorBaseWithActiveItem.cs +++ b/src/Caliburn.Micro.Core/Conductor/Base/ConductorBaseWithActiveItem.cs @@ -12,7 +12,7 @@ public abstract class ConductorBaseWithActiveItem : ConductorBase, IConduc private T _activeItem; /// - /// The currently active item. + /// Gets or sets the currently active item. /// public T ActiveItem { get => _activeItem; @@ -20,9 +20,11 @@ public T ActiveItem { } /// - /// The currently active item. + /// Gets or sets the currently active item. /// - /// + /// + /// The currently active item. + /// object IHaveActiveItem.ActiveItem { get => ActiveItem; set => ActiveItem = (T)value; diff --git a/src/Caliburn.Micro.Core/Conductor/Contracts/ICloseResult.cs b/src/Caliburn.Micro.Core/Conductor/Contracts/ICloseResult.cs index 99ebe9396..2d43a2cfc 100644 --- a/src/Caliburn.Micro.Core/Conductor/Contracts/ICloseResult.cs +++ b/src/Caliburn.Micro.Core/Conductor/Contracts/ICloseResult.cs @@ -7,12 +7,12 @@ namespace Caliburn.Micro; /// public interface ICloseResult { /// - /// Indicates which children shbould close if the parent cannot. + /// Gets list of children that should close if the parent cannot. /// IEnumerable Children { get; } /// - /// Indicates whether a close can occur. + /// Gets a value indicating whether a close can occur. /// bool CloseCanOccur { get; } } diff --git a/src/Caliburn.Micro.Core/Conductor/Contracts/IHaveActiveItem.cs b/src/Caliburn.Micro.Core/Conductor/Contracts/IHaveActiveItem.cs index d9a0195fb..aceb48f30 100644 --- a/src/Caliburn.Micro.Core/Conductor/Contracts/IHaveActiveItem.cs +++ b/src/Caliburn.Micro.Core/Conductor/Contracts/IHaveActiveItem.cs @@ -5,7 +5,7 @@ /// public interface IHaveActiveItem { /// - /// The currently active item. + /// Gets or sets the currently active item. /// object ActiveItem { get; set; } } diff --git a/src/Caliburn.Micro.Core/Conductor/EventArgs/ActivationProcessedEventArgs.cs b/src/Caliburn.Micro.Core/Conductor/EventArgs/ActivationProcessedEventArgs.cs index 441aa5341..69557471f 100644 --- a/src/Caliburn.Micro.Core/Conductor/EventArgs/ActivationProcessedEventArgs.cs +++ b/src/Caliburn.Micro.Core/Conductor/EventArgs/ActivationProcessedEventArgs.cs @@ -7,7 +7,7 @@ namespace Caliburn.Micro; /// public class ActivationProcessedEventArgs : EventArgs { /// - /// The item whose activation was processed. + /// Gets or sets the item whose activation was processed. /// public object Item { get; set; } diff --git a/src/Caliburn.Micro.Core/Coroutine/Models/CoroutineExecutionContext.cs b/src/Caliburn.Micro.Core/Coroutine/Models/CoroutineExecutionContext.cs index 9f4df928a..d7bae0a77 100644 --- a/src/Caliburn.Micro.Core/Coroutine/Models/CoroutineExecutionContext.cs +++ b/src/Caliburn.Micro.Core/Coroutine/Models/CoroutineExecutionContext.cs @@ -5,17 +5,17 @@ /// public class CoroutineExecutionContext { /// - /// The source from which the message originates. + /// Gets or sets the source from which the message originates. /// public object Source { get; set; } /// - /// The view associated with the target. + /// Gets or sets the view associated with the target. /// public object View { get; set; } /// - /// The instance on which the action is invoked. + /// Gets or sets the instance on which the action is invoked. /// public object Target { get; set; } } diff --git a/src/Caliburn.Micro.Core/EventAggregator/Extensions/EventAggregatorExtensions.cs b/src/Caliburn.Micro.Core/EventAggregator/Extensions/EventAggregatorExtensions.cs index 50263bb3d..e78c548fa 100644 --- a/src/Caliburn.Micro.Core/EventAggregator/Extensions/EventAggregatorExtensions.cs +++ b/src/Caliburn.Micro.Core/EventAggregator/Extensions/EventAggregatorExtensions.cs @@ -12,6 +12,7 @@ public static class EventAggregatorExtensions { /// Subscribes an instance to all events declared through implementations of . /// /// The subscription is invoked on the thread chosen by the publisher. + /// The EventAggregator. /// The instance to subscribe for event publication. public static void SubscribeOnPublishedThread(this IEventAggregator eventAggregator, object subscriber) => eventAggregator.Subscribe(subscriber, f => f()); @@ -20,6 +21,7 @@ public static void SubscribeOnPublishedThread(this IEventAggregator eventAggrega /// Subscribes an instance to all events declared through implementations of . /// /// The subscription is invoked on the thread chosen by the publisher. + /// The event aggregator. /// The instance to subscribe for event publication. [Obsolete("Use SubscribeOnPublishedThread")] public static void Subscribe(this IEventAggregator eventAggregator, object subscriber) @@ -29,6 +31,7 @@ public static void Subscribe(this IEventAggregator eventAggregator, object subsc /// Subscribes an instance to all events declared through implementations of . /// /// The subscription is invoked on a new background thread. + /// The event aggregator. /// The instance to subscribe for event publication. public static void SubscribeOnBackgroundThread(this IEventAggregator eventAggregator, object subscriber) => eventAggregator.Subscribe(subscriber, f => Task.Factory.StartNew(f, default, TaskCreationOptions.None, TaskScheduler.Default)); @@ -37,6 +40,7 @@ public static void SubscribeOnBackgroundThread(this IEventAggregator eventAggreg /// Subscribes an instance to all events declared through implementations of . /// /// The subscription is invoked on the UI thread. + /// The event aggregator. /// The instance to subscribe for event publication. public static void SubscribeOnUIThread(this IEventAggregator eventAggregator, object subscriber) => eventAggregator.Subscribe( diff --git a/src/Caliburn.Micro.Core/Extensions/Execute.cs b/src/Caliburn.Micro.Core/Extensions/Execute.cs index e3297b8bf..2e87f35db 100644 --- a/src/Caliburn.Micro.Core/Extensions/Execute.cs +++ b/src/Caliburn.Micro.Core/Extensions/Execute.cs @@ -8,7 +8,7 @@ namespace Caliburn.Micro; /// public static class Execute { /// - /// Indicates whether or not the framework is in design-time mode. + /// Gets a value indicating whether or not the framework is in design-time mode. /// public static bool InDesignMode => PlatformProvider.Current.InDesignMode; diff --git a/src/Caliburn.Micro.Core/IoC/ExtensionPoints/IoC.cs b/src/Caliburn.Micro.Core/IoC/ExtensionPoints/IoC.cs index db0cf9ab8..ed189eabf 100644 --- a/src/Caliburn.Micro.Core/IoC/ExtensionPoints/IoC.cs +++ b/src/Caliburn.Micro.Core/IoC/ExtensionPoints/IoC.cs @@ -9,21 +9,21 @@ namespace Caliburn.Micro; /// public static class IoC { /// - /// Gets an instance by type and key. + /// Gets or sets func to get an instance by type and key. /// public static Func GetInstance { get; set; } = (service, key) => throw new InvalidOperationException("IoC is not initialized."); /// - /// Gets all instances of a particular type. + /// Gets or sets func to get all instances of a particular type. /// public static Func> GetAllInstances { get; set; } = service => throw new InvalidOperationException("IoC is not initialized."); /// - /// Passes an existing instance to the IoC container to enable dependencies to be injected. + /// Gets or sets action to be passes an existing instance to the IoC container to enable dependencies to be injected. /// public static Action BuildUp { get; set; } = instance diff --git a/src/Caliburn.Micro.Core/IoC/Extensions/ContainerExtensions.cs b/src/Caliburn.Micro.Core/IoC/Extensions/ContainerExtensions.cs index 9d4490979..0e9963351 100644 --- a/src/Caliburn.Micro.Core/IoC/Extensions/ContainerExtensions.cs +++ b/src/Caliburn.Micro.Core/IoC/Extensions/ContainerExtensions.cs @@ -15,7 +15,7 @@ public static class ContainerExtensions { /// The type of the implementation. /// The container. /// The key. - /// The container. + /// The . public static SimpleContainer Singleton(this SimpleContainer container, string key = null) => Singleton(container, key); @@ -26,7 +26,7 @@ public static SimpleContainer Singleton(this SimpleContainer co /// The type of the implementation. /// The container. /// The key. - /// The container. + /// The . public static SimpleContainer Singleton(this SimpleContainer container, string key = null) where TImplementation : TService { container.RegisterSingleton(typeof(TService), key, typeof(TImplementation)); @@ -40,7 +40,7 @@ public static SimpleContainer Singleton(this SimpleCo /// The type of the implementation. /// The container. /// The key. - /// The container. + /// The . public static SimpleContainer PerRequest(this SimpleContainer container, string key = null) => PerRequest(container, key); @@ -51,7 +51,7 @@ public static SimpleContainer PerRequest(this SimpleContainer c /// The type of the implementation. /// The container. /// The key. - /// The container. + /// The . public static SimpleContainer PerRequest(this SimpleContainer container, string key = null) where TImplementation : TService { container.RegisterPerRequest(typeof(TService), key, typeof(TImplementation)); @@ -65,7 +65,7 @@ public static SimpleContainer PerRequest(this SimpleC /// The type of the service. /// The container. /// The instance. - /// The container. + /// The . public static SimpleContainer Instance(this SimpleContainer container, TService instance) { container.RegisterInstance(typeof(TService), null, instance); @@ -78,7 +78,7 @@ public static SimpleContainer Instance(this SimpleContainer container, /// The type of the service. /// The container. /// The handler. - /// The container. + /// The . public static SimpleContainer Handler( this SimpleContainer container, Func handler) { @@ -94,7 +94,7 @@ public static SimpleContainer Handler( /// The container. /// The assembly. /// The type filter. - /// The container. + /// The . public static SimpleContainer AllTypesOf( this SimpleContainer container, Assembly assembly, diff --git a/src/Caliburn.Micro.Core/PlatformProvider/Contracts/IPlatformProvider.cs b/src/Caliburn.Micro.Core/PlatformProvider/Contracts/IPlatformProvider.cs index cc5609661..1e97647d5 100644 --- a/src/Caliburn.Micro.Core/PlatformProvider/Contracts/IPlatformProvider.cs +++ b/src/Caliburn.Micro.Core/PlatformProvider/Contracts/IPlatformProvider.cs @@ -10,12 +10,12 @@ namespace Caliburn.Micro; /// public interface IPlatformProvider { /// - /// Indicates whether or not the framework is in design-time mode. + /// Gets a value indicating whether or not the framework is in design-time mode. /// bool InDesignMode { get; } /// - /// Whether or not classes should execute property change notications on the UI thread. + /// Gets a value indicating whether or not classes should execute property change notications on the UI thread. /// bool PropertyChangeNotificationsOnUIThread { get; } diff --git a/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs b/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs index 25193dc1c..938ade94e 100644 --- a/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs +++ b/src/Caliburn.Micro.Core/Result/Extensions/ResultExtensions.cs @@ -12,7 +12,6 @@ public static class ResultExtensions { /// /// The result to decorate. /// The coroutine to execute when was canceled. - /// public static IResult WhenCancelled(this IResult result, Func coroutine) => new ContinueResultDecorator(result, coroutine); @@ -20,7 +19,6 @@ public static IResult WhenCancelled(this IResult result, Func coroutine /// Overrides of the decorated instance. /// /// The result to decorate. - /// public static IResult OverrideCancel(this IResult result) => new OverrideCancelResultDecorator(result); @@ -31,7 +29,6 @@ public static IResult OverrideCancel(this IResult result) /// The result to decorate. /// The rescue coroutine. /// Set to true to cancel the result after executing rescue. - /// public static IResult Rescue(this IResult result, Func rescue, bool cancelResult = true) where TException : Exception => new RescueResultDecorator(result, rescue, cancelResult); @@ -42,7 +39,6 @@ public static IResult Rescue(this IResult result, FuncThe result to decorate. /// The rescue coroutine. /// Set to true to cancel the result after executing rescue. - /// public static IResult Rescue(this IResult result, Func rescue, bool cancelResult = true) => Rescue(result, rescue, cancelResult); diff --git a/src/Caliburn.Micro.Core/Screen/EventArgs/ActivationEventArgs.cs b/src/Caliburn.Micro.Core/Screen/EventArgs/ActivationEventArgs.cs index b9ae16c48..ac6c2cc36 100644 --- a/src/Caliburn.Micro.Core/Screen/EventArgs/ActivationEventArgs.cs +++ b/src/Caliburn.Micro.Core/Screen/EventArgs/ActivationEventArgs.cs @@ -7,7 +7,7 @@ namespace Caliburn.Micro; /// public class ActivationEventArgs : EventArgs { /// - /// Indicates whether the sender was initialized in addition to being activated. + /// Gets or sets a value indicating whether the sender was initialized in addition to being activated. /// public bool WasInitialized { get; set; } } diff --git a/src/Caliburn.Micro.Core/Screen/EventArgs/DeactivationEventArgs.cs b/src/Caliburn.Micro.Core/Screen/EventArgs/DeactivationEventArgs.cs index e5c587ab9..dac45989b 100644 --- a/src/Caliburn.Micro.Core/Screen/EventArgs/DeactivationEventArgs.cs +++ b/src/Caliburn.Micro.Core/Screen/EventArgs/DeactivationEventArgs.cs @@ -7,7 +7,7 @@ namespace Caliburn.Micro; /// public class DeactivationEventArgs : EventArgs { /// - /// Indicates whether the sender was closed in addition to being deactivated. + /// Gets or sets a value indicating whether the sender was closed in addition to being deactivated. /// public bool WasClosed { get; set; } } diff --git a/src/Caliburn.Micro.Core/Screen/EventHandlers/AsyncEventHandler.cs b/src/Caliburn.Micro.Core/Screen/EventHandlers/AsyncEventHandler.cs index 3b3b9551c..5c869983f 100644 --- a/src/Caliburn.Micro.Core/Screen/EventHandlers/AsyncEventHandler.cs +++ b/src/Caliburn.Micro.Core/Screen/EventHandlers/AsyncEventHandler.cs @@ -3,5 +3,12 @@ namespace Caliburn.Micro; +/// +/// Async Event Handler. +/// +/// The Event Args type. +/// Event source. +/// Event argument. +/// Task. public delegate Task AsyncEventHandler(object sender, TEventArgs e) where TEventArgs : EventArgs; diff --git a/src/Caliburn.Micro.Core/Screen/Extensions/AsyncEventHandlerExtensions.cs b/src/Caliburn.Micro.Core/Screen/Extensions/AsyncEventHandlerExtensions.cs index 49288c938..37c908b41 100644 --- a/src/Caliburn.Micro.Core/Screen/Extensions/AsyncEventHandlerExtensions.cs +++ b/src/Caliburn.Micro.Core/Screen/Extensions/AsyncEventHandlerExtensions.cs @@ -5,11 +5,28 @@ namespace Caliburn.Micro; +/// +/// Async EventHandler Extensions. +/// public static class AsyncEventHandlerExtensions { + /// + /// Get Invocation List of AsyncEventHandler. + /// + /// The Event args type. + /// Async EventHandler. + /// List of AsyncEventHandler. public static IEnumerable> GetHandlers(this AsyncEventHandler handler) where TEventArgs : EventArgs => handler.GetInvocationList().Cast>(); + /// + /// Invoke all handlers of AsyncEventHandler. + /// + /// The Event args type. + /// Async EventHandler. + /// The event source. + /// The Event args. + /// Task. public static Task InvokeAllAsync(this AsyncEventHandler handler, object sender, TEventArgs e) where TEventArgs : EventArgs => Task.WhenAll( diff --git a/src/Caliburn.Micro.Core/Screen/Extensions/ScreenExtensions.cs b/src/Caliburn.Micro.Core/Screen/Extensions/ScreenExtensions.cs index e86ecf418..a71455385 100644 --- a/src/Caliburn.Micro.Core/Screen/Extensions/ScreenExtensions.cs +++ b/src/Caliburn.Micro.Core/Screen/Extensions/ScreenExtensions.cs @@ -83,11 +83,11 @@ public static Task CloseItemAsync(this ConductorBase conductor, T item, Ca where T : class => conductor.DeactivateItemAsync(item, true, cancellationToken); - /// + /// /// Activates a child whenever the specified parent is activated. - /// - ///The child to activate. - ///The parent whose activation triggers the child's activation. + /// + /// The child to activate. + /// The parent whose activation triggers the child's activation. public static void ActivateWith(this IActivate child, IActivate parent) { var childReference = new WeakReference(child); @@ -103,11 +103,11 @@ async Task OnParentActivated(object s, ActivationEventArgs e) { parent.Activated += OnParentActivated; } - /// + /// /// Deactivates a child whenever the specified parent is deactivated. - /// - ///The child to deactivate. - ///The parent whose deactivation triggers the child's deactivation. + /// + /// The child to deactivate. + /// The parent whose deactivation triggers the child's deactivation. public static void DeactivateWith(this IDeactivate child, IDeactivate parent) { var childReference = new WeakReference(child); @@ -123,11 +123,11 @@ async Task OnParentDeactivated(object s, DeactivationEventArgs e) { parent.Deactivated += OnParentDeactivated; } - /// + /// /// Activates and Deactivates a child whenever the specified parent is Activated or Deactivated. - /// - ///The child to activate/deactivate. - ///The parent whose activation/deactivation triggers the child's activation/deactivation. + /// + /// The child to activate/deactivate. + /// The parent whose activation/deactivation triggers the child's activation/deactivation. public static void ConductWith(this TChild child, TParent parent) where TChild : IActivate, IDeactivate where TParent : IActivate, IDeactivate { diff --git a/src/Caliburn.Micro.Core/Types/INotifyPropertyChangedEx.cs b/src/Caliburn.Micro.Core/Types/INotifyPropertyChangedEx.cs index af3954b4e..b0ad76980 100644 --- a/src/Caliburn.Micro.Core/Types/INotifyPropertyChangedEx.cs +++ b/src/Caliburn.Micro.Core/Types/INotifyPropertyChangedEx.cs @@ -7,7 +7,7 @@ namespace Caliburn.Micro; /// public interface INotifyPropertyChangedEx : INotifyPropertyChanged { /// - /// Enables/Disables property change notification. + /// Gets or sets a value indicating whether to enable/Disable property change notification. /// bool IsNotifying { get; set; } diff --git a/src/Caliburn.Micro.Core/ViewAware/EventArgs/ViewAttachedEventArgs.cs b/src/Caliburn.Micro.Core/ViewAware/EventArgs/ViewAttachedEventArgs.cs index 7b695ade3..bf2f1c867 100644 --- a/src/Caliburn.Micro.Core/ViewAware/EventArgs/ViewAttachedEventArgs.cs +++ b/src/Caliburn.Micro.Core/ViewAware/EventArgs/ViewAttachedEventArgs.cs @@ -7,12 +7,12 @@ namespace Caliburn.Micro; /// public class ViewAttachedEventArgs : EventArgs { /// - /// The view. + /// Gets or sets the view. /// public object View { get; set; } /// - /// The context. + /// Gets or sets the context. /// public object Context { get; set; } } diff --git a/src/Caliburn.Micro.Core/ViewAware/ViewAware.cs b/src/Caliburn.Micro.Core/ViewAware/ViewAware.cs index 5b94600e9..6631bd3d5 100644 --- a/src/Caliburn.Micro.Core/ViewAware/ViewAware.cs +++ b/src/Caliburn.Micro.Core/ViewAware/ViewAware.cs @@ -70,6 +70,7 @@ protected virtual void OnViewAttached(object view, object context) { /// /// Called when an attached view's Loaded event fires. /// + /// The loaded view. protected virtual void OnViewLoaded(object view) { } From ee08a04b442142b5fe7bcefdfcaf6d7476b6a460 Mon Sep 17 00:00:00 2001 From: khaled Date: Mon, 9 Oct 2023 06:26:49 +0200 Subject: [PATCH 10/14] - Refactored all (.csproj) to be more clean and clear. - Added standard text for missing xml comments. - The code Refactored according to the configured analyzers. - Added comments to '.editorconfig' to explain the changed diagnostic from silent or suggestion to warning. - All the projects now build with all analyzers enabled including StyleCop. - The tests passing. - There is still issues needs to be resolved, for now they suppressed in 'Directory.Build.props', You will find note there with all errors. - Test files in Caliburn.Micro.Core.Tests are moved to sub folder and extracted new files, so files contains single type. There still a lot places that can be improved. --- .editorconfig | 342 +++----- .../Caliburn.Micro.Core.Tests.csproj | 14 +- .../ConductWithTests.cs} | 77 +- .../ConductorWithCollectionOneActiveTests.cs | 92 +- .../EventAggregatorTests.cs | 175 ---- .../EventAggregatorHandlerExistenceTests.cs | 20 + .../EventAggregatorPublishingTests.cs | 101 +++ .../EventAggregatorSubscribingTests.cs | 30 + .../EventAggregatorUnsubscribingTests.cs | 24 + .../IoC_Get_Tests.cs} | 93 +- ...pleContainer_Checking_For_Handler_Tests.cs | 20 + ...ntainer_Creating_AChild_Container_Tests.cs | 34 + .../SimpleContainer_Find_Constructor_Tests.cs | 72 ++ ...ontainer_Getting_ASingle_Instance_Tests.cs | 24 + .../SimpleContainer_Recursive_Tests.cs | 140 +++ ...leContainer_Registering_Instances_Tests.cs | 41 + .../SimpleContainerTests.cs | 355 -------- .../Caliburn.Micro.Core.csproj | 77 +- .../Caliburn.Micro.Maui.csproj | 94 +- .../AssemblySource.cs | 126 +-- .../AssemblySourceCache.cs | 72 ++ .../Caliburn.Micro.Platform.Core.csproj | 6 +- .../ExtensionMethods.cs | 16 +- .../NameTransformer.cs | 116 +-- .../RegExHelper.cs | 64 +- .../StringSplitter.cs | 102 +-- .../TypeMappingConfiguration.cs | 55 +- .../AssemblyCacheTests.cs | 18 +- .../BindingScopeTests.cs | 98 --- .../BindingScope_FindName_Tests.cs | 64 ++ ...BindingScope_FindScopeNamingRoute_Tests.cs | 35 + .../Caliburn.Micro.Platform.Tests.csproj | 19 +- .../MessageBinderTests.cs | 4 +- .../ParserTests.cs | 14 +- .../ScopeNamingRouteTests.cs | 9 +- .../StringSplitterTests.cs | 44 +- .../ViewLocatorTests.cs | 13 +- .../ViewModelLocatorTests.cs | 58 +- src/Caliburn.Micro.Platform/Action.cs | 147 ++-- .../ActionExecutionContext.cs | 116 ++- src/Caliburn.Micro.Platform/ActionMessage.cs | 817 +++++++++--------- src/Caliburn.Micro.Platform/Bind.cs | 213 +++-- src/Caliburn.Micro.Platform/BindingScope.cs | 477 +++++----- .../BooleanToVisibilityConverter.cs | 25 +- .../Caliburn.Micro.Platform.csproj | 92 +- src/Caliburn.Micro.Platform/ChildResolver.cs | 51 +- .../ChildResolver{T}.cs | 27 + .../ConventionManager.cs | 582 +++++++------ .../DependencyPropertyHelper.cs | 103 ++- .../ElementConvention.cs | 79 +- .../IHaveParameters.cs | 2 +- src/Caliburn.Micro.Platform/Message.cs | 149 ++-- src/Caliburn.Micro.Platform/MessageBinder.cs | 125 ++- src/Caliburn.Micro.Platform/Parser.cs | 469 +++++----- .../Platforms/Android/ActivityEventArgs.cs | 24 +- .../ActivityLifecycleCallbackHandler.cs | 104 +-- .../Android/AndroidPlatformProvider.cs | 145 ++-- .../Platforms/Android/CaliburnApplication.cs | 75 +- .../Platforms/Maui/ActionMessage.cs | 685 +++++++-------- .../Maui/Android/ActivityEventArgs.cs | 25 +- .../ActivityLifecycleCallbackHandler.cs | 159 ++-- .../Maui/Android/AndroidPlatformProvider.cs | 172 ++-- .../Maui/Android/CaliburnApplication.cs | 81 +- .../Platforms/Maui/AttachedCollection.cs | 60 +- .../Platforms/Maui/ConventionManager.cs | 483 +++++------ .../DependencyPropertyChangedEventArgs.cs | 26 +- .../Platforms/Maui/FormsPlatformProvider.cs | 77 +- .../Platforms/Maui/HttpUtility.cs | 185 ++-- .../Platforms/Maui/IAttachedObject.cs | 22 +- .../Platforms/Maui/INavigationService.cs | 55 +- ...FormsApplication.cs => MauiApplication.cs} | 159 ++-- ...{NavigationHelper.cs => NavigateHelper.cs} | 34 +- .../Platforms/Maui/NavigationExtensions.cs | 14 +- .../Platforms/Maui/NavigationPageAdapter.cs | 348 ++++---- .../Platforms/Maui/Parameter.cs | 87 +- .../Platforms/Maui/PropertyChangedCallback.cs | 9 +- .../Platforms/Maui/RoutedEventArgs.cs | 8 +- .../Platforms/Maui/RoutedEventHandler.cs | 9 +- .../Platforms/Maui/TriggerActionBase.cs | 32 +- .../Maui/Windows/CaliburnApplication.cs | 326 ++++--- .../Maui/Windows/MauiPlatformProvider.cs | 159 ++-- .../Maui/iOS/CaliburnApplicationDelegate.cs | 110 ++- .../Platforms/Maui/iOS/IUIViewController.cs | 18 +- .../Platforms/Maui/iOS/iOSPlatformProvider.cs | 150 ++-- .../Platforms/Xamarin.Forms/ActionMessage.cs | 714 ++++++++------- .../Xamarin.Forms/AttachedCollection.cs | 60 +- .../Xamarin.Forms/ConventionManager.cs | 466 +++++----- .../DependencyPropertyChangedEventArgs.cs | 14 +- .../Xamarin.Forms/FormsApplication.cs | 79 +- .../Xamarin.Forms/FormsPlatformProvider.cs | 44 +- .../Platforms/Xamarin.Forms/HttpUtility.cs | 141 +-- .../Xamarin.Forms/IAttachedObject.cs | 22 +- .../Xamarin.Forms/INavigationService.cs | 55 +- ...elper.cs => NavigateHelper{TViewModel}.cs} | 39 +- .../Xamarin.Forms/NavigationExtensions.cs | 14 +- .../Xamarin.Forms/NavigationPageAdapter.cs | 358 ++++---- .../Platforms/Xamarin.Forms/Parameter.cs | 85 +- .../Xamarin.Forms/PropertyChangedCallback.cs | 6 +- .../Xamarin.Forms/RoutedEventArgs.cs | 2 +- .../Xamarin.Forms/RoutedEventHandler.cs | 8 +- .../Xamarin.Forms/TriggerActionBase.cs | 38 +- .../iOS/CaliburnApplicationDelegate.cs | 83 +- .../Platforms/iOS/IUIViewController.cs | 20 +- .../Platforms/iOS/iOSPlatformProvider.cs | 123 +-- .../net46-netcore/AttachedCollection.cs | 45 +- .../{Bootstrapper.cs => BootstrapperBase.cs} | 104 +-- .../Platforms/net46-netcore/FrameAdapter.cs | 383 ++++---- .../net46-netcore/INavigationService.cs | 72 +- .../Platforms/net46-netcore/IWindowManager.cs | 34 + .../net46-netcore/NavigationExtensions.cs | 13 +- .../net46-netcore/NavigationHelper.cs | 37 +- .../Platforms/net46-netcore/Parameter.cs | 56 +- .../net46-netcore/WindowConductor.cs | 129 +-- .../Platforms/net46-netcore/WindowManager.cs | 231 ++--- .../Platforms/uap/Activator.cs | 9 + .../Platforms/uap/AddToCollection.cs | 9 + .../Platforms/uap/AddToDictionary.cs | 9 + .../Platforms/uap/AppManifestHelper.cs | 125 +-- .../Platforms/uap/AttachedCollection.81.cs | 54 +- .../Platforms/uap/CachingFrameAdapter.cs | 160 ++-- .../Platforms/uap/CaliburnApplication.cs | 130 +-- .../Platforms/uap/DispatcherTaskExtensions.cs | 60 +- .../Platforms/uap/FrameAdapter.cs | 533 ++++++------ .../Platforms/uap/Getter.cs | 3 + .../Platforms/uap/IAttachedObject.cs | 21 +- .../Platforms/uap/INavigationService.cs | 49 +- .../Platforms/uap/ISupportSharing.cs | 4 +- .../Platforms/uap/NavigateHelper.cs | 41 +- .../Platforms/uap/NavigationExtensions.cs | 40 +- .../Platforms/uap/Parameter.cs | 64 +- .../Platforms/uap/Setter.cs | 9 + .../Platforms/uap/SharingService.cs | 37 +- .../Platforms/uap/TriggerAction.cs | 60 +- .../Platforms/uap/VisualElement.cs | 65 ++ .../Platforms/uap/WinRTContainer.cs | 37 +- .../Platforms/uap/XamlMember.cs | 60 ++ .../Platforms/uap/XamlMetadataProvider.cs | 497 +---------- .../Platforms/uap/XamlSystemBaseType.cs | 64 ++ .../Platforms/uap/XamlTypeInfoProvider.cs | 103 +++ .../Platforms/uap/XamlUserType.cs | 146 ++++ src/Caliburn.Micro.Platform/View.cs | 374 ++++---- src/Caliburn.Micro.Platform/ViewLocator.cs | 638 +++++++------- .../ViewModelBinder.cs | 394 ++++----- .../ViewModelLocator.cs | 526 +++++------ .../XamlPlatformProvider.cs | 163 ++-- .../Caliburn.Micro.Xamarin.Forms.csproj | 53 +- src/Directory.Build.props | 149 +++- src/global.json | 2 +- 148 files changed, 8573 insertions(+), 9663 deletions(-) rename src/Caliburn.Micro.Core.Tests/{ScreenExtentionTests.cs => ConductorTests/ConductWithTests.cs} (72%) rename src/Caliburn.Micro.Core.Tests/{ => ConductorTests}/ConductorWithCollectionOneActiveTests.cs (77%) delete mode 100644 src/Caliburn.Micro.Core.Tests/EventAggregatorTests.cs create mode 100644 src/Caliburn.Micro.Core.Tests/EventAggregatorTests/EventAggregatorHandlerExistenceTests.cs create mode 100644 src/Caliburn.Micro.Core.Tests/EventAggregatorTests/EventAggregatorPublishingTests.cs create mode 100644 src/Caliburn.Micro.Core.Tests/EventAggregatorTests/EventAggregatorSubscribingTests.cs create mode 100644 src/Caliburn.Micro.Core.Tests/EventAggregatorTests/EventAggregatorUnsubscribingTests.cs rename src/Caliburn.Micro.Core.Tests/{IoCTests.cs => IocTests/IoC_Get_Tests.cs} (64%) create mode 100644 src/Caliburn.Micro.Core.Tests/IocTests/SimpleContainer_Checking_For_Handler_Tests.cs create mode 100644 src/Caliburn.Micro.Core.Tests/IocTests/SimpleContainer_Creating_AChild_Container_Tests.cs create mode 100644 src/Caliburn.Micro.Core.Tests/IocTests/SimpleContainer_Find_Constructor_Tests.cs create mode 100644 src/Caliburn.Micro.Core.Tests/IocTests/SimpleContainer_Getting_ASingle_Instance_Tests.cs create mode 100644 src/Caliburn.Micro.Core.Tests/IocTests/SimpleContainer_Recursive_Tests.cs create mode 100644 src/Caliburn.Micro.Core.Tests/IocTests/SimpleContainer_Registering_Instances_Tests.cs delete mode 100644 src/Caliburn.Micro.Core.Tests/SimpleContainerTests.cs create mode 100644 src/Caliburn.Micro.Platform.Core/AssemblySourceCache.cs delete mode 100644 src/Caliburn.Micro.Platform.Tests/BindingScopeTests.cs create mode 100644 src/Caliburn.Micro.Platform.Tests/BindingScope_FindName_Tests.cs create mode 100644 src/Caliburn.Micro.Platform.Tests/BindingScope_FindScopeNamingRoute_Tests.cs create mode 100644 src/Caliburn.Micro.Platform/ChildResolver{T}.cs rename src/Caliburn.Micro.Platform/Platforms/Maui/{FormsApplication.cs => MauiApplication.cs} (69%) rename src/Caliburn.Micro.Platform/Platforms/Maui/{NavigationHelper.cs => NavigateHelper.cs} (65%) rename src/Caliburn.Micro.Platform/Platforms/Xamarin.Forms/{NavigationHelper.cs => NavigateHelper{TViewModel}.cs} (57%) rename src/Caliburn.Micro.Platform/Platforms/net46-netcore/{Bootstrapper.cs => BootstrapperBase.cs} (75%) create mode 100644 src/Caliburn.Micro.Platform/Platforms/net46-netcore/IWindowManager.cs create mode 100644 src/Caliburn.Micro.Platform/Platforms/uap/Activator.cs create mode 100644 src/Caliburn.Micro.Platform/Platforms/uap/AddToCollection.cs create mode 100644 src/Caliburn.Micro.Platform/Platforms/uap/AddToDictionary.cs create mode 100644 src/Caliburn.Micro.Platform/Platforms/uap/Getter.cs create mode 100644 src/Caliburn.Micro.Platform/Platforms/uap/Setter.cs create mode 100644 src/Caliburn.Micro.Platform/Platforms/uap/VisualElement.cs create mode 100644 src/Caliburn.Micro.Platform/Platforms/uap/XamlMember.cs create mode 100644 src/Caliburn.Micro.Platform/Platforms/uap/XamlSystemBaseType.cs create mode 100644 src/Caliburn.Micro.Platform/Platforms/uap/XamlTypeInfoProvider.cs create mode 100644 src/Caliburn.Micro.Platform/Platforms/uap/XamlUserType.cs diff --git a/.editorconfig b/.editorconfig index becf76c82..ab8bec56d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,7 +8,6 @@ root = true # A newline ending every file # Use 4 spaces as indentation [*] -insert_final_newline = true indent_style = space indent_size = 4 @@ -17,39 +16,44 @@ indent_size = 8 # Xml project files [*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}] +tab_width = 2 indent_size = 2 +end_of_line = crlf +indent_style = space +insert_final_newline = true # Xml config files [*.{props,targets,config,nuspec}] +tab_width = 2 indent_size = 2 +end_of_line = crlf +indent_style = space +insert_final_newline = true [CMakeLists.txt] indent_size = 2 -[*.cmd] -indent_size = 2 - [**.md] indent_style = tab trim_trailing_whitespace = false -[*.ps1] +[{*.yml,*.yaml,package.json}] indent_size = 2 -[*.sh] +[**.json] indent_size = 2 -end_of_line = lf -[{*.yml,*.yaml,package.json}] +[*.cmd] indent_size = 2 -[**.json] +[*.ps1] indent_size = 2 -# C# files +[*.sh] +indent_size = 2 +end_of_line = lf + [*.cs] -tab_width = 4 -end_of_line = crlf csharp_indent_block_contents = true csharp_indent_braces = false csharp_indent_case_contents = true @@ -63,12 +67,6 @@ csharp_new_line_before_members_in_anonymous_types = true csharp_new_line_before_members_in_object_initializers = true csharp_new_line_before_open_brace = none csharp_new_line_between_query_expression_clauses = true -csharp_prefer_braces = true:error -csharp_prefer_simple_default_expression = true:error -csharp_prefer_simple_using_statement = true:error -csharp_prefer_static_local_function = true:suggestion -csharp_preserve_single_line_blocks = true -csharp_preserve_single_line_statements = true csharp_space_after_cast = false csharp_space_after_colon_in_inheritance_clause = true csharp_space_after_comma = true @@ -91,69 +89,91 @@ csharp_space_between_method_declaration_name_and_open_parenthesis = false csharp_space_between_method_declaration_parameter_list_parentheses = false csharp_space_between_parentheses = false csharp_space_between_square_brackets = false +csharp_prefer_braces = true:warning +csharp_prefer_simple_default_expression = true:suggestion +csharp_prefer_simple_using_statement = true:warning +csharp_prefer_static_local_function = true:suggestion +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = true csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent -csharp_style_conditional_delegate_call = true:error +csharp_style_conditional_delegate_call = true:warning csharp_style_deconstructed_variable_declaration = true:suggestion -csharp_style_expression_bodied_accessors = true:error -csharp_style_expression_bodied_constructors = true:error -csharp_style_expression_bodied_indexers = true:error -csharp_style_expression_bodied_lambdas = true:error -csharp_style_expression_bodied_local_functions = true:error -csharp_style_expression_bodied_methods = true:error -csharp_style_expression_bodied_operators = true:error -csharp_style_expression_bodied_properties = true:error -csharp_style_implicit_object_creation_when_type_is_apparent = false:none -csharp_style_inlined_variable_declaration = true:error -csharp_style_namespace_declarations = file_scoped:error -csharp_style_pattern_matching_over_as_with_null_check = true:error -csharp_style_pattern_matching_over_is_with_cast_check = true:error -csharp_style_prefer_extended_property_pattern = true:error -csharp_style_prefer_index_operator = true:error -csharp_style_prefer_local_over_anonymous_function = true:error +csharp_style_expression_bodied_accessors = true:warning +csharp_style_expression_bodied_constructors = true:warning +csharp_style_expression_bodied_indexers = true:warning +csharp_style_expression_bodied_lambdas = true:warning +csharp_style_expression_bodied_local_functions = true:warning +csharp_style_expression_bodied_methods = true:warning +csharp_style_expression_bodied_operators = true:warning +csharp_style_expression_bodied_properties = true:warning +csharp_style_implicit_object_creation_when_type_is_apparent = false:warning +csharp_style_inlined_variable_declaration = true:warning +csharp_style_namespace_declarations = file_scoped:warning +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_prefer_extended_property_pattern = true:suggestion +csharp_style_prefer_index_operator = true:suggestion +csharp_style_prefer_local_over_anonymous_function = true:suggestion csharp_style_prefer_method_group_conversion = true:suggestion -csharp_style_prefer_not_pattern = true:error -csharp_style_prefer_null_check_over_type_check = true:error -csharp_style_prefer_pattern_matching = true:error -csharp_style_prefer_range_operator = true:error +csharp_style_prefer_not_pattern = true:suggestion +csharp_style_prefer_null_check_over_type_check = true:suggestion +csharp_style_prefer_pattern_matching = true:suggestion +csharp_style_prefer_primary_constructors = true:suggestion +csharp_style_prefer_range_operator = true:suggestion csharp_style_prefer_readonly_struct = true:suggestion -csharp_style_prefer_switch_expression = true:error +csharp_style_prefer_readonly_struct_member = true:suggestion +csharp_style_prefer_switch_expression = true:suggestion csharp_style_prefer_top_level_statements = true:suggestion csharp_style_prefer_tuple_swap = true:suggestion csharp_style_prefer_utf8_string_literals = true:suggestion -csharp_style_throw_expression = true:error -csharp_style_unused_value_assignment_preference = discard_variable:error +csharp_style_throw_expression = true:suggestion +csharp_style_unused_value_assignment_preference = discard_variable:warning csharp_style_unused_value_expression_statement_preference = discard_variable:silent -csharp_style_var_elsewhere = false:error -csharp_style_var_for_built_in_types = false:error -csharp_style_var_when_type_is_apparent = true:error -csharp_using_directive_placement = outside_namespace:error - -csharp_style_prefer_readonly_struct_member = true:suggestion -csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent -csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent +csharp_style_var_elsewhere = false:warning +csharp_style_var_for_built_in_types = false:warning +csharp_style_var_when_type_is_apparent = true:warning +csharp_using_directive_placement = outside_namespace:warning + +dotnet_diagnostic.SA1101.severity = none # Prefix Local Calls With This +dotnet_diagnostic.SA1500.severity = none # Braces For MultiLine Statements Must Not Share Line +dotnet_diagnostic.SA1633.severity = none # File Must Have Header +dotnet_diagnostic.SA1309.severity = none # Field Names Must Not Begin With Underscore + +dotnet_diagnostic.CA1070.severity = warning # Do not declare event fields as virtual +dotnet_diagnostic.CA1001.severity = warning # Types that own disposable fields should be disposable +dotnet_diagnostic.CA1200.severity = warning # Avoid using cref tags with a prefix +dotnet_diagnostic.CA1311.severity = warning # Specify a culture or use an invariant version +dotnet_diagnostic.CA1309.severity = warning # Use ordinal string comparison +dotnet_diagnostic.CA1507.severity = warning # Use nameof to express symbol names +dotnet_diagnostic.CA2016.severity = warning # Forward the 'CancellationToken' parameter to methods [*.{cs,vb}] tab_width = 4 +indent_size = 4 end_of_line = crlf +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true dotnet_style_namespace_match_folder = false:silent dotnet_style_operator_placement_when_wrapping = beginning_of_line - dotnet_style_coalesce_expression = true:suggestion -dotnet_style_collection_initializer = true:error +dotnet_style_collection_initializer = true:suggestion dotnet_style_explicit_tuple_names = true:suggestion -dotnet_style_null_propagation = true:error -dotnet_style_object_initializer = true:error -dotnet_style_prefer_auto_properties = true:error -dotnet_style_prefer_compound_assignment = true:error -dotnet_style_prefer_conditional_expression_over_assignment = true:error -dotnet_style_prefer_conditional_expression_over_return = true:error +dotnet_style_null_propagation = true:suggestion +dotnet_style_object_initializer = true:suggestion +dotnet_style_prefer_auto_properties = true:suggestion +dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion +dotnet_style_prefer_conditional_expression_over_return = true:suggestion dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion dotnet_style_prefer_inferred_tuple_names = true:suggestion -dotnet_style_prefer_is_null_check_over_reference_equality_method = true:error -dotnet_style_prefer_simplified_boolean_expressions = true:error +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion dotnet_style_prefer_simplified_interpolation = true:suggestion dotnet_style_readonly_field = true:error dotnet_style_predefined_type_for_locals_parameters_members = true:error @@ -161,180 +181,96 @@ dotnet_style_predefined_type_for_member_access = true:error dotnet_style_require_accessibility_modifiers = for_non_interface_members:error dotnet_style_allow_multiple_blank_lines_experimental = false:error dotnet_style_allow_statement_immediately_after_block_experimental = true:silent -dotnet_code_quality_unused_parameters = all:error dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:error dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:error dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:error dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning dotnet_style_qualification_for_field = false:error dotnet_style_qualification_for_property = false:error dotnet_style_qualification_for_method = false:error dotnet_style_qualification_for_event = false:error -dotnet_diagnostic.SA0001.severity = none -dotnet_diagnostic.SA1633.severity = silent -dotnet_diagnostic.SA1500.severity = silent -dotnet_diagnostic.SA1309.severity = silent -dotnet_diagnostic.SA1101.severity = silent - -dotnet_diagnostic.NUnit2001.severity = warning -dotnet_diagnostic.NUnit2002.severity = warning -dotnet_diagnostic.NUnit2003.severity = warning -dotnet_diagnostic.NUnit2004.severity = warning -dotnet_diagnostic.NUnit2016.severity = warning -dotnet_diagnostic.NUnit2017.severity = warning -dotnet_diagnostic.NUnit2018.severity = warning -dotnet_diagnostic.NUnit2019.severity = warning -dotnet_diagnostic.NUnit2027.severity = warning -dotnet_diagnostic.NUnit2028.severity = warning -dotnet_diagnostic.NUnit2029.severity = warning -dotnet_diagnostic.NUnit2030.severity = warning -dotnet_diagnostic.NUnit2032.severity = warning -dotnet_diagnostic.NUnit2033.severity = warning -dotnet_diagnostic.NUnit2034.severity = warning -dotnet_diagnostic.NUnit2035.severity = warning -dotnet_diagnostic.NUnit2036.severity = warning -dotnet_diagnostic.NUnit2037.severity = warning -dotnet_diagnostic.NUnit2038.severity = warning -dotnet_diagnostic.NUnit2039.severity = warning -dotnet_diagnostic.NUnit1028.severity = warning -dotnet_diagnostic.IDE0052.severity = warning -dotnet_diagnostic.IDE0021.severity = warning -dotnet_diagnostic.IDE0059.severity = warning -dotnet_diagnostic.IDE0008.severity = warning -dotnet_diagnostic.IDE0051.severity = warning -dotnet_diagnostic.IDE0064.severity = warning -dotnet_diagnostic.IDE0076.severity = warning -dotnet_diagnostic.IDE0077.severity = warning -dotnet_diagnostic.SYSLIB1045.severity = warning -dotnet_diagnostic.SYSLIB1054.severity = warning -dotnet_diagnostic.CA1070.severity = warning -dotnet_diagnostic.CA2016.severity = warning -dotnet_diagnostic.IDE0004.severity = warning -dotnet_diagnostic.IDE0005.severity = silent -dotnet_diagnostic.IDE2000.severity = warning -dotnet_diagnostic.IDE0241.severity = warning -dotnet_diagnostic.IDE0240.severity = warning -dotnet_diagnostic.IDE0200.severity = warning -dotnet_diagnostic.IDE0083.severity = warning -dotnet_diagnostic.IDE0080.severity = warning -dotnet_diagnostic.IDE0078.severity = warning -dotnet_diagnostic.IDE0075.severity = warning -dotnet_diagnostic.IDE0074.severity = warning -dotnet_diagnostic.IDE0065.severity = warning -dotnet_diagnostic.IDE0017.severity = warning -dotnet_diagnostic.IDE0018.severity = warning -dotnet_diagnostic.IDE0019.severity = warning -dotnet_diagnostic.IDE0020.severity = warning -dotnet_diagnostic.IDE0022.severity = warning -dotnet_diagnostic.IDE0023.severity = warning -dotnet_diagnostic.IDE0024.severity = warning -dotnet_diagnostic.IDE0025.severity = warning -dotnet_diagnostic.IDE0026.severity = warning -dotnet_diagnostic.IDE0027.severity = warning -dotnet_diagnostic.IDE0028.severity = warning -dotnet_diagnostic.IDE0029.severity = warning -dotnet_diagnostic.IDE0030.severity = warning -dotnet_diagnostic.IDE0031.severity = warning -dotnet_diagnostic.IDE0032.severity = suggestion -dotnet_diagnostic.IDE0034.severity = warning -dotnet_diagnostic.IDE0036.severity = warning -dotnet_diagnostic.IDE0039.severity = suggestion -dotnet_diagnostic.IDE0040.severity = warning -dotnet_diagnostic.IDE0045.severity = warning -dotnet_diagnostic.IDE0046.severity = warning -dotnet_diagnostic.IDE0047.severity = warning -dotnet_diagnostic.IDE0048.severity = warning -dotnet_diagnostic.IDE0053.severity = warning -dotnet_diagnostic.IDE0054.severity = warning -dotnet_diagnostic.IDE0055.severity = warning -csharp_style_prefer_primary_constructors = true:suggestion - -#### Naming styles #### - -# Naming rules - -dotnet_naming_rule.interface_should_be_begins_with_i.severity = error +dotnet_style_allow_multiple_blank_lines_experimental = false:warning +dotnet_style_allow_statement_immediately_after_block_experimental = true:silent +dotnet_style_predefined_type_for_locals_parameters_members = true:warning +dotnet_style_predefined_type_for_member_access = true:warning +dotnet_style_qualification_for_event = false:warning +dotnet_style_qualification_for_field = false:warning +dotnet_style_qualification_for_method = false:warning +dotnet_style_qualification_for_property = false:warning +dotnet_style_readonly_field = true:warning +dotnet_style_require_accessibility_modifiers = for_non_interface_members:warning +dotnet_code_quality_unused_parameters = all:error +dotnet_code_quality_unused_parameters = all:warning +dotnet_naming_rule.interface_should_be_begins_with_i.severity = warning dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i - dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case - dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion dotnet_naming_rule.types_should_be_pascal_case.symbols = types dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case - -# Symbol specifications - dotnet_naming_symbols.interface.applicable_kinds = interface dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected dotnet_naming_symbols.interface.required_modifiers = - dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected dotnet_naming_symbols.non_field_members.required_modifiers = - dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected dotnet_naming_symbols.types.required_modifiers = - -# Naming styles - dotnet_naming_style.begins_with_i.required_prefix = I dotnet_naming_style.begins_with_i.required_suffix = dotnet_naming_style.begins_with_i.word_separator = dotnet_naming_style.begins_with_i.capitalization = pascal_case - dotnet_naming_style.pascal_case.required_prefix = dotnet_naming_style.pascal_case.required_suffix = dotnet_naming_style.pascal_case.word_separator = dotnet_naming_style.pascal_case.capitalization = pascal_case -dotnet_code_quality_unused_parameters = all:error -dotnet_style_allow_multiple_blank_lines_experimental = false:error -dotnet_style_allow_statement_immediately_after_block_experimental = true:silent -dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:error -dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:error -dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion -dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:error -dotnet_style_predefined_type_for_locals_parameters_members = true:error -dotnet_style_predefined_type_for_member_access = true:error -dotnet_style_qualification_for_event = false:error -dotnet_style_qualification_for_field = false:error -dotnet_style_qualification_for_method = false:error -dotnet_style_qualification_for_property = false:error -dotnet_style_readonly_field = true:error -dotnet_style_require_accessibility_modifiers = for_non_interface_members:error - -dotnet_diagnostic.CA1014.severity = silent -dotnet_diagnostic.CA1303.severity = silent -dotnet_diagnostic.CA1822.severity = silent - -dotnet_diagnostic.CA1827.severity = warning -dotnet_diagnostic.CA1828.severity = warning -dotnet_diagnostic.CA2211.severity = warning -dotnet_diagnostic.CA2219.severity = warning -dotnet_diagnostic.CA2245.severity = warning -dotnet_diagnostic.CA1000.severity = warning -dotnet_diagnostic.CA1018.severity = warning -dotnet_diagnostic.CA1041.severity = warning -dotnet_diagnostic.CA1050.severity = warning -dotnet_diagnostic.CA1051.severity = warning -dotnet_diagnostic.CA1067.severity = warning -dotnet_diagnostic.CA1068.severity = warning -dotnet_diagnostic.CA1069.severity = warning -dotnet_diagnostic.CA1016.severity = warning -dotnet_diagnostic.CA1061.severity = warning -dotnet_diagnostic.CA1401.severity = warning -dotnet_diagnostic.CA1421.severity = warning -dotnet_diagnostic.CA1419.severity = warning -dotnet_diagnostic.CA2009.severity = warning -dotnet_diagnostic.CA2011.severity = warning -dotnet_diagnostic.CA2012.severity = warning -dotnet_diagnostic.CA2019.severity = warning -dotnet_diagnostic.CA5351.severity = warning -dotnet_diagnostic.CA5350.severity = warning -dotnet_diagnostic.CA1010.severity = warning -dotnet_diagnostic.IDE0070.severity = warning -dotnet_diagnostic.IDE0044.severity = warning +dotnet_diagnostic.CA1014.severity = none # Mark assemblies with CLSCompliantAttribute +dotnet_diagnostic.CA1303.severity = none # Do not pass literals as localized parameters +dotnet_diagnostic.CA1822.severity = none # Make members as static + +dotnet_diagnostic.CA1000.severity = warning # Do not declare static members on generic types +dotnet_diagnostic.CA1010.severity = warning # Generic interface should also be implemented +dotnet_diagnostic.CA1016.severity = warning # Mark assemblies with assembly version +dotnet_diagnostic.CA1018.severity = warning # Mark attributes with AttributeUsageAttribute +dotnet_diagnostic.CA1036.severity = warning # Override methods on comparable types +dotnet_diagnostic.CA1041.severity = warning # Provide ObsoleteAttribute message +dotnet_diagnostic.CA1050.severity = warning # Declare types in namespaces +dotnet_diagnostic.CA1051.severity = warning # Do not declare visible instance fields +dotnet_diagnostic.CA1061.severity = warning # Do not hide base class methods +dotnet_diagnostic.CA1067.severity = warning # Override Object.Equals(object) when implementing IEquatable +dotnet_diagnostic.CA1068.severity = warning # CancellationToken parameters must come last +dotnet_diagnostic.CA1069.severity = warning # Enums values should not be duplicated +dotnet_diagnostic.CA1310.severity = warning # Specify StringComparison for correctness +dotnet_diagnostic.CA1305.severity = warning # Specify IFormatProvider Globalization +dotnet_diagnostic.CA1304.severity = warning # Specify CultureInfo +dotnet_diagnostic.CA2101.severity = warning # Specify marshaling for P/Invoke string arguments +dotnet_diagnostic.CA1816.severity = warning # Dispose methods should call SuppressFinalize +dotnet_diagnostic.CA2211.severity = warning # Non-constant fields should not be visible +dotnet_diagnostic.CA2208.severity = warning # Instantiate argument exceptions correctly +dotnet_diagnostic.CA2219.severity = warning # Do not raise exceptions in finally clauses +dotnet_diagnostic.CA2249.severity = warning # Consider using 'string.Contains' instead of 'string.IndexOf' +dotnet_diagnostic.CA2248.severity = warning # Provide correct 'enum' argument to 'Enum.HasFlag' +dotnet_diagnostic.CA2245.severity = warning # Do not assign a property to itself +dotnet_diagnostic.CA5397.severity = warning # Do not use deprecated SslProtocols values +dotnet_diagnostic.CA5384.severity = warning # Do Not Use Digital Signature Algorithm (DSA) +dotnet_diagnostic.CA5379.severity = warning # Ensure Key Derivation Function algorithm is sufficiently strong +dotnet_diagnostic.CA5350.severity = warning # Do Not Use Weak Cryptographic Algorithms +dotnet_diagnostic.CA5351.severity = warning # Do Not Use Broken Cryptographic Algorithms +dotnet_diagnostic.CA5364.severity = warning # Do Not Use Deprecated Security Protocols +dotnet_diagnostic.CA2019.severity = warning # Improper 'ThreadStatic' field initialization +dotnet_diagnostic.CA2012.severity = warning # Use ValueTasks correctly +dotnet_diagnostic.CA2011.severity = warning # Avoid infinite recursion +dotnet_diagnostic.CA2009.severity = warning # Do not call ToImmutableCollection on an ImmutableCollection value +dotnet_diagnostic.CA1854.severity = warning # Prefer the 'IDictionary.TryGetValue(TKey, out TValue)' method +dotnet_diagnostic.CA1853.severity = warning # Unnecessary call to 'Dictionary.ContainsKey(key)' +dotnet_diagnostic.CA1852.severity = warning # Seal internal types +dotnet_diagnostic.CA1827.severity = warning # Do not use Count() or LongCount() when Any() can be used +dotnet_diagnostic.CA1828.severity = warning # Do not use CountAsync() or LongCountAsync() when AnyAsync() can be used diff --git a/src/Caliburn.Micro.Core.Tests/Caliburn.Micro.Core.Tests.csproj b/src/Caliburn.Micro.Core.Tests/Caliburn.Micro.Core.Tests.csproj index 337286563..3b9dc1be3 100644 --- a/src/Caliburn.Micro.Core.Tests/Caliburn.Micro.Core.Tests.csproj +++ b/src/Caliburn.Micro.Core.Tests/Caliburn.Micro.Core.Tests.csproj @@ -1,26 +1,30 @@  + + net462 false + $(NoWarn);CA1707;SA0001;xUnit1004 + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - \ No newline at end of file diff --git a/src/Caliburn.Micro.Core.Tests/ScreenExtentionTests.cs b/src/Caliburn.Micro.Core.Tests/ConductorTests/ConductWithTests.cs similarity index 72% rename from src/Caliburn.Micro.Core.Tests/ScreenExtentionTests.cs rename to src/Caliburn.Micro.Core.Tests/ConductorTests/ConductWithTests.cs index 04c0f26a9..bc2b78252 100644 --- a/src/Caliburn.Micro.Core.Tests/ScreenExtentionTests.cs +++ b/src/Caliburn.Micro.Core.Tests/ConductorTests/ConductWithTests.cs @@ -4,31 +4,27 @@ using System.Text; using System.Threading; using System.Threading.Tasks; + using Caliburn.Micro.Core; using Xunit; -namespace Caliburn.Micro.Core.Tests -{ - public class ConductWithTests - { +namespace Caliburn.Micro.Core.Tests { + public class ConductWithTests { [Fact] - public async Task Screen_ConductWithTests() - { + public async Task Screen_ConductWithTests() { var root = new Screen(); - var child1 = new StateScreen - { - DisplayName = "screen1" + var child1 = new StateScreen { + DisplayName = "screen1", }; - // simulate a long deactivation process - var child2 = new StateScreen(TimeSpan.FromSeconds(3)) - { - DisplayName = "screen2" + + // simulate a long deactivation process + var child2 = new StateScreen(TimeSpan.FromSeconds(3)) { + DisplayName = "screen2", }; - var child3 = new StateScreen() - { - DisplayName = "screen3" + var child3 = new StateScreen() { + DisplayName = "screen3", }; child1.ConductWith(root); @@ -49,23 +45,19 @@ public async Task Screen_ConductWithTests() } [Fact] - public async Task Conductor_ConductWithTests() - { + public async Task Conductor_ConductWithTests() { var root = new Conductor.Collection.AllActive(); - var child1 = new StateScreen - { - DisplayName = "screen1" + var child1 = new StateScreen { + DisplayName = "screen1", }; - var child2 = new StateScreen(TimeSpan.FromSeconds(3)) - { + var child2 = new StateScreen(TimeSpan.FromSeconds(3)) { DisplayName = "screen2", IsClosable = false, }; - var child3 = new StateScreen() - { - DisplayName = "screen3" + var child3 = new StateScreen() { + DisplayName = "screen3", }; root.Items.Add(child1); @@ -85,30 +77,25 @@ public async Task Conductor_ConductWithTests() Assert.True(child3.IsClosed, "child 3 should be closed"); } - class StateScreen : Screen - { - public StateScreen() - { + private sealed class StateScreen : Screen { + private readonly TimeSpan? deactivationDelay; + + public StateScreen() { } public StateScreen(TimeSpan? deactivationDelay) - { - this.deactivationDelay = deactivationDelay; - } + => this.deactivationDelay = deactivationDelay; public bool WasActivated { get; private set; } + public bool IsClosed { get; private set; } + public bool IsClosable { get; set; } - public override Task CanCloseAsync(CancellationToken cancellationToken = default) - { - return Task.FromResult(IsClosable); - } + public override Task CanCloseAsync(CancellationToken cancellationToken = default) => Task.FromResult(IsClosable); - protected override async Task OnActivateAsync(CancellationToken cancellationToken) - { - if (deactivationDelay.HasValue) - { + protected override async Task OnActivateAsync(CancellationToken cancellationToken) { + if (deactivationDelay.HasValue) { await Task.Delay(deactivationDelay.Value, cancellationToken).ConfigureAwait(false); } @@ -118,19 +105,15 @@ protected override async Task OnActivateAsync(CancellationToken cancellationToke IsClosable = false; } - protected override async Task OnDeactivateAsync(bool close, CancellationToken cancellationToken = default(CancellationToken)) - { + protected override async Task OnDeactivateAsync(bool close, CancellationToken cancellationToken = default(CancellationToken)) { await base.OnDeactivateAsync(close, cancellationToken).ConfigureAwait(false); - if (deactivationDelay.HasValue) - { + if (deactivationDelay.HasValue) { await Task.Delay(deactivationDelay.Value, cancellationToken).ConfigureAwait(false); } IsClosed = close; } - - private readonly TimeSpan? deactivationDelay; } } } diff --git a/src/Caliburn.Micro.Core.Tests/ConductorWithCollectionOneActiveTests.cs b/src/Caliburn.Micro.Core.Tests/ConductorTests/ConductorWithCollectionOneActiveTests.cs similarity index 77% rename from src/Caliburn.Micro.Core.Tests/ConductorWithCollectionOneActiveTests.cs rename to src/Caliburn.Micro.Core.Tests/ConductorTests/ConductorWithCollectionOneActiveTests.cs index 6e3371cd0..163bfa1be 100644 --- a/src/Caliburn.Micro.Core.Tests/ConductorWithCollectionOneActiveTests.cs +++ b/src/Caliburn.Micro.Core.Tests/ConductorTests/ConductorWithCollectionOneActiveTests.cs @@ -1,32 +1,13 @@ using System; using System.Threading; using System.Threading.Tasks; -using Xunit; - -namespace Caliburn.Micro.Core.Tests -{ - public class ConductorWithCollectionOneActiveTests - { - private class StateScreen : Screen - { - public bool IsClosed { get; private set; } - public bool IsClosable { get; set; } - - public override Task CanCloseAsync(CancellationToken cancellationToken) - { - return Task.FromResult(IsClosable); - } - protected override async Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) - { - await base.OnDeactivateAsync(close, cancellationToken); - IsClosed = close; - } - } +using Xunit; +namespace Caliburn.Micro.Core.Tests { + public class ConductorWithCollectionOneActiveTests { [Fact] - public void AddedItemAppearsInChildren() - { + public void AddedItemAppearsInChildren() { var conductor = new Conductor.Collection.OneActive(); var conducted = new Screen(); conductor.Items.Add(conducted); @@ -34,44 +15,38 @@ public void AddedItemAppearsInChildren() } [Fact] - public async Task CanCloseIsTrueWhenItemsAreClosable() - { + public async Task CanCloseIsTrueWhenItemsAreClosable() { var conductor = new Conductor.Collection.OneActive(); - var conducted = new StateScreen - { - IsClosable = true + var conducted = new StateScreen { + IsClosable = true, }; conductor.Items.Add(conducted); await ((IActivate)conductor).ActivateAsync(CancellationToken.None); - var canClose =await conductor.CanCloseAsync(CancellationToken.None); + bool canClose = await conductor.CanCloseAsync(CancellationToken.None); Assert.True(canClose); Assert.False(conducted.IsClosed); } [Fact(Skip = "Investigating close issue. http://caliburnmicro.codeplex.com/discussions/275824")] - public async Task CanCloseIsTrueWhenItemsAreNotClosableAndCloseStrategyCloses() - { - var conductor = new Conductor.Collection.OneActive - { - CloseStrategy = new DefaultCloseStrategy(true) + public async Task CanCloseIsTrueWhenItemsAreNotClosableAndCloseStrategyCloses() { + var conductor = new Conductor.Collection.OneActive { + CloseStrategy = new DefaultCloseStrategy(true), }; - var conducted = new StateScreen - { - IsClosable = true + var conducted = new StateScreen { + IsClosable = true, }; conductor.Items.Add(conducted); - await((IActivate)conductor).ActivateAsync(CancellationToken.None); - var canClose = await conductor.CanCloseAsync(CancellationToken.None); + await ((IActivate)conductor).ActivateAsync(CancellationToken.None); + bool canClose = await conductor.CanCloseAsync(CancellationToken.None); Assert.True(canClose); Assert.True(conducted.IsClosed); } [Fact] - public async Task ChildrenAreActivatedIfConductorIsActive() - { + public async Task ChildrenAreActivatedIfConductorIsActive() { var conductor = new Conductor.Collection.OneActive(); var conducted = new Screen(); conductor.Items.Add(conducted); @@ -82,8 +57,7 @@ public async Task ChildrenAreActivatedIfConductorIsActive() } [Fact(Skip = "ActiveItem currently set regardless of IsActive value. See http://caliburnmicro.codeplex.com/discussions/276375")] - public async Task ChildrenAreNotActivatedIfConductorIsNotActive() - { + public async Task ChildrenAreNotActivatedIfConductorIsNotActive() { var conductor = new Conductor.Collection.OneActive(); var conducted = new Screen(); conductor.Items.Add(conducted); @@ -93,15 +67,13 @@ public async Task ChildrenAreNotActivatedIfConductorIsNotActive() } [Fact(Skip = "Behavior currently allowed; under investigation. See http://caliburnmicro.codeplex.com/discussions/276373")] - public void ConductorCannotConductSelf() - { + public void ConductorCannotConductSelf() { var conductor = new Conductor.Collection.OneActive(); Assert.Throws(() => conductor.Items.Add(conductor)); } [Fact] - public void ParentItemIsSetOnAddedConductedItem() - { + public void ParentItemIsSetOnAddedConductedItem() { var conductor = new Conductor.Collection.OneActive(); var conducted = new Screen(); conductor.Items.Add(conducted); @@ -109,8 +81,7 @@ public void ParentItemIsSetOnAddedConductedItem() } [Fact] - public void ParentItemIsSetOnReplacedConductedItem() - { + public void ParentItemIsSetOnReplacedConductedItem() { var conductor = new Conductor.Collection.OneActive(); var originalConducted = new Screen(); conductor.Items.Add(originalConducted); @@ -120,8 +91,7 @@ public void ParentItemIsSetOnReplacedConductedItem() } [Fact(Skip = "This is not possible as we don't get the removed items in the event handler.")] - public void ParentItemIsUnsetOnClear() - { + public void ParentItemIsUnsetOnClear() { var conductor = new Conductor.Collection.OneActive(); var conducted = new Screen(); conductor.Items.Add(conducted); @@ -130,8 +100,7 @@ public void ParentItemIsUnsetOnClear() } [Fact] - public void ParentItemIsUnsetOnRemovedConductedItem() - { + public void ParentItemIsUnsetOnRemovedConductedItem() { var conductor = new Conductor.Collection.OneActive(); var conducted = new Screen(); conductor.Items.Add(conducted); @@ -140,8 +109,7 @@ public void ParentItemIsUnsetOnRemovedConductedItem() } [Fact] - public void ParentItemIsUnsetOnReplaceConductedItem() - { + public void ParentItemIsUnsetOnReplaceConductedItem() { var conductor = new Conductor.Collection.OneActive(); var conducted = new Screen(); conductor.Items.Add(conducted); @@ -150,5 +118,19 @@ public void ParentItemIsUnsetOnReplaceConductedItem() Assert.NotEqual(conductor, conducted.Parent); Assert.Equal(conductor, conducted2.Parent); } + + private sealed class StateScreen : Screen { + public bool IsClosed { get; private set; } + + public bool IsClosable { get; set; } + + public override Task CanCloseAsync(CancellationToken cancellationToken) + => Task.FromResult(IsClosable); + + protected override async Task OnDeactivateAsync(bool close, CancellationToken cancellationToken) { + await base.OnDeactivateAsync(close, cancellationToken); + IsClosed = close; + } + } } } diff --git a/src/Caliburn.Micro.Core.Tests/EventAggregatorTests.cs b/src/Caliburn.Micro.Core.Tests/EventAggregatorTests.cs deleted file mode 100644 index 02f764447..000000000 --- a/src/Caliburn.Micro.Core.Tests/EventAggregatorTests.cs +++ /dev/null @@ -1,175 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Moq; -using Xunit; - -namespace Caliburn.Micro.Core.Tests -{ - public class EventAggregatorSubscribing - { - [Fact] - public void A_null_subscriber_causes_an_ArgumentNullException() - { - Assert.Throws(() => { new EventAggregator().SubscribeOnPublishedThread(null); }); - } - - [Fact] - public void A_null_marshall_causes_an_ArgumentNullException() - { - var handlerStub = new Mock>().Object; - Assert.Throws(() => { new EventAggregator().Subscribe(handlerStub, null); }); - } - - [Fact] - public void A_valid_subscriber_is_assigned_as_a_handler_its_message_type() - { - var handlerStub = new Mock>().Object; - var aggregator = new EventAggregator(); - - Assert.False(aggregator.HandlerExistsFor(typeof(object))); - - aggregator.SubscribeOnPublishedThread(handlerStub); - - Assert.True(aggregator.HandlerExistsFor(typeof(object))); - } - } - - public class EventAggregatorUnsubscribing - { - [Fact] - public void A_null_subscriber_throws_an_ArgumentNullException() - { - Assert.Throws(() => { new EventAggregator().Unsubscribe(null); }); - } - - [Fact] - public void A_valid_subscriber_gets_removed_from_the_handler_list() - { - var eventAggregator = new EventAggregator(); - var handlerMock = new Mock>(); - - eventAggregator.SubscribeOnPublishedThread(handlerMock.Object); - Assert.True(eventAggregator.HandlerExistsFor(typeof(object))); - - eventAggregator.Unsubscribe(handlerMock.Object); - Assert.False(eventAggregator.HandlerExistsFor(typeof(object))); - } - } - - public class EventAggregatorPublishing - { - [Fact] - public async Task A_null_marshal_causes_an_ArgumentNullException() - { - await Assert.ThrowsAsync(async () => { await new EventAggregator().PublishAsync(new object(), null, CancellationToken.None); }); - } - - [Fact] - public async Task A_null_message_causes_an_ArgumentNullException() - { - await Assert.ThrowsAsync(async () => { await new EventAggregator().PublishOnCurrentThreadAsync(null, CancellationToken.None); }); - } - - [Fact] - public async Task A_valid_message_is_invoked_on_the_supplied_publication_marshaller() - { - var eventAggregator = new EventAggregator(); - var handlerMock = new Mock>(); - var marshallerCalled = false; - - eventAggregator.SubscribeOnPublishedThread(handlerMock.Object); - - await eventAggregator.PublishAsync(new object(), f => - { - marshallerCalled = true; - - return f(); - - }, CancellationToken.None); - - Assert.True(marshallerCalled); - } - - [Fact] - public async Task A_valid_message_is_invoked_on_the_supplied_subscription_marshaller() - { - var eventAggregator = new EventAggregator(); - var handlerMock = new Mock>(); - var marshallerCalled = false; - - eventAggregator.Subscribe(handlerMock.Object, f => - { - marshallerCalled = true; - - return f(); - - }); - - await eventAggregator.PublishOnCurrentThreadAsync(new object(), CancellationToken.None); - - Assert.True(marshallerCalled); - } - - [Fact] - public async Task A_valid_message_is_published_to_all_handlers() - { - var eventAggregator = new EventAggregator(); - - var handlerMockA = new Mock>(); - var handlerMockB = new Mock>(); - - eventAggregator.SubscribeOnPublishedThread(handlerMockA.Object); - eventAggregator.SubscribeOnPublishedThread(handlerMockB.Object); - - await eventAggregator.PublishOnCurrentThreadAsync(new object(), CancellationToken.None); - - handlerMockA.Verify(handlerStub => handlerStub.HandleAsync(It.IsAny(), It.IsAny()), - Times.AtLeastOnce()); - handlerMockB.Verify(handlerStub => handlerStub.HandleAsync(It.IsAny(), It.IsAny()), - Times.AtLeastOnce()); - } - - [Fact] - public async Task A_valid_message_is_published_to_all_handlers_respecting_inheritance() - { - var eventAggregator = new EventAggregator(); - - var handlerMockA = new Mock>(); - var handlerMockB = new Mock>(); - - eventAggregator.SubscribeOnPublishedThread(handlerMockA.Object); - eventAggregator.SubscribeOnPublishedThread(handlerMockB.Object); - - await eventAggregator.PublishOnCurrentThreadAsync(new Message(), CancellationToken.None); - - handlerMockA.Verify(handlerStub => handlerStub.HandleAsync(It.IsAny(), It.IsAny()), - Times.AtLeastOnce()); - handlerMockB.Verify(handlerStub => handlerStub.HandleAsync(It.IsAny(), It.IsAny()), - Times.AtLeastOnce()); - } - - public class MessageBase { } - public class Message : MessageBase { } - } - - public class EventAggregatorHandlerExistence - { - [Fact] - public void False_returned_when_no_handlers_exist_for_a_given_message() - { - Assert.False(new EventAggregator().HandlerExistsFor(typeof(object))); - } - - [Fact] - public void True_returned_when_a_handler_exists_for_a_given_message() - { - var handlerStub = new Mock>().Object; - var aggregator = new EventAggregator(); - - aggregator.SubscribeOnPublishedThread(handlerStub); - - Assert.True(aggregator.HandlerExistsFor(typeof(object))); - } - } -} diff --git a/src/Caliburn.Micro.Core.Tests/EventAggregatorTests/EventAggregatorHandlerExistenceTests.cs b/src/Caliburn.Micro.Core.Tests/EventAggregatorTests/EventAggregatorHandlerExistenceTests.cs new file mode 100644 index 000000000..a19678d2a --- /dev/null +++ b/src/Caliburn.Micro.Core.Tests/EventAggregatorTests/EventAggregatorHandlerExistenceTests.cs @@ -0,0 +1,20 @@ +using Moq; +using Xunit; + +namespace Caliburn.Micro.Core.Tests { + public class EventAggregatorHandlerExistenceTests { + [Fact] + public void False_returned_when_no_handlers_exist_for_a_given_message() + => Assert.False(new EventAggregator().HandlerExistsFor(typeof(object))); + + [Fact] + public void True_returned_when_a_handler_exists_for_a_given_message() { + IHandle handlerStub = new Mock>().Object; + var aggregator = new EventAggregator(); + + aggregator.SubscribeOnPublishedThread(handlerStub); + + Assert.True(aggregator.HandlerExistsFor(typeof(object))); + } + } +} diff --git a/src/Caliburn.Micro.Core.Tests/EventAggregatorTests/EventAggregatorPublishingTests.cs b/src/Caliburn.Micro.Core.Tests/EventAggregatorTests/EventAggregatorPublishingTests.cs new file mode 100644 index 000000000..eed7d990c --- /dev/null +++ b/src/Caliburn.Micro.Core.Tests/EventAggregatorTests/EventAggregatorPublishingTests.cs @@ -0,0 +1,101 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +using Moq; +using Xunit; + +namespace Caliburn.Micro.Core.Tests { + public class EventAggregatorPublishingTests { + [Fact] + public async Task A_null_marshal_causes_an_ArgumentNullException() + => await Assert.ThrowsAsync(async () => await new EventAggregator().PublishAsync(new object(), null, CancellationToken.None)); + + [Fact] + public async Task A_null_message_causes_an_ArgumentNullException() + => await Assert.ThrowsAsync(async () => await new EventAggregator().PublishOnCurrentThreadAsync(null, CancellationToken.None)); + + [Fact] + public async Task A_valid_message_is_invoked_on_the_supplied_publication_marshaller() { + var eventAggregator = new EventAggregator(); + var handlerMock = new Mock>(); + bool marshallerCalled = false; + + eventAggregator.SubscribeOnPublishedThread(handlerMock.Object); + + await eventAggregator.PublishAsync( + new object(), + f => { + marshallerCalled = true; + + return f(); + }, + CancellationToken.None); + + Assert.True(marshallerCalled); + } + + [Fact] + public async Task A_valid_message_is_invoked_on_the_supplied_subscription_marshaller() { + var eventAggregator = new EventAggregator(); + var handlerMock = new Mock>(); + bool marshallerCalled = false; + + eventAggregator.Subscribe(handlerMock.Object, f => { + marshallerCalled = true; + + return f(); + }); + + await eventAggregator.PublishOnCurrentThreadAsync(new object(), CancellationToken.None); + + Assert.True(marshallerCalled); + } + + [Fact] + public async Task A_valid_message_is_published_to_all_handlers() { + var eventAggregator = new EventAggregator(); + + var handlerMockA = new Mock>(); + var handlerMockB = new Mock>(); + + eventAggregator.SubscribeOnPublishedThread(handlerMockA.Object); + eventAggregator.SubscribeOnPublishedThread(handlerMockB.Object); + + await eventAggregator.PublishOnCurrentThreadAsync(new object(), CancellationToken.None); + + handlerMockA.Verify( + handlerStub => handlerStub.HandleAsync(It.IsAny(), It.IsAny()), + Times.AtLeastOnce()); + handlerMockB.Verify( + handlerStub => handlerStub.HandleAsync(It.IsAny(), It.IsAny()), + Times.AtLeastOnce()); + } + + [Fact] + public async Task A_valid_message_is_published_to_all_handlers_respecting_inheritance() { + var eventAggregator = new EventAggregator(); + + var handlerMockA = new Mock>(); + var handlerMockB = new Mock>(); + + eventAggregator.SubscribeOnPublishedThread(handlerMockA.Object); + eventAggregator.SubscribeOnPublishedThread(handlerMockB.Object); + + await eventAggregator.PublishOnCurrentThreadAsync(new Message(), CancellationToken.None); + + handlerMockA.Verify( + handlerStub => handlerStub.HandleAsync(It.IsAny(), It.IsAny()), + Times.AtLeastOnce()); + handlerMockB.Verify( + handlerStub => handlerStub.HandleAsync(It.IsAny(), It.IsAny()), + Times.AtLeastOnce()); + } + + public class MessageBase { + } + + public sealed class Message : MessageBase { + } + } +} diff --git a/src/Caliburn.Micro.Core.Tests/EventAggregatorTests/EventAggregatorSubscribingTests.cs b/src/Caliburn.Micro.Core.Tests/EventAggregatorTests/EventAggregatorSubscribingTests.cs new file mode 100644 index 000000000..3a763999a --- /dev/null +++ b/src/Caliburn.Micro.Core.Tests/EventAggregatorTests/EventAggregatorSubscribingTests.cs @@ -0,0 +1,30 @@ +using System; + +using Moq; +using Xunit; + +namespace Caliburn.Micro.Core.Tests { + public class EventAggregatorSubscribingTests { + [Fact] + public void A_null_subscriber_causes_an_ArgumentNullException() + => Assert.Throws(() => { new EventAggregator().SubscribeOnPublishedThread(null); }); + + [Fact] + public void A_null_marshall_causes_an_ArgumentNullException() { + IHandle handlerStub = new Mock>().Object; + Assert.Throws(() => { new EventAggregator().Subscribe(handlerStub, null); }); + } + + [Fact] + public void A_valid_subscriber_is_assigned_as_a_handler_its_message_type() { + IHandle handlerStub = new Mock>().Object; + var aggregator = new EventAggregator(); + + Assert.False(aggregator.HandlerExistsFor(typeof(object))); + + aggregator.SubscribeOnPublishedThread(handlerStub); + + Assert.True(aggregator.HandlerExistsFor(typeof(object))); + } + } +} diff --git a/src/Caliburn.Micro.Core.Tests/EventAggregatorTests/EventAggregatorUnsubscribingTests.cs b/src/Caliburn.Micro.Core.Tests/EventAggregatorTests/EventAggregatorUnsubscribingTests.cs new file mode 100644 index 000000000..229d2ce8d --- /dev/null +++ b/src/Caliburn.Micro.Core.Tests/EventAggregatorTests/EventAggregatorUnsubscribingTests.cs @@ -0,0 +1,24 @@ +using System; + +using Moq; +using Xunit; + +namespace Caliburn.Micro.Core.Tests { + public class EventAggregatorUnsubscribingTests { + [Fact] + public void A_null_subscriber_throws_an_ArgumentNullException() + => Assert.Throws(() => { new EventAggregator().Unsubscribe(null); }); + + [Fact] + public void A_valid_subscriber_gets_removed_from_the_handler_list() { + var eventAggregator = new EventAggregator(); + var handlerMock = new Mock>(); + + eventAggregator.SubscribeOnPublishedThread(handlerMock.Object); + Assert.True(eventAggregator.HandlerExistsFor(typeof(object))); + + eventAggregator.Unsubscribe(handlerMock.Object); + Assert.False(eventAggregator.HandlerExistsFor(typeof(object))); + } + } +} diff --git a/src/Caliburn.Micro.Core.Tests/IoCTests.cs b/src/Caliburn.Micro.Core.Tests/IocTests/IoC_Get_Tests.cs similarity index 64% rename from src/Caliburn.Micro.Core.Tests/IoCTests.cs rename to src/Caliburn.Micro.Core.Tests/IocTests/IoC_Get_Tests.cs index a3c5b1160..f04a41a8f 100644 --- a/src/Caliburn.Micro.Core.Tests/IoCTests.cs +++ b/src/Caliburn.Micro.Core.Tests/IocTests/IoC_Get_Tests.cs @@ -1,93 +1,74 @@ using System; using System.Collections.Generic; -using Xunit; - -namespace Caliburn.Micro.Core.Tests -{ - public class IoCGet - { - private class IoCReset : IDisposable - { - private readonly Action _buildUp; - private readonly Func> _getAllInstances; - private readonly Func _getInstance; - - private IoCReset() - { - _getInstance = IoC.GetInstance; - _getAllInstances = IoC.GetAllInstances; - _buildUp = IoC.BuildUp; - } - public void Dispose() - { - IoC.GetInstance = _getInstance; - IoC.GetAllInstances = _getAllInstances; - IoC.BuildUp = _buildUp; - } - - public static IDisposable Create() - { - return new IoCReset(); - } - } +using Xunit; +namespace Caliburn.Micro.Core.Tests { + public class IoC_Get_Tests { [Fact] - public void A_not_initialized_BuildUp_throws_an_InvalidOperationException() - { - using (IoCReset.Create()) - { + public void A_not_initialized_BuildUp_throws_an_InvalidOperationException() { + using (IoCReset.Create()) { Assert.Throws(() => IoC.BuildUp(new object())); } } [Fact] - public void A_not_initialized_GetAllInstances_throws_an_InvalidOperationException() - { - using (IoCReset.Create()) - { + public void A_not_initialized_GetAllInstances_throws_an_InvalidOperationException() { + using (IoCReset.Create()) { Assert.Throws(() => IoC.GetAll()); } } - [Fact] - public void A_not_initialized_GetInstance_throws_an_InvalidOperationException() - { - using (IoCReset.Create()) - { + public void A_not_initialized_GetInstance_throws_an_InvalidOperationException() { + using (IoCReset.Create()) { Assert.Throws(() => IoC.Get()); } } [Fact] - public void A_null_GetInstance_throws_a_NullRefrenceException() - { - using (IoCReset.Create()) - { + public void A_null_GetInstance_throws_a_NullRefrenceException() { + using (IoCReset.Create()) { IoC.GetInstance = null; Assert.Throws(() => IoC.Get()); } } [Fact] - public void A_valid_GetAll_does_not_throw() - { - using (IoCReset.Create()) - { - IoC.GetAllInstances = type => new object[] {"foo", "bar"}; + public void A_valid_GetAll_does_not_throw() { + using (IoCReset.Create()) { + IoC.GetAllInstances = type => new object[] { "foo", "bar" }; IoC.GetAll(); } } [Fact] - public void A_valid_GetInstance_does_not_throw() - { - using (IoCReset.Create()) - { + public void A_valid_GetInstance_does_not_throw() { + using (IoCReset.Create()) { IoC.GetInstance = (type, s) => new object(); IoC.Get(); } } + + private sealed class IoCReset : IDisposable { + private readonly Action _buildUp; + private readonly Func> _getAllInstances; + private readonly Func _getInstance; + + private IoCReset() { + _getInstance = IoC.GetInstance; + _getAllInstances = IoC.GetAllInstances; + _buildUp = IoC.BuildUp; + } + + public static IDisposable Create() + => new IoCReset(); + + public void Dispose() { + IoC.GetInstance = _getInstance; + IoC.GetAllInstances = _getAllInstances; + IoC.BuildUp = _buildUp; + } + } } } diff --git a/src/Caliburn.Micro.Core.Tests/IocTests/SimpleContainer_Checking_For_Handler_Tests.cs b/src/Caliburn.Micro.Core.Tests/IocTests/SimpleContainer_Checking_For_Handler_Tests.cs new file mode 100644 index 000000000..ccd8f6473 --- /dev/null +++ b/src/Caliburn.Micro.Core.Tests/IocTests/SimpleContainer_Checking_For_Handler_Tests.cs @@ -0,0 +1,20 @@ +using Xunit; + +namespace Caliburn.Micro.Core.Tests { + public class SimpleContainer_Checking_For_Handler_Tests { + [Fact] + public void HasHandler_returns_false_when_handler_does_not_exist() { + Assert.False(new SimpleContainer().HasHandler(typeof(object), null)); + Assert.False(new SimpleContainer().HasHandler(null, "Object")); + } + + [Fact] + public void HasHandler_returns_true_when_handler_exists() { + var container = new SimpleContainer(); + container.RegisterPerRequest(typeof(object), "Object", typeof(object)); + + Assert.True(container.HasHandler(typeof(object), null)); + Assert.True(container.HasHandler(null, "Object")); + } + } +} diff --git a/src/Caliburn.Micro.Core.Tests/IocTests/SimpleContainer_Creating_AChild_Container_Tests.cs b/src/Caliburn.Micro.Core.Tests/IocTests/SimpleContainer_Creating_AChild_Container_Tests.cs new file mode 100644 index 000000000..508826b42 --- /dev/null +++ b/src/Caliburn.Micro.Core.Tests/IocTests/SimpleContainer_Creating_AChild_Container_Tests.cs @@ -0,0 +1,34 @@ +using Xunit; + +namespace Caliburn.Micro.Core.Tests { + public class SimpleContainer_Creating_AChild_Container_Tests { + [Fact] + public void Singleton_instances_are_the_same_across_parent_and_child() { + var container = new SimpleContainer(); + container.Singleton(); + SimpleContainer childContainer = container.CreateChildContainer(); + + object parentInstance = container.GetInstance(typeof(object), null); + object childInstance = childContainer.GetInstance(typeof(object), null); + + Assert.Same(parentInstance, childInstance); + } + + [Fact] + public void The_child_container_returned_contains_parent_entries() { + var container = new SimpleContainer(); + container.PerRequest(); + SimpleContainer childContainer = container.CreateChildContainer(); + + Assert.NotNull(childContainer.GetInstance(typeof(object), null)); + } + + [Fact] + public void The_child_container_returned_is_not_the_same_instance_as_its_parent() { + var container = new SimpleContainer(); + SimpleContainer childContainer = container.CreateChildContainer(); + + Assert.NotSame(container, childContainer); + } + } +} diff --git a/src/Caliburn.Micro.Core.Tests/IocTests/SimpleContainer_Find_Constructor_Tests.cs b/src/Caliburn.Micro.Core.Tests/IocTests/SimpleContainer_Find_Constructor_Tests.cs new file mode 100644 index 000000000..f7d6491c9 --- /dev/null +++ b/src/Caliburn.Micro.Core.Tests/IocTests/SimpleContainer_Find_Constructor_Tests.cs @@ -0,0 +1,72 @@ +using Xunit; + +namespace Caliburn.Micro.Core.Tests { + public class SimpleContainer_Find_Constructor_Tests { + [Fact] + public void Container_Finds_Single_Constructor() { + var container = new SimpleContainer(); + container.Singleton(); + container.GetInstance(typeof(SingleEmptyConstructorType), null); + } + + [Fact] + public void Container_No_EmptyConstructor() { + var container = new SimpleContainer(); + container.Singleton(); + container.GetInstance(typeof(SingleNonEmptyConstructorType), null); + } + + [Fact] + public void Container_SingleIntConstructor() { + var container = new SimpleContainer(); + container.Singleton(); + container.RegisterInstance(typeof(int), "x", 4); + var inst = (SingleIntConstructor)container.GetInstance(typeof(SingleIntConstructor), null); + Assert.Equal(4, inst.Value); + } + + [Fact] + public void Container_ChooseConstructorWithRegisteredParameter() { + var container = new SimpleContainer(); + container.Singleton(); + container.RegisterInstance(typeof(int), null, 23); + var inst = (TwoConstructors)container.GetInstance(typeof(TwoConstructors), null); + Assert.Equal(23, inst.Value); + } + + [Fact] + public void Container_ChooseEmptyConstructorWithoutRegisteredParameter() { + var container = new SimpleContainer(); + container.Singleton(); + var inst = (TwoConstructors)container.GetInstance(typeof(TwoConstructors), null); + Assert.Equal(42, inst.Value); + } + + private sealed class SingleNonEmptyConstructorType { + public SingleNonEmptyConstructorType(SingleEmptyConstructorType type) + => _ = type; + } + + private sealed class SingleEmptyConstructorType { + public SingleEmptyConstructorType() { + } + } + + private sealed class SingleIntConstructor { + public SingleIntConstructor(int x) + => Value = x; + + public int Value { get; private set; } + } + + private sealed class TwoConstructors { + public TwoConstructors() + => Value = 42; + + public TwoConstructors(int value) + => Value = value; + + public int Value { get; set; } + } + } +} diff --git a/src/Caliburn.Micro.Core.Tests/IocTests/SimpleContainer_Getting_ASingle_Instance_Tests.cs b/src/Caliburn.Micro.Core.Tests/IocTests/SimpleContainer_Getting_ASingle_Instance_Tests.cs new file mode 100644 index 000000000..069707dcd --- /dev/null +++ b/src/Caliburn.Micro.Core.Tests/IocTests/SimpleContainer_Getting_ASingle_Instance_Tests.cs @@ -0,0 +1,24 @@ +using Xunit; + +namespace Caliburn.Micro.Core.Tests { + public class SimpleContainer_Getting_ASingle_Instance_Tests { + [Fact] + public void An_instance_is_returned_for_the_type_specified_if_found() { + var container = new SimpleContainer(); + container.PerRequest(); + + Assert.NotNull(container.GetInstance(typeof(object), null)); + } + + [Fact] + public void Instances_can_be_found_by_name_only() { + var container = new SimpleContainer(); + container.RegisterPerRequest(typeof(object), "AnObject", typeof(object)); + + Assert.NotNull(container.GetInstance(null, "AnObject")); + } + + [Fact] + public void Null_is_returned_when_no_instance_is_found() => Assert.Null(new SimpleContainer().GetInstance(typeof(object), null)); + } +} diff --git a/src/Caliburn.Micro.Core.Tests/IocTests/SimpleContainer_Recursive_Tests.cs b/src/Caliburn.Micro.Core.Tests/IocTests/SimpleContainer_Recursive_Tests.cs new file mode 100644 index 000000000..0277e1c8c --- /dev/null +++ b/src/Caliburn.Micro.Core.Tests/IocTests/SimpleContainer_Recursive_Tests.cs @@ -0,0 +1,140 @@ +using System.Collections.Generic; +using System.Linq; + +using Xunit; + +namespace Caliburn.Micro.Core.Tests { + public class SimpleContainer_Recursive_Tests { + private interface IComponent { + } + + private interface IDependency1 { + } + + private interface IDependency2 { + } + + private interface IEnumerableDependency { + } + + [Fact] + public void Instances_Are_Recursively_Property_Injected_When_Enabled() { + var container = new SimpleContainer { + EnablePropertyInjection = true, + }; + + RegisterAllComponents(container); + + var instance = (Component)container.GetInstance(); + + Assert.NotNull(((Dependency1)instance.Dependency1).Dependency2); + } + + [Fact] + public void BuildUp_Injects_All_Registered_Dependencies_Non_Recursively() { + var container = new SimpleContainer(); + RegisterAllComponents(container); + + var instance = (Component)container.GetInstance(); + container.BuildUp(instance); + + Assert.Null(((Dependency1)instance.Dependency1).Dependency2); + } + + [Fact] + public void BuildUp_Injects_Dependencies_Recursively() { + var container = new SimpleContainer { + EnablePropertyInjection = true, + }; + + RegisterAllComponents(container); + + var instance = (Component)container.GetInstance(); + container.BuildUp(instance); + + Assert.NotNull(((Dependency1)instance.Dependency1).Dependency2); + } + + [Fact] + public void BuildUp_Injects_Enumerable_Dependencies() { + var container = new SimpleContainer { + EnablePropertyInjection = true, + }; + + RegisterAllComponents(container); + + var instance = (Component)container.GetInstance(); + container.BuildUp(instance); + + Assert.Equal(2, ((Dependency1)instance.Dependency1).EnumerableDependencies.Count); + } + + [Fact] + public void BuildUp_Injects_Properties_Of_Enumerable_Dependencies() { + var container = new SimpleContainer { + EnablePropertyInjection = true, + }; + + RegisterAllComponents(container); + + var instance = (Component)container.GetInstance(); + container.BuildUp(instance); + + Assert.NotNull(((EnumerableDependency1)((Dependency1)instance.Dependency1).EnumerableDependencies.First()).Dependency2); + } + + [Fact] + public void BuildUp_Throws_When_Multiple_Types_Found_For_Component() { + var container = new SimpleContainer(); + RegisterAllComponents(container); + container.RegisterPerRequest(typeof(IDependency1), null, typeof(SecondDependency1)); + + var instance = (Component)container.GetInstance(); + + try { + container.BuildUp(instance); + } catch { + return; + } + + Assert.NotNull(null); + } + + private static void RegisterAllComponents(SimpleContainer container) { + container.RegisterPerRequest(typeof(IComponent), null, typeof(Component)); + container.RegisterPerRequest(typeof(IDependency1), null, typeof(Dependency1)); + container.RegisterPerRequest(typeof(IDependency2), null, typeof(Dependency2)); + container.RegisterPerRequest(typeof(NonInterfaceDependency), null, typeof(NonInterfaceDependency)); + container.RegisterPerRequest(typeof(IEnumerableDependency), null, typeof(EnumerableDependency1)); + container.RegisterPerRequest(typeof(IEnumerableDependency), null, typeof(EnumerableDependency2)); + } + + private sealed class Component : IComponent { + public IDependency1 Dependency1 { get; set; } + + public NonInterfaceDependency NonInterfaceDependency { get; set; } + } + + private class Dependency1 : IDependency1 { + public IDependency2 Dependency2 { get; set; } + + public IList EnumerableDependencies { get; set; } + } + + private sealed class Dependency2 : IDependency2 { + } + + private sealed class EnumerableDependency1 : IEnumerableDependency { + public IDependency2 Dependency2 { get; set; } + } + + private sealed class EnumerableDependency2 : IEnumerableDependency { + } + + private sealed class NonInterfaceDependency { + } + + private sealed class SecondDependency1 : Dependency1 { + } + } +} diff --git a/src/Caliburn.Micro.Core.Tests/IocTests/SimpleContainer_Registering_Instances_Tests.cs b/src/Caliburn.Micro.Core.Tests/IocTests/SimpleContainer_Registering_Instances_Tests.cs new file mode 100644 index 000000000..444fc0ed2 --- /dev/null +++ b/src/Caliburn.Micro.Core.Tests/IocTests/SimpleContainer_Registering_Instances_Tests.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using System.Linq; + +using Xunit; + +namespace Caliburn.Micro.Core.Tests { + public class SimpleContainer_Registering_Instances_Tests { + [Fact] + public void Instances_registed_Singleton_return_the_same_instance_for_each_call() { + var container = new SimpleContainer(); + container.Singleton(); + + object instanceA = container.GetInstance(typeof(object), null); + object instanceB = container.GetInstance(typeof(object), null); + + Assert.Same(instanceA, instanceB); + } + + [Fact] + public void Instances_registered_PerRequest_returns_a_different_instance_for_each_call() { + var container = new SimpleContainer(); + container.PerRequest(); + + object instanceA = container.GetInstance(typeof(object), null); + object instanceB = container.GetInstance(typeof(object), null); + + Assert.NotSame(instanceA, instanceB); + } + + [Fact] + public void Instances_registered_with_different_keys_get_all_instances_return_all() { + var container = new SimpleContainer(); + container.RegisterInstance(typeof(object), "test", new object()); + container.RegisterInstance(typeof(object), "test", new object()); + + IEnumerable results = container.GetAllInstances("test"); + + Assert.Equal(2, results.Count()); + } + } +} diff --git a/src/Caliburn.Micro.Core.Tests/SimpleContainerTests.cs b/src/Caliburn.Micro.Core.Tests/SimpleContainerTests.cs deleted file mode 100644 index e6c1381a6..000000000 --- a/src/Caliburn.Micro.Core.Tests/SimpleContainerTests.cs +++ /dev/null @@ -1,355 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Xunit; - -namespace Caliburn.Micro.Core.Tests -{ - public class SimpleContainerCreatingAChildContainer - { - [Fact] - public void Singleton_instances_are_the_same_across_parent_and_child() - { - var container = new SimpleContainer(); - container.Singleton(); - var childContainer = container.CreateChildContainer(); - - var parentInstance = container.GetInstance(typeof(object), null); - var childInstance = childContainer.GetInstance(typeof(object), null); - - Assert.Same(parentInstance, childInstance); - } - - [Fact] - public void The_child_container_returned_contains_parent_entries() - { - var container = new SimpleContainer(); - container.PerRequest(); - var childContainer = container.CreateChildContainer(); - - Assert.NotNull(childContainer.GetInstance(typeof(object), null)); - } - - [Fact] - public void The_child_container_returned_is_not_the_same_instance_as_its_parent() - { - var container = new SimpleContainer(); - var childContainer = container.CreateChildContainer(); - - Assert.NotSame(container, childContainer); - } - } - - public class SimpleContainerCheckingForHandler - { - [Fact] - public void HasHandler_returns_false_when_handler_does_not_exist() - { - Assert.False(new SimpleContainer().HasHandler(typeof(object), null)); - Assert.False(new SimpleContainer().HasHandler(null, "Object")); - } - - [Fact] - public void HasHandler_returns_true_when_handler_exists() - { - var container = new SimpleContainer(); - container.RegisterPerRequest(typeof(object), "Object", typeof(object)); - - Assert.True(container.HasHandler(typeof(object), null)); - Assert.True(container.HasHandler(null, "Object")); - } - } - - public class SimpleContainerGettingASingleInstance - { - [Fact] - public void An_instance_is_returned_for_the_type_specified_if_found() - { - var container = new SimpleContainer(); - container.PerRequest(); - - Assert.NotNull(container.GetInstance(typeof(object), null)); - } - - [Fact] - public void Instances_can_be_found_by_name_only() - { - var container = new SimpleContainer(); - container.RegisterPerRequest(typeof(object), "AnObject", typeof(object)); - - Assert.NotNull(container.GetInstance(null, "AnObject")); - } - - [Fact] - public void Null_is_returned_when_no_instance_is_found() - { - Assert.Null(new SimpleContainer().GetInstance(typeof(object), null)); - } - } - - public class SimpleContainerRegisteringInstances - { - [Fact] - public void Instances_registed_Singleton_return_the_same_instance_for_each_call() - { - var container = new SimpleContainer(); - container.Singleton(); - - var instanceA = container.GetInstance(typeof(object), null); - var instanceB = container.GetInstance(typeof(object), null); - - Assert.Same(instanceA, instanceB); - } - - [Fact] - public void Instances_registered_PerRequest_returns_a_different_instance_for_each_call() - { - var container = new SimpleContainer(); - container.PerRequest(); - - var instanceA = container.GetInstance(typeof(object), null); - var instanceB = container.GetInstance(typeof(object), null); - - Assert.NotSame(instanceA, instanceB); - } - - [Fact] - public void Instances_registered_with_different_keys_get_all_instances_return_all() - { - var container = new SimpleContainer(); - container.RegisterInstance(typeof(object), "test", new object()); - container.RegisterInstance(typeof(object), "test", new object()); - - var results = container.GetAllInstances("test"); - - Assert.Equal(2, results.Count()); - } - } - - public class SimpleContainer_Find_Constructor - { - - public class SingleEmptyConstructorType - { - public SingleEmptyConstructorType() - { - - } - } - - [Fact] - public void Container_Finds_Single_Constructor() - { - var container = new SimpleContainer(); - container.Singleton(); - container.GetInstance(typeof(SingleEmptyConstructorType), null); - } - - public class SingleNonEmptyConstructorType - { - public SingleNonEmptyConstructorType(SimpleContainer_Find_Constructor.SingleEmptyConstructorType type) - { - } - } - - [Fact] - public void Container_No_EmptyConstructor() - { - var container = new SimpleContainer(); - container.Singleton(); - container.GetInstance(typeof(SingleNonEmptyConstructorType), null); - } - - public class SingleIntConstructor - { - public int Value { get; private set; } - - public SingleIntConstructor(int x) - { - this.Value = x; - } - } - - [Fact] - public void Container_SingleIntConstructor() - { - var container = new SimpleContainer(); - container.Singleton(); - container.RegisterInstance(typeof(int), "x", 4); - var inst = (SingleIntConstructor)container.GetInstance(typeof(SingleIntConstructor), null); - Assert.Equal(4, inst.Value); - } - - public class TwoConstructors - { - public int Value { get; set; } - - public TwoConstructors() - { - this.Value = 42; - } - - public TwoConstructors(int value) - { - Value = value; - } - } - - [Fact] - public void Container_ChooseConstructorWithRegisteredParameter() - { - var container = new SimpleContainer(); - container.Singleton(); - container.RegisterInstance(typeof(int), null, 23); - var inst = (TwoConstructors)container.GetInstance(typeof(TwoConstructors), null); - Assert.Equal(23, inst.Value); - } - - [Fact] - public void Container_ChooseEmptyConstructorWithoutRegisteredParameter() - { - var container = new SimpleContainer(); - container.Singleton(); - var inst = (TwoConstructors)container.GetInstance(typeof(TwoConstructors), null); - Assert.Equal(42, inst.Value); - } - } - - public class SimpleContainer_Recursive - { - private interface IComponent { } - private interface IDependency1 { } - private interface IDependency2 { } - private interface IEnumerableDependency { } - - private class Component : IComponent - { - public IDependency1 Dependency1 { get; set; } - public NonInterfaceDependency NonInterfaceDependency { get; set; } - } - - private class Dependency1 : IDependency1 - { - public IDependency2 Dependency2 { get; set; } - public IList EnumerableDependencies { get; set; } - } - - private class Dependency2 : IDependency2 { } - - private class EnumerableDependency1 : IEnumerableDependency - { - public IDependency2 Dependency2 { get; set; } - } - - private class EnumerableDependency2 : IEnumerableDependency { } - - private class NonInterfaceDependency { } - - private class SecondDependency1 : Dependency1 { } - - private static void RegisterAllComponents(SimpleContainer container) - { - container.RegisterPerRequest(typeof(IComponent), null, typeof(Component)); - container.RegisterPerRequest(typeof(IDependency1), null, typeof(Dependency1)); - container.RegisterPerRequest(typeof(IDependency2), null, typeof(Dependency2)); - container.RegisterPerRequest(typeof(NonInterfaceDependency), null, typeof(NonInterfaceDependency)); - container.RegisterPerRequest(typeof(IEnumerableDependency), null, typeof(EnumerableDependency1)); - container.RegisterPerRequest(typeof(IEnumerableDependency), null, typeof(EnumerableDependency2)); - } - - [Fact] - public void Instances_Are_Recursively_Property_Injected_When_Enabled() - { - var container = new SimpleContainer - { - EnablePropertyInjection = true - }; - - RegisterAllComponents(container); - - var instance = (Component)container.GetInstance(); - - Assert.NotNull(((Dependency1)instance.Dependency1).Dependency2); - } - - [Fact] - public void BuildUp_Injects_All_Registered_Dependencies_Non_Recursively() - { - var container = new SimpleContainer(); - RegisterAllComponents(container); - - var instance = (Component)container.GetInstance(); - container.BuildUp(instance); - - Assert.Null(((Dependency1)instance.Dependency1).Dependency2); - } - - [Fact] - public void BuildUp_Injects_Dependencies_Recursively() - { - var container = new SimpleContainer - { - EnablePropertyInjection = true - }; - - RegisterAllComponents(container); - - var instance = (Component)container.GetInstance(); - container.BuildUp(instance); - - Assert.NotNull(((Dependency1)instance.Dependency1).Dependency2); - } - - [Fact] - public void BuildUp_Injects_Enumerable_Dependencies() - { - var container = new SimpleContainer - { - EnablePropertyInjection = true - }; - - RegisterAllComponents(container); - - var instance = (Component)container.GetInstance(); - container.BuildUp(instance); - - Assert.Equal(2, (((Dependency1)instance.Dependency1).EnumerableDependencies.Count)); - } - - [Fact] - public void BuildUp_Injects_Properties_Of_Enumerable_Dependencies() - { - var container = new SimpleContainer - { - EnablePropertyInjection = true - }; - - RegisterAllComponents(container); - - var instance = (Component)container.GetInstance(); - container.BuildUp(instance); - - Assert.NotNull(((EnumerableDependency1)(((Dependency1)instance.Dependency1).EnumerableDependencies.First())).Dependency2); - } - - [Fact] - public void BuildUp_Throws_When_Multiple_Types_Found_For_Component() - { - var container = new SimpleContainer(); - RegisterAllComponents(container); - container.RegisterPerRequest(typeof(IDependency1), null, typeof(SecondDependency1)); - - var instance = (Component)container.GetInstance(); - - try - { - container.BuildUp(instance); - } - catch - { - return; - } - - Assert.NotNull(null); - } - } -} diff --git a/src/Caliburn.Micro.Core/Caliburn.Micro.Core.csproj b/src/Caliburn.Micro.Core/Caliburn.Micro.Core.csproj index bbcf4e6a1..03d8f849d 100644 --- a/src/Caliburn.Micro.Core/Caliburn.Micro.Core.csproj +++ b/src/Caliburn.Micro.Core/Caliburn.Micro.Core.csproj @@ -10,84 +10,21 @@ latest - - - - - - true - true - true - - - - $(NoWarn);CA1711;CA1003;CA1070;CA1034;CA1052;CA1062;CA2007 - $(NoWarn);CA1033;CA1031;CA1716;CA2008;CA1849;CA1822;CA1812 - - - - 7 - prompt - True - All - latest-all - true - True - True - True - True - true - - - - - - - - - - Caliburn.Micro.Core - - - - - - - - + + - + + + + + diff --git a/src/Caliburn.Micro.Maui/Caliburn.Micro.Maui.csproj b/src/Caliburn.Micro.Maui/Caliburn.Micro.Maui.csproj index 59cc27d9b..9cfa1c13f 100644 --- a/src/Caliburn.Micro.Maui/Caliburn.Micro.Maui.csproj +++ b/src/Caliburn.Micro.Maui/Caliburn.Micro.Maui.csproj @@ -1,35 +1,35 @@  - - net6.0;net6.0-android;net6.0-ios;net6.0-maccatalyst - $(TargetFrameworks);net6.0-windows10.0.19041 - $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage - - true - true - + + + net6.0; + net6.0-android; + net6.0-ios; + net6.0-maccatalyst + + + + MAUI - 14.2 - 14.0 - 21.0 - 10.0.17763.0 - 10.0.17763.0 - + true + true + disable + 8.0 Caliburn.Micro.Maui Caliburn.Micro.Maui - - - enable - 8.0 - + $(TargetList) + $(TargetFrameworks);net6.0-windows10.0.19041 + $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage - - - - - + 14.2 + 14.0 + 21.0 + 10.0.17763.0 + + 10.0.17763.0 + @@ -52,23 +52,9 @@ - - - - - - - - - - - - - - - - - + + Platforms\Maui\%(RecursiveDir)%(Filename)%(Extension) + @@ -77,22 +63,28 @@ - + + Platforms\Maui\Android\%(RecursiveDir)%(Filename)%(Extension) + - + - - - - - - + + Platforms\Maui\ios\%(RecursiveDir)%(Filename)%(Extension) + - - + + Platforms\Maui\Windows\%(RecursiveDir)%(Filename)%(Extension) + + + + + + + diff --git a/src/Caliburn.Micro.Platform.Core/AssemblySource.cs b/src/Caliburn.Micro.Platform.Core/AssemblySource.cs index 1d90fb78c..400b2b1d8 100644 --- a/src/Caliburn.Micro.Platform.Core/AssemblySource.cs +++ b/src/Caliburn.Micro.Platform.Core/AssemblySource.cs @@ -5,123 +5,45 @@ using System.Linq; using System.Reflection; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro { /// /// A source of assemblies that are inspectable by the framework. /// - public static class AssemblySource - { + public static class AssemblySource { /// /// The singleton instance of the AssemblySource used by the framework. /// - public static readonly IObservableCollection Instance = new BindableCollection(); - - - /// - /// Adds a collection of assemblies to AssemblySource - /// - /// The assemblies to add - public static void AddRange(IEnumerable assemblies) - { - foreach(var assembly in assemblies) - { - try - { - if (!Instance.Contains(assembly)) - Instance.Add(assembly); - } - catch (ArgumentException) - { - // ignore - } - } - } - - /// - /// Finds a type which matches one of the elements in the sequence of names. - /// - public static Func, Type> FindTypeByNames = names => - { - if (names == null) - { - return null; - } - - var type = names - .Join(Instance.SelectMany(a => a.ExportedTypes), n => n, t => t.FullName, (n, t) => t) - .FirstOrDefault(); - return type; - }; - } - - /// - /// A caching subsystem for . - /// - public static class AssemblySourceCache - { - private static bool isInstalled; - private static readonly IDictionary TypeNameCache = new Dictionary(); - - /// - /// Extracts the types from the spezified assembly for storing in the cache. - /// - public static Func> ExtractTypes = assembly => - assembly.ExportedTypes - .Where(t => - typeof(INotifyPropertyChanged).GetTypeInfo().IsAssignableFrom(t.GetTypeInfo())); + public static readonly IObservableCollection Instance + = new BindableCollection(); /// - /// Installs the caching subsystem. + /// Gets or sets func to finds a type which matches one of the elements in the sequence of names. /// - public static System.Action Install = () => - { - if (isInstalled) - { - return; - } - - isInstalled = true; - - AssemblySource.Instance.CollectionChanged += (s, e) => - { - switch (e.Action) - { - case NotifyCollectionChangedAction.Add: - e.NewItems.OfType() - .SelectMany(a => ExtractTypes(a)) - .Apply(AddTypeAssembly); - break; - case NotifyCollectionChangedAction.Remove: - case NotifyCollectionChangedAction.Replace: - case NotifyCollectionChangedAction.Reset: - TypeNameCache.Clear(); - AssemblySource.Instance - .SelectMany(a => ExtractTypes(a)) - .Apply(AddTypeAssembly); - break; - } - }; - - AssemblySource.Instance.Refresh(); - - AssemblySource.FindTypeByNames = names => - { - if (names == null) - { + public static Func, Type> FindTypeByNames { get; set; } + = names => { + if (names == null) { return null; } - var type = names.Select(n => TypeNameCache.GetValueOrDefault(n)).FirstOrDefault(t => t != null); + Type type = names + .Join(Instance.SelectMany(a => a.ExportedTypes), n => n, t => t.FullName, (n, t) => t) + .FirstOrDefault(); return type; }; - }; - private static void AddTypeAssembly(Type type) - { - if (!TypeNameCache.ContainsKey(type.FullName)) - { - TypeNameCache.Add(type.FullName, type); + /// + /// Adds a collection of assemblies to AssemblySource. + /// + /// The assemblies to add. + public static void AddRange(IEnumerable assemblies) { + foreach (Assembly assembly in assemblies) { + try { + if (!Instance.Contains(assembly)) { + Instance.Add(assembly); + } + } catch (ArgumentException) { + // ignore + } } } } diff --git a/src/Caliburn.Micro.Platform.Core/AssemblySourceCache.cs b/src/Caliburn.Micro.Platform.Core/AssemblySourceCache.cs new file mode 100644 index 000000000..cd3f88c9f --- /dev/null +++ b/src/Caliburn.Micro.Platform.Core/AssemblySourceCache.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Linq; +using System.Reflection; + +namespace Caliburn.Micro { + /// + /// A caching subsystem for . + /// + public static class AssemblySourceCache { + private static readonly IDictionary TypeNameCache = new Dictionary(); + + private static bool isInstalled; + + /// + /// Gets or sets func to extracts the types from the spezified assembly for storing in the cache. + /// + public static Func> ExtractTypes { get; set; } = assembly => + assembly.ExportedTypes + .Where(t => + typeof(INotifyPropertyChanged).GetTypeInfo().IsAssignableFrom(t.GetTypeInfo())); + + /// + /// Gets or sets func to installs the caching subsystem. + /// + public static System.Action Install { get; set; } + = () => { + if (isInstalled) { + return; + } + + isInstalled = true; + + AssemblySource.Instance.CollectionChanged += (s, e) => { + switch (e.Action) { + case NotifyCollectionChangedAction.Add: + e.NewItems.OfType() + .SelectMany(a => ExtractTypes(a)) + .Apply(AddTypeAssembly); + break; + case NotifyCollectionChangedAction.Remove: + case NotifyCollectionChangedAction.Replace: + case NotifyCollectionChangedAction.Reset: + TypeNameCache.Clear(); + AssemblySource.Instance + .SelectMany(a => ExtractTypes(a)) + .Apply(AddTypeAssembly); + break; + } + }; + + AssemblySource.Instance.Refresh(); + + AssemblySource.FindTypeByNames = names => { + if (names == null) { + return null; + } + + Type type = names.Select(n => TypeNameCache.GetValueOrDefault(n)).FirstOrDefault(t => t != null); + return type; + }; + }; + + private static void AddTypeAssembly(Type type) { + if (!TypeNameCache.ContainsKey(type.FullName)) { + TypeNameCache.Add(type.FullName, type); + } + } + } +} diff --git a/src/Caliburn.Micro.Platform.Core/Caliburn.Micro.Platform.Core.csproj b/src/Caliburn.Micro.Platform.Core/Caliburn.Micro.Platform.Core.csproj index 23ff8eab7..94a48b147 100644 --- a/src/Caliburn.Micro.Platform.Core/Caliburn.Micro.Platform.Core.csproj +++ b/src/Caliburn.Micro.Platform.Core/Caliburn.Micro.Platform.Core.csproj @@ -1,4 +1,4 @@ - + netstandard2.0 @@ -7,9 +7,7 @@ .\..\Caliburn.Micro.snk true - - - + diff --git a/src/Caliburn.Micro.Platform.Core/ExtensionMethods.cs b/src/Caliburn.Micro.Platform.Core/ExtensionMethods.cs index c7b0851c9..e3fae9a19 100644 --- a/src/Caliburn.Micro.Platform.Core/ExtensionMethods.cs +++ b/src/Caliburn.Micro.Platform.Core/ExtensionMethods.cs @@ -1,25 +1,21 @@ using System.Collections.Generic; using System.Reflection; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro { /// /// Generic extension methods used by the framework. /// - public static class ExtensionMethods - { + public static class ExtensionMethods { /// /// Get's the name of the assembly. /// /// The assembly. /// The assembly's name. public static string GetAssemblyName(this Assembly assembly) - { - return assembly.FullName.Remove(assembly.FullName.IndexOf(',')); - } + => assembly.FullName.Remove(assembly.FullName.IndexOf(',')); /// - /// Gets the value for a key. If the key does not exist, return default(TValue); + /// Gets the value for a key. If the key does not exist, return default(TValue). /// /// The type of the keys in the dictionary. /// The type of the values in the dictionary. @@ -27,8 +23,6 @@ public static string GetAssemblyName(this Assembly assembly) /// The key to look up. /// The key value. default(TValue) if this key is not in the dictionary. public static TValue GetValueOrDefault(this IDictionary dictionary, TKey key) - { - return dictionary.TryGetValue(key, out TValue result) ? result : default; - } + => dictionary.TryGetValue(key, out TValue result) ? result : default; } } diff --git a/src/Caliburn.Micro.Platform.Core/NameTransformer.cs b/src/Caliburn.Micro.Platform.Core/NameTransformer.cs index 4a28a9fbe..28ddc863b 100644 --- a/src/Caliburn.Micro.Platform.Core/NameTransformer.cs +++ b/src/Caliburn.Micro.Platform.Core/NameTransformer.cs @@ -3,94 +3,71 @@ using System.Linq; using System.Text.RegularExpressions; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro { /// /// Class for managing the list of rules for doing name transformation. /// - public class NameTransformer : BindableCollection - { - - private const RegexOptions options = RegexOptions.None; - private bool useEagerRuleSelection = true; + public class NameTransformer : BindableCollection { + private const RegexOptions Options = RegexOptions.None; /// - /// Flag to indicate if transformations from all matched rules are returned. Otherwise, transformations from only the first matched rule are returned. + /// Gets or sets a value indicating whether if transformations from all matched rules are returned. Otherwise, transformations from only the first matched rule are returned. /// - public bool UseEagerRuleSelection - { - get { return useEagerRuleSelection; } - set { useEagerRuleSelection = value; } - } + public bool UseEagerRuleSelection { get; set; } = true; /// /// Adds a transform using a single replacement value and a global filter pattern. /// - /// Regular expression pattern for replacing text + /// Regular expression pattern for replacing text. /// The replacement value. - /// Regular expression pattern for global filtering + /// Regular expression pattern for global filtering. public void AddRule(string replacePattern, string replaceValue, string globalFilterPattern = null) - { - AddRule(replacePattern, new[] { replaceValue }, globalFilterPattern); - } + => AddRule(replacePattern, new[] { replaceValue }, globalFilterPattern); /// /// Adds a transform using a list of replacement values and a global filter pattern. /// - /// Regular expression pattern for replacing text - /// The list of replacement values - /// Regular expression pattern for global filtering - public void AddRule(string replacePattern, IEnumerable replaceValueList, string globalFilterPattern = null) - { - Add(new Rule - { - ReplacePattern = replacePattern, - ReplacementValues = replaceValueList, - GlobalFilterPattern = globalFilterPattern - }); - } + /// Regular expression pattern for replacing text. + /// The list of replacement values. + /// Regular expression pattern for global filtering. + public void AddRule(string replacePattern, IEnumerable replaceValueList, string globalFilterPattern = null) => Add(new Rule { + ReplacePattern = replacePattern, + ReplacementValues = replaceValueList, + GlobalFilterPattern = globalFilterPattern, + }); /// /// Gets the list of transformations for a given name. /// - /// The name to transform into the resolved name list + /// The name to transform into the resolved name list. /// The transformed names. - public IEnumerable Transform(string source) - { - return Transform(source, r => r); - } + public IEnumerable Transform(string source) => Transform(source, r => r); /// /// Gets the list of transformations for a given name. /// - /// The name to transform into the resolved name list - /// A function to do a transform on each item in the ReplaceValueList prior to applying the regular expression transform + /// The name to transform into the resolved name list. + /// A function to do a transform on each item in the ReplaceValueList prior to applying the regular expression transform. /// The transformed names. - public IEnumerable Transform(string source, Func getReplaceString) - { + public IEnumerable Transform(string source, Func getReplaceString) { var nameList = new List(); - var rules = this.Reverse(); + IEnumerable rules = this.Reverse(); - foreach (var rule in rules) - { - if (!string.IsNullOrEmpty(rule.GlobalFilterPattern) && !rule.GlobalFilterPatternRegex.IsMatch(source)) - { + foreach (Rule rule in rules) { + if (!string.IsNullOrEmpty(rule.GlobalFilterPattern) && !rule.GlobalFilterPatternRegex.IsMatch(source)) { continue; } - if (!rule.ReplacePatternRegex.IsMatch(source)) - { + if (!rule.ReplacePatternRegex.IsMatch(source)) { continue; } nameList.AddRange( rule.ReplacementValues .Select(getReplaceString) - .Select(repString => rule.ReplacePatternRegex.Replace(source, repString)) - ); + .Select(repString => rule.ReplacePatternRegex.Replace(source, repString))); - if (!useEagerRuleSelection) - { + if (!UseEagerRuleSelection) { break; } } @@ -98,50 +75,39 @@ public IEnumerable Transform(string source, Func getRepl return nameList; } - /// + /// /// A rule that describes a name transform. - /// - public class Rule - { + /// + public class Rule { private Regex replacePatternRegex; private Regex globalFilterPatternRegex; /// - /// Regular expression pattern for global filtering + /// Gets or sets regular expression pattern for global filtering. /// - public string GlobalFilterPattern; + public string GlobalFilterPattern { get; set; } /// - /// Regular expression pattern for replacing text + /// Gets or sets regular expression pattern for replacing text. /// - public string ReplacePattern; + public string ReplacePattern { get; set; } /// - /// The list of replacement values + /// Gets or sets the list of replacement values. /// - public IEnumerable ReplacementValues; + public IEnumerable ReplacementValues { get; set; } /// - /// Regular expression for global filtering + /// Gets regular expression for global filtering. /// public Regex GlobalFilterPatternRegex - { - get - { - return globalFilterPatternRegex ?? (globalFilterPatternRegex = new Regex(GlobalFilterPattern, options)); - } - } + => globalFilterPatternRegex ?? (globalFilterPatternRegex = new Regex(GlobalFilterPattern, Options)); /// - /// Regular expression for replacing text + /// Gets regular expression for replacing text. /// public Regex ReplacePatternRegex - { - get - { - return replacePatternRegex ?? (replacePatternRegex = new Regex(ReplacePattern, options)); - } - } + => replacePatternRegex ?? (replacePatternRegex = new Regex(ReplacePattern, Options)); } } -} \ No newline at end of file +} diff --git a/src/Caliburn.Micro.Platform.Core/RegExHelper.cs b/src/Caliburn.Micro.Platform.Core/RegExHelper.cs index 678e8a34f..b01344cc2 100644 --- a/src/Caliburn.Micro.Platform.Core/RegExHelper.cs +++ b/src/Caliburn.Micro.Platform.Core/RegExHelper.cs @@ -1,71 +1,63 @@ using System; -namespace Caliburn.Micro -{ +namespace Caliburn.Micro { /// - /// Helper class for encoding strings to regular expression patterns + /// Helper class for encoding strings to regular expression patterns. /// - public static class RegExHelper - { + public static class RegExHelper { /// - /// Regular expression pattern for valid name + /// Regular expression pattern for valid name. /// public const string NameRegEx = @"[\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Lo}\p{Nl}_][\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Lo}\p{Nl}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\p{Cf}_]*"; /// - /// Regular expression pattern for subnamespace (including dot) + /// Regular expression pattern for subnamespace (including dot). /// public const string SubNamespaceRegEx = NameRegEx + @"\."; /// - /// Regular expression pattern for namespace or namespace fragment + /// Regular expression pattern for namespace or namespace fragment. /// public const string NamespaceRegEx = "(" + SubNamespaceRegEx + ")*"; /// - /// Creates a named capture group with the specified regular expression + /// Creates a named capture group with the specified regular expression. /// - /// Name of capture group to create - /// Regular expression pattern to capture - /// Regular expression capture group with the specified group name + /// Name of capture group to create. + /// Regular expression pattern to capture. + /// Regular expression capture group with the specified group name. public static string GetCaptureGroup(string groupName, string regEx) - { - return String.Concat(@"(?<", groupName, ">", regEx, ")"); - } + => string.Concat(@"(?<", groupName, ">", regEx, ")"); /// - /// Converts a namespace (including wildcards) to a regular expression string + /// Converts a namespace (including wildcards) to a regular expression string. /// - /// Source namespace to convert to regular expression - /// Namespace converted to a regular expression - public static string NamespaceToRegEx(string srcNamespace) - { - //Need to escape the "." as it's a special character in regular expression syntax - var nsencoded = srcNamespace.Replace(".", @"\."); + /// Source namespace to convert to regular expression. + /// Namespace converted to a regular expression. + public static string NamespaceToRegEx(string srcNamespace) { + // Need to escape the "." as it's a special character in regular expression syntax + string nsencoded = srcNamespace.Replace(".", @"\."); - //Replace "*" wildcard with regular expression syntax + // Replace "*" wildcard with regular expression syntax nsencoded = nsencoded.Replace(@"*\.", NamespaceRegEx); + return nsencoded; } /// - /// Creates a capture group for a valid name regular expression pattern + /// Creates a capture group for a valid name regular expression pattern. /// - /// Name of capture group to create - /// Regular expression capture group with the specified group name + /// Name of capture group to create. + /// Regular expression capture group with the specified group name. public static string GetNameCaptureGroup(string groupName) - { - return GetCaptureGroup(groupName, NameRegEx); - } + => GetCaptureGroup(groupName, NameRegEx); /// - /// Creates a capture group for a namespace regular expression pattern + /// Creates a capture group for a namespace regular expression pattern. /// - /// Name of capture group to create - /// Regular expression capture group with the specified group name + /// Name of capture group to create. + /// Regular expression capture group with the specified group name. public static string GetNamespaceCaptureGroup(string groupName) - { - return GetCaptureGroup(groupName, NamespaceRegEx); - } + => GetCaptureGroup(groupName, NamespaceRegEx); } -} \ No newline at end of file +} diff --git a/src/Caliburn.Micro.Platform.Core/StringSplitter.cs b/src/Caliburn.Micro.Platform.Core/StringSplitter.cs index a9d8f2240..a8f8fb83c 100644 --- a/src/Caliburn.Micro.Platform.Core/StringSplitter.cs +++ b/src/Caliburn.Micro.Platform.Core/StringSplitter.cs @@ -2,50 +2,36 @@ using System.Linq; using System.Text; -namespace Caliburn.Micro -{ - +namespace Caliburn.Micro { /// - /// Helper class when splitting strings + /// Helper class when splitting strings. /// - public static class StringSplitter - { - + public static class StringSplitter { /// - /// Splits a string with a chosen separator. + /// Splits a string with a chosen separator. /// If a substring is contained in [...] it will not be splitted. /// - /// The message to split - /// The separator to use when splitting - /// - public static string[] Split(string message, char separator) - { - //Splits a string using the specified separator, if it is found outside of relevant places - //delimited by [ and ] + /// The message to split. + /// The separator to use when splitting. + public static string[] Split(string message, char separator) { + // Splits a string using the specified separator, if it is found outside of relevant places + // delimited by [ and ] string str; var list = new List(); var builder = new StringBuilder(); int squareBrackets = 0; - foreach (var current in message) - { - //Square brackets are used as delimiters, so only separators outside them count... - if (current == '[') - { + foreach (char current in message) { + // Square brackets are used as delimiters, so only separators outside them count... + if (current == '[') { squareBrackets++; - } - else if (current == ']') - { + } else if (current == ']') { squareBrackets--; - } - else if (current == separator) - { - if (squareBrackets == 0) - { + } else if (current == separator) { + if (squareBrackets == 0) { str = builder.ToString(); - if (!string.IsNullOrEmpty(str)) - { + if (!string.IsNullOrEmpty(str)) { list.Add(builder.ToString().Trim()); } @@ -58,8 +44,7 @@ public static string[] Split(string message, char separator) } str = builder.ToString(); - if (!string.IsNullOrEmpty(str)) - { + if (!string.IsNullOrEmpty(str)) { list.Add(builder.ToString().Trim()); } @@ -69,14 +54,12 @@ public static string[] Split(string message, char separator) } /// - /// Splits a string with , as separator. - /// Does not split within {},[],() + /// Splits a string with , as separator. + /// Does not split within {},[],(). /// - /// The string to split - /// - public static string[] SplitParameters(string parameters) - { - //Splits parameter string taking into account brackets... + /// The string to split. + public static string[] SplitParameters(string parameters) { + // Splits parameter string taking into account brackets... var list = new List(); var builder = new StringBuilder(); @@ -85,22 +68,17 @@ public static string[] SplitParameters(string parameters) int curlyBrackets = 0; int squareBrackets = 0; int roundBrackets = 0; - for (int i = 0; i < parameters.Length; i++) - { - var current = parameters[i]; - - if (current == '"' || current == '\'') - { - if (i == 0 || parameters[i - 1] != '\\') - { + for (int i = 0; i < parameters.Length; i++) { + char current = parameters[i]; + + if (current == '"' || current == '\'') { + if (i == 0 || parameters[i - 1] != '\\') { isInString = !isInString; } } - if (!isInString) - { - switch (current) - { + if (!isInString) { + switch (current) { case '{': curlyBrackets++; break; @@ -120,18 +98,18 @@ public static string[] SplitParameters(string parameters) roundBrackets--; break; default: - if (current == ',' && roundBrackets == 0 && squareBrackets == 0 && curlyBrackets == 0) - { - //The only commas to be considered as parameter separators are outside: - //- Strings - //- Square brackets (to ignore indexers) - //- Parantheses (to ignore method invocations) - //- Curly brackets (to ignore initializers and Bindings) - list.Add(builder.ToString()); - builder.Length = 0; - continue; + if (current != ',' || roundBrackets != 0 || squareBrackets != 0 || curlyBrackets != 0) { + break; } - break; + + // The only commas to be considered as parameter separators are outside: + // - Strings + // - Square brackets (to ignore indexers) + // - Parantheses (to ignore method invocations) + // - Curly brackets (to ignore initializers and Bindings) + list.Add(builder.ToString()); + builder.Length = 0; + continue; } } diff --git a/src/Caliburn.Micro.Platform.Core/TypeMappingConfiguration.cs b/src/Caliburn.Micro.Platform.Core/TypeMappingConfiguration.cs index 58589a56d..7fde0bda3 100644 --- a/src/Caliburn.Micro.Platform.Core/TypeMappingConfiguration.cs +++ b/src/Caliburn.Micro.Platform.Core/TypeMappingConfiguration.cs @@ -1,46 +1,57 @@ -namespace Caliburn.Micro -{ - using System.Collections.Generic; +using System.Collections.Generic; +namespace Caliburn.Micro { /// - /// Class to specify settings for configuring type mappings by the ViewLocator or ViewModelLocator + /// Class to specify settings for configuring type mappings by the ViewLocator or ViewModelLocator. /// - public class TypeMappingConfiguration - { + public class TypeMappingConfiguration { /// - /// The default subnamespace for Views. Used for creating default subnamespace mappings. Defaults to "Views". + /// Initializes a new instance of the class. /// - public string DefaultSubNamespaceForViews { get; set; } = "Views"; + public TypeMappingConfiguration() { + DefaultSubNamespaceForViews = "Views"; + DefaultSubNamespaceForViewModels = "ViewModels"; + UseNameSuffixesInMappings = true; + NameFormat = @"{0}{1}"; + IncludeViewSuffixInViewModelNames = true; + ViewSuffixList = new List(new[] { "View", "Page" }); + ViewModelSuffix = "ViewModel"; + } /// - /// The default subnamespace for ViewModels. Used for creating default subnamespace mappings. Defaults to "ViewModels". + /// Gets or sets the default subnamespace for Views. Used for creating default subnamespace mappings. Defaults to "Views". /// - public string DefaultSubNamespaceForViewModels { get; set; } = "ViewModels"; + public string DefaultSubNamespaceForViews { get; set; } /// - /// Flag to indicate whether or not the name of the Type should be transformed when adding a type mapping. Defaults to true. + /// Gets or sets the default subnamespace for ViewModels. Used for creating default subnamespace mappings. Defaults to "ViewModels". /// - public bool UseNameSuffixesInMappings { get; set; } = true; + public string DefaultSubNamespaceForViewModels { get; set; } /// - /// The format string used to compose the name of a type from base name and name suffix + /// Gets or sets a value indicating whether flag to indicate whether or not the name of the Type should be transformed when adding a type mapping. Defaults to true. /// - public string NameFormat { get; set; } = @"{0}{1}"; + public bool UseNameSuffixesInMappings { get; set; } /// - /// Flag to indicate if ViewModel names should include View suffixes (i.e. CustomerPageViewModel vs. CustomerViewModel) + /// Gets or sets the format string used to compose the name of a type from base name and name suffix. /// - public bool IncludeViewSuffixInViewModelNames { get; set; } = true; + public string NameFormat { get; set; } /// - /// List of View suffixes for which default type mappings should be created. Applies only when UseNameSuffixesInMappings = true. - /// Default values are "View", "Page" + /// Gets or sets a value indicating whether flag to indicate if ViewModel names should include View suffixes (i.e. CustomerPageViewModel vs. CustomerViewModel). /// - public List ViewSuffixList { get; set; } = new List(new[] { "View", "Page" }); + public bool IncludeViewSuffixInViewModelNames { get; set; } /// - /// The name suffix for ViewModels. Applies only when UseNameSuffixesInMappings = true. The default is "ViewModel". + /// Gets or sets list of View suffixes for which default type mappings should be created. Applies only when UseNameSuffixesInMappings = true. + /// Default values are "View", "Page". /// - public string ViewModelSuffix { get; set; } = "ViewModel"; + public List ViewSuffixList { get; set; } + + /// + /// Gets or sets the name suffix for ViewModels. Applies only when UseNameSuffixesInMappings = true. The default is "ViewModel". + /// + public string ViewModelSuffix { get; set; } } -} \ No newline at end of file +} diff --git a/src/Caliburn.Micro.Platform.Tests/AssemblyCacheTests.cs b/src/Caliburn.Micro.Platform.Tests/AssemblyCacheTests.cs index 72fa67271..39b2e9c0f 100644 --- a/src/Caliburn.Micro.Platform.Tests/AssemblyCacheTests.cs +++ b/src/Caliburn.Micro.Platform.Tests/AssemblyCacheTests.cs @@ -1,5 +1,5 @@ using System; -using System.Globalization; + using Xunit; namespace Caliburn.Micro.Platform.Tests @@ -11,11 +11,11 @@ public void AddingTheSameAssemblyMoreThanOneShouldNotThrow() { AssemblySourceCache.Install(); - var testAssembly = typeof(AssemblyCacheTests).Assembly; + System.Reflection.Assembly testAssembly = typeof(AssemblyCacheTests).Assembly; AssemblySource.Instance.Add(testAssembly); - //Re-add the same assembly - var exception = Record.Exception(() => AssemblySource.Instance.Add(testAssembly)); + /* Re-add the same assembly */ + Exception exception = Record.Exception(() => AssemblySource.Instance.Add(testAssembly)); Assert.Null(exception); } @@ -24,17 +24,13 @@ public void ResettingTheCacheWithMoreThanOneAssemblyShouldNotThrow() { AssemblySourceCache.Install(); - var testAssembly = typeof(AssemblyCacheTests).Assembly; + System.Reflection.Assembly testAssembly = typeof(AssemblyCacheTests).Assembly; AssemblySource.Instance.AddRange(new[] { testAssembly, testAssembly }); - //Refresh clears and re-creates the cache - var exception = Record.Exception(() => AssemblySource.Instance.Refresh()); + /* Refresh clears and re-creates the cache */ + Exception exception = Record.Exception(() => AssemblySource.Instance.Refresh()); Assert.Null(exception); } } - - public class TestScreen : Screen - { - } } diff --git a/src/Caliburn.Micro.Platform.Tests/BindingScopeTests.cs b/src/Caliburn.Micro.Platform.Tests/BindingScopeTests.cs deleted file mode 100644 index 433e51e25..000000000 --- a/src/Caliburn.Micro.Platform.Tests/BindingScopeTests.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Windows; -using System.Windows.Controls; -using Xunit; - -namespace Caliburn.Micro.Platform.Tests -{ - public class BindingScopeFindName - { - [WpfFact] - public void A_given_match_is_always_the_first_instance_found() - { - var elements = new List - { - new FrameworkElement - { - Name = "Foo" - }, - new FrameworkElement - { - Name = "Foo" - } - }; - - var found = BindingScope.FindName(elements, "Foo"); - Assert.NotSame(elements.Last(), found); - } - - [WpfFact] - public void A_given_name_is_found_regardless_of_case_sensitivity() - { - var elements = new List - { - new FrameworkElement - { - Name = "FOO" - } - }; - - var found = BindingScope.FindName(elements, "foo"); - Assert.NotNull(found); - } - - [WpfFact] - public void A_given_name_is_matched_correctly() - { - var elements = new List - { - new FrameworkElement - { - Name = "Bar" - }, - new FrameworkElement - { - Name = "Foo" - } - }; - - var found = BindingScope.FindName(elements, "Foo"); - Assert.NotNull(found); - } - } - - public class BindingScope_FindScopeNamingRoute - { - [WpfFact] - public void A_given_Pages_Content_is_ScopeRoute_if_it_is_a_dependency_object() - { - var page = new Page - { - Content = new Control() - }; - var route = BindingScope.FindScopeNamingRoute(page); - - Assert.Same(page.Content, route.Root); - } - - [WpfFact] - public void A_given_UserControl_is_ScopeRoute() - { - var userControl = new UserControl(); - var route = BindingScope.FindScopeNamingRoute(userControl); - - Assert.Same(userControl, route.Root); - } - - [WpfFact] - public void Any_DependencyObject_is_ScopeRoot_if_IsScopeRoot_is_true() - { - var dependencyObject = new DependencyObject(); - dependencyObject.SetValue(View.IsScopeRootProperty, true); - var route = BindingScope.FindScopeNamingRoute(dependencyObject); - - Assert.Same(dependencyObject, route.Root); - } - } -} diff --git a/src/Caliburn.Micro.Platform.Tests/BindingScope_FindName_Tests.cs b/src/Caliburn.Micro.Platform.Tests/BindingScope_FindName_Tests.cs new file mode 100644 index 000000000..81f6e8bc9 --- /dev/null +++ b/src/Caliburn.Micro.Platform.Tests/BindingScope_FindName_Tests.cs @@ -0,0 +1,64 @@ +using System.Collections.Generic; +using System.Linq; +using System.Windows; + +using Xunit; + +namespace Caliburn.Micro.Platform.Tests +{ + public class BindingScope_FindName_Tests + { + [WpfFact] + public void A_given_match_is_always_the_first_instance_found() + { + var elements = new List + { + new FrameworkElement + { + Name = "Foo", + }, + new FrameworkElement + { + Name = "Foo", + }, + }; + + FrameworkElement found = BindingScope.FindName(elements, "Foo"); + Assert.NotSame(elements.Last(), found); + } + + [WpfFact] + public void A_given_name_is_found_regardless_of_case_sensitivity() + { + var elements = new List + { + new FrameworkElement + { + Name = "FOO", + }, + }; + + FrameworkElement found = BindingScope.FindName(elements, "foo"); + Assert.NotNull(found); + } + + [WpfFact] + public void A_given_name_is_matched_correctly() + { + var elements = new List + { + new FrameworkElement + { + Name = "Bar", + }, + new FrameworkElement + { + Name = "Foo", + }, + }; + + FrameworkElement found = BindingScope.FindName(elements, "Foo"); + Assert.NotNull(found); + } + } +} diff --git a/src/Caliburn.Micro.Platform.Tests/BindingScope_FindScopeNamingRoute_Tests.cs b/src/Caliburn.Micro.Platform.Tests/BindingScope_FindScopeNamingRoute_Tests.cs new file mode 100644 index 000000000..63af90951 --- /dev/null +++ b/src/Caliburn.Micro.Platform.Tests/BindingScope_FindScopeNamingRoute_Tests.cs @@ -0,0 +1,35 @@ +using System.Windows; +using System.Windows.Controls; + +using Xunit; + +namespace Caliburn.Micro.Platform.Tests { + public class BindingScope_FindScopeNamingRoute_Tests { + [WpfFact] + public void A_given_Pages_Content_is_ScopeRoute_if_it_is_a_dependency_object() { + var page = new Page { + Content = new Control(), + }; + BindingScope.ScopeNamingRoute route = BindingScope.FindScopeNamingRoute(page); + + Assert.Same(page.Content, route.Root); + } + + [WpfFact] + public void A_given_UserControl_is_ScopeRoute() { + var userControl = new UserControl(); + BindingScope.ScopeNamingRoute route = BindingScope.FindScopeNamingRoute(userControl); + + Assert.Same(userControl, route.Root); + } + + [WpfFact] + public void Any_DependencyObject_is_ScopeRoot_if_IsScopeRoot_is_true() { + var dependencyObject = new DependencyObject(); + dependencyObject.SetValue(View.IsScopeRootProperty, true); + BindingScope.ScopeNamingRoute route = BindingScope.FindScopeNamingRoute(dependencyObject); + + Assert.Same(dependencyObject, route.Root); + } + } +} diff --git a/src/Caliburn.Micro.Platform.Tests/Caliburn.Micro.Platform.Tests.csproj b/src/Caliburn.Micro.Platform.Tests/Caliburn.Micro.Platform.Tests.csproj index 04ad2ae69..982f37874 100644 --- a/src/Caliburn.Micro.Platform.Tests/Caliburn.Micro.Platform.Tests.csproj +++ b/src/Caliburn.Micro.Platform.Tests/Caliburn.Micro.Platform.Tests.csproj @@ -1,13 +1,20 @@  + + net462 false + $(NoWarn);CA1707;SA0001 + all @@ -17,20 +24,16 @@ - - - - - - - + - + + + \ No newline at end of file diff --git a/src/Caliburn.Micro.Platform.Tests/MessageBinderTests.cs b/src/Caliburn.Micro.Platform.Tests/MessageBinderTests.cs index 2337e473c..cf70c2fea 100644 --- a/src/Caliburn.Micro.Platform.Tests/MessageBinderTests.cs +++ b/src/Caliburn.Micro.Platform.Tests/MessageBinderTests.cs @@ -8,11 +8,11 @@ public class MessageBinderTests public void EvaluateParameterCaseInsensitive() { MessageBinder.SpecialValues.Add("$sampleParameter", context => 42); - var caseSensitiveValue = MessageBinder.EvaluateParameter("$sampleParameter", typeof(int), new ActionExecutionContext()); + object caseSensitiveValue = MessageBinder.EvaluateParameter("$sampleParameter", typeof(int), new ActionExecutionContext()); Assert.NotEqual("$sampleParameter", caseSensitiveValue); - var caseInsensitiveValue = MessageBinder.EvaluateParameter("$sampleparameter", typeof(int), new ActionExecutionContext()); + object caseInsensitiveValue = MessageBinder.EvaluateParameter("$sampleparameter", typeof(int), new ActionExecutionContext()); Assert.NotEqual("$sampleparameter", caseInsensitiveValue); } } diff --git a/src/Caliburn.Micro.Platform.Tests/ParserTests.cs b/src/Caliburn.Micro.Platform.Tests/ParserTests.cs index f20324a76..e046c2dc1 100644 --- a/src/Caliburn.Micro.Platform.Tests/ParserTests.cs +++ b/src/Caliburn.Micro.Platform.Tests/ParserTests.cs @@ -1,9 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Globalization; + using Xunit; namespace Caliburn.Micro.Platform.Tests @@ -13,9 +9,9 @@ public class ParserTests [Fact] public void CreateParametersWithOddNumbers() { - var evenResult = Parser.CreateParameter(null, "0.1"); - var oddResult = Parser.CreateParameter(null, "-0.1"); - var nanResult = Parser.CreateParameter(null, "-0.1abc"); + Parameter evenResult = Parser.CreateParameter(null, "0.1"); + Parameter oddResult = Parser.CreateParameter(null, "-0.1"); + Parameter nanResult = Parser.CreateParameter(null, "-0.1abc"); Assert.Equal(0.1, double.Parse((string)evenResult.Value, CultureInfo.InvariantCulture)); Assert.Equal(-0.1, double.Parse((string)oddResult.Value, CultureInfo.InvariantCulture)); diff --git a/src/Caliburn.Micro.Platform.Tests/ScopeNamingRouteTests.cs b/src/Caliburn.Micro.Platform.Tests/ScopeNamingRouteTests.cs index 1403eed06..ca588ab12 100644 --- a/src/Caliburn.Micro.Platform.Tests/ScopeNamingRouteTests.cs +++ b/src/Caliburn.Micro.Platform.Tests/ScopeNamingRouteTests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Windows; + using Xunit; namespace Caliburn.Micro.Platform.Tests @@ -16,7 +17,7 @@ public void CannotAddDisjointHops() var d3 = new DependencyObject(); var d4 = new DependencyObject(); - // d1 -> d2 and d3 -> d4, but d2 doesn't lead to d3, so d3 -> d4 is rejected + /* d1 -> d2 and d3 -> d4, but d2 doesn't lead to d3, so d3 -> d4 is rejected */ route.AddHop(d1, d2); Assert.Throws(() => route.AddHop(d3, d4)); } @@ -29,7 +30,7 @@ public void CorrectlyGetsAddedHop() var d2 = new DependencyObject(); route.AddHop(d1, d2); DependencyObject target; - var result = route.TryGetHop(d1, out target); + bool result = route.TryGetHop(d1, out target); Assert.True(result); Assert.Same(d2, target); } @@ -51,10 +52,10 @@ public void GetsAllHopsAdded() { d2, d3, - d4 + d4, }; - var source = d1; + DependencyObject source = d1; DependencyObject target; while (route.TryGetHop(source, out target)) diff --git a/src/Caliburn.Micro.Platform.Tests/StringSplitterTests.cs b/src/Caliburn.Micro.Platform.Tests/StringSplitterTests.cs index 21ce578fa..cd902b815 100644 --- a/src/Caliburn.Micro.Platform.Tests/StringSplitterTests.cs +++ b/src/Caliburn.Micro.Platform.Tests/StringSplitterTests.cs @@ -1,54 +1,52 @@ using Xunit; -namespace Caliburn.Micro.Platform.Tests -{ - public class StringSplitterTests - { +namespace Caliburn.Micro.Platform.Tests { + public class StringSplitterTests { [Fact] - public void SplitSimpleString() - { - var output = StringSplitter.Split("MyMethodName", ';'); + public void SplitSimpleString() { + string[] output = StringSplitter.Split("MyMethodName", ';'); Assert.Collection(output, o => Assert.Equal("MyMethodName", o)); } [Fact] - public void SplitSeparatedString() - { - var output = StringSplitter.Split("First;Second", ';'); + public void SplitSeparatedString() { + string[] output = StringSplitter.Split("First;Second", ';'); - Assert.Collection(output, + Assert.Collection( + output, o => Assert.Equal("First", o), o => Assert.Equal("Second", o)); } [Fact] - public void TrimsSplitSimpleString() - { - var output = StringSplitter.Split("MyMethodName ", ';'); + public void TrimsSplitSimpleString() { + string[] output = StringSplitter.Split("MyMethodName ", ';'); Assert.Collection(output, o => Assert.Equal("MyMethodName", o)); } [Fact] - public void RemovesEmptySplitsSeparatedString() - { - var output = StringSplitter.Split("First;Second;", ';'); + public void RemovesEmptySplitsSeparatedString() { + string[] output = StringSplitter.Split("First;Second;", ';'); - Assert.Collection(output, + Assert.Collection( + output, o => Assert.Equal("First", o), o => Assert.Equal("Second", o)); } [Fact] - public void HandlesNewLinesInSeparatedString() - { - var output = StringSplitter.Split(@" + public void HandlesNewLinesInSeparatedString() { + string[] output = StringSplitter.Split( + @" First; Second; - ", ';'); + ", + ';'); - Assert.Collection(output, + Assert.Collection( + output, o => Assert.Equal("First", o), o => Assert.Equal("Second", o)); } diff --git a/src/Caliburn.Micro.Platform.Tests/ViewLocatorTests.cs b/src/Caliburn.Micro.Platform.Tests/ViewLocatorTests.cs index f2f4de0ef..09bb65abd 100644 --- a/src/Caliburn.Micro.Platform.Tests/ViewLocatorTests.cs +++ b/src/Caliburn.Micro.Platform.Tests/ViewLocatorTests.cs @@ -1,4 +1,5 @@ using System; + using Xunit; namespace Caliburn.Micro.Platform.Tests @@ -12,7 +13,7 @@ public void ConfigureTypeMappingsShouldThrowWhenDefaultSubNamespaceForViewModels { DefaultSubNamespaceForViews = "not empty", DefaultSubNamespaceForViewModels = string.Empty, - NameFormat = "not Empty" + NameFormat = "not Empty", }; Assert.Throws(() => ViewLocator.ConfigureTypeMappings(config)); @@ -25,7 +26,7 @@ public void ConfigureTypeMappingsShouldThrowWhenDefaultSubNamespaceForViewModels { DefaultSubNamespaceForViews = "not null", DefaultSubNamespaceForViewModels = null, - NameFormat = "not null" + NameFormat = "not null", }; Assert.Throws(() => ViewLocator.ConfigureTypeMappings(config)); @@ -38,7 +39,7 @@ public void ConfigureTypeMappingsShouldThrowWhenDefaultSubNamespaceForViewsIsEmp { DefaultSubNamespaceForViews = string.Empty, DefaultSubNamespaceForViewModels = "not Empty", - NameFormat = "not Empty" + NameFormat = "not Empty", }; Assert.Throws(() => ViewLocator.ConfigureTypeMappings(config)); @@ -51,7 +52,7 @@ public void ConfigureTypeMappingsShouldThrowWhenDefaultSubNamespaceForViewsIsNul { DefaultSubNamespaceForViews = null, DefaultSubNamespaceForViewModels = "not null", - NameFormat = "not null" + NameFormat = "not null", }; Assert.Throws(() => ViewLocator.ConfigureTypeMappings(config)); @@ -64,7 +65,7 @@ public void ConfigureTypeMappingsShouldThrowWhenNameFormatIsEmpty() { DefaultSubNamespaceForViews = "not Empty", DefaultSubNamespaceForViewModels = "not Empty", - NameFormat = string.Empty + NameFormat = string.Empty, }; Assert.Throws(() => ViewLocator.ConfigureTypeMappings(config)); @@ -77,7 +78,7 @@ public void ConfigureTypeMappingsShouldThrowWhenNameFormatIsNull() { DefaultSubNamespaceForViews = "not null", DefaultSubNamespaceForViewModels = "not null", - NameFormat = null + NameFormat = null, }; Assert.Throws(() => ViewLocator.ConfigureTypeMappings(config)); diff --git a/src/Caliburn.Micro.Platform.Tests/ViewModelLocatorTests.cs b/src/Caliburn.Micro.Platform.Tests/ViewModelLocatorTests.cs index abb890884..217d87ec0 100644 --- a/src/Caliburn.Micro.Platform.Tests/ViewModelLocatorTests.cs +++ b/src/Caliburn.Micro.Platform.Tests/ViewModelLocatorTests.cs @@ -1,91 +1,77 @@ using System; + using Xunit; -namespace Caliburn.Micro.Platform.Tests -{ - public class ViewModelLocatorTests - { +namespace Caliburn.Micro.Platform.Tests { + public class ViewModelLocatorTests { [Fact] - public void ConfigureTypeMappingsShouldThrowWhenDefaultSubNamespaceForViewModelsIsEmpty() - { - var config = new TypeMappingConfiguration - { + public void ConfigureTypeMappingsShouldThrowWhenDefaultSubNamespaceForViewModelsIsEmpty() { + var config = new TypeMappingConfiguration { DefaultSubNamespaceForViews = "not empty", DefaultSubNamespaceForViewModels = string.Empty, - NameFormat = "not Empty" + NameFormat = "not Empty", }; Assert.Throws(() => ViewModelLocator.ConfigureTypeMappings(config)); } [Fact] - public void ConfigureTypeMappingsShouldThrowWhenDefaultSubNamespaceForViewModelsIsNull() - { - var config = new TypeMappingConfiguration - { + public void ConfigureTypeMappingsShouldThrowWhenDefaultSubNamespaceForViewModelsIsNull() { + var config = new TypeMappingConfiguration { DefaultSubNamespaceForViews = "not null", DefaultSubNamespaceForViewModels = null, - NameFormat = "not null" + NameFormat = "not null", }; Assert.Throws(() => ViewModelLocator.ConfigureTypeMappings(config)); } [Fact] - public void ConfigureTypeMappingsShouldThrowWhenDefaultSubNamespaceForViewsIsEmpty() - { - var config = new TypeMappingConfiguration - { + public void ConfigureTypeMappingsShouldThrowWhenDefaultSubNamespaceForViewsIsEmpty() { + var config = new TypeMappingConfiguration { DefaultSubNamespaceForViews = string.Empty, DefaultSubNamespaceForViewModels = "not Empty", - NameFormat = "not Empty" + NameFormat = "not Empty", }; Assert.Throws(() => ViewModelLocator.ConfigureTypeMappings(config)); } [Fact] - public void ConfigureTypeMappingsShouldThrowWhenDefaultSubNamespaceForViewsIsNull() - { - var config = new TypeMappingConfiguration - { + public void ConfigureTypeMappingsShouldThrowWhenDefaultSubNamespaceForViewsIsNull() { + var config = new TypeMappingConfiguration { DefaultSubNamespaceForViews = null, DefaultSubNamespaceForViewModels = "not null", - NameFormat = "not null" + NameFormat = "not null", }; Assert.Throws(() => ViewModelLocator.ConfigureTypeMappings(config)); } [Fact] - public void ConfigureTypeMappingsShouldThrowWhenNameFormatIsEmpty() - { - var config = new TypeMappingConfiguration - { + public void ConfigureTypeMappingsShouldThrowWhenNameFormatIsEmpty() { + var config = new TypeMappingConfiguration { DefaultSubNamespaceForViews = "not Empty", DefaultSubNamespaceForViewModels = "not Empty", - NameFormat = string.Empty + NameFormat = string.Empty, }; Assert.Throws(() => ViewModelLocator.ConfigureTypeMappings(config)); } [Fact] - public void ConfigureTypeMappingsShouldThrowWhenNameFormatIsNull() - { - var config = new TypeMappingConfiguration - { + public void ConfigureTypeMappingsShouldThrowWhenNameFormatIsNull() { + var config = new TypeMappingConfiguration { DefaultSubNamespaceForViews = "not null", DefaultSubNamespaceForViewModels = "not null", - NameFormat = null + NameFormat = null, }; Assert.Throws(() => ViewModelLocator.ConfigureTypeMappings(config)); } [Fact] - public void COnfigureTypeMappingsWithDefaultValuesShouldNotThrow() - { + public void COnfigureTypeMappingsWithDefaultValuesShouldNotThrow() { var typeMappingConfiguration = new TypeMappingConfiguration(); ViewModelLocator.ConfigureTypeMappings(typeMappingConfiguration); diff --git a/src/Caliburn.Micro.Platform/Action.cs b/src/Caliburn.Micro.Platform/Action.cs index a1dffe372..290ff3400 100644 --- a/src/Caliburn.Micro.Platform/Action.cs +++ b/src/Caliburn.Micro.Platform/Action.cs @@ -1,4 +1,22 @@ -#if XFORMS +#if WINDOWS_UWP +using System.Linq; +using System.Reflection; + +using Windows.UI.Xaml; +#elif XFORMS +using DependencyObject = Xamarin.Forms.BindableObject; +using DependencyProperty = Xamarin.Forms.BindableProperty; +using FrameworkElement = Xamarin.Forms.VisualElement; +using UIElement = Xamarin.Forms.Element; +#elif MAUI +using DependencyObject = Microsoft.Maui.Controls.BindableObject; +using DependencyProperty = Microsoft.Maui.Controls.BindableProperty; +using FrameworkElement = Microsoft.Maui.Controls.VisualElement; +#else +using System.Windows; +#endif + +#if XFORMS namespace Caliburn.Micro.Xamarin.Forms #elif MAUI namespace Caliburn.Micro.Maui @@ -6,30 +24,10 @@ namespace Caliburn.Micro.Maui namespace Caliburn.Micro #endif { -#if WINDOWS_UWP - using System.Linq; - using Windows.UI.Xaml; - using System.Reflection; -#elif XFORMS - using UIElement = global::Xamarin.Forms.Element; - using FrameworkElement = global::Xamarin.Forms.VisualElement; - using DependencyProperty = global::Xamarin.Forms.BindableProperty; - using DependencyObject = global::Xamarin.Forms.BindableObject; -#elif MAUI - using UIElement = global::Microsoft.Maui.Controls.Element; - using FrameworkElement = global::Microsoft.Maui.Controls.VisualElement; - using DependencyProperty = global::Microsoft.Maui.Controls.BindableProperty; - using DependencyObject = global::Microsoft.Maui.Controls.BindableObject; -#else - using System.Windows; -#endif - /// /// A host for action related attached properties. /// public static class Action { - static readonly ILog Log = LogManager.GetLog(typeof(Action)); - /// /// A property definition representing the target of an . The DataContext of the element will be set to this instance. /// @@ -38,9 +36,8 @@ public static class Action { "Target", typeof(object), typeof(Action), - null, - OnTargetChanged - ); + null, + OnTargetChanged); /// /// A property definition representing the target of an . The DataContext of the element is not set to this instance. @@ -50,27 +47,26 @@ public static class Action { "TargetWithoutContext", typeof(object), typeof(Action), - null, - OnTargetWithoutContextChanged - ); + null, + OnTargetWithoutContextChanged); + + private static readonly ILog Log = LogManager.GetLog(typeof(Action)); /// /// Sets the target of the . /// /// The element to attach the target to. /// The target for instances of . - public static void SetTarget(DependencyObject d, object target) { - d.SetValue(TargetProperty, target); - } + public static void SetTarget(DependencyObject d, object target) + => d.SetValue(TargetProperty, target); /// /// Gets the target for instances of . /// /// The element to which the target is attached. - /// The target for instances of - public static object GetTarget(DependencyObject d) { - return d.GetValue(TargetProperty); - } + /// The target for instances of . + public static object GetTarget(DependencyObject d) + => d.GetValue(TargetProperty); /// /// Sets the target of the . @@ -80,53 +76,47 @@ public static object GetTarget(DependencyObject d) { /// /// The DataContext will not be set. /// - public static void SetTargetWithoutContext(DependencyObject d, object target) { - d.SetValue(TargetWithoutContextProperty, target); - } + public static void SetTargetWithoutContext(DependencyObject d, object target) + => d.SetValue(TargetWithoutContextProperty, target); /// /// Gets the target for instances of . /// /// The element to which the target is attached. - /// The target for instances of - public static object GetTargetWithoutContext(DependencyObject d) { - return d.GetValue(TargetWithoutContextProperty); - } + /// The target for instances of . + public static object GetTargetWithoutContext(DependencyObject d) + => d.GetValue(TargetWithoutContextProperty); - /// + /// /// Checks if the -Target was set. - /// - /// DependencyObject to check - /// True if Target or TargetWithoutContext was set on + /// + /// DependencyObject to check. + /// True if Target or TargetWithoutContext was set on . public static bool HasTargetSet(DependencyObject element) { - if (GetTarget(element) != null || GetTargetWithoutContext(element) != null) + if (GetTarget(element) != null || GetTargetWithoutContext(element) != null) { return true; + } #if XFORMS return false; #else - var frameworkElement = element as FrameworkElement; - if (frameworkElement == null) - return false; - - return ConventionManager.HasBinding(frameworkElement, TargetProperty) - || ConventionManager.HasBinding(frameworkElement, TargetWithoutContextProperty); + return element is FrameworkElement frameworkElement && + (ConventionManager.HasBinding(frameworkElement, TargetProperty) || + ConventionManager.HasBinding(frameworkElement, TargetWithoutContextProperty)); #endif } #if !XFORMS - /// + /// /// Uses the action pipeline to invoke the method. - /// - /// The object instance to invoke the method on. - /// The name of the method to invoke. - /// The view. - /// The source of the invocation. - /// The event args. - /// The method parameters. + /// + /// The object instance to invoke the method on. + /// The name of the method to invoke. + /// The view. + /// The source of the invocation. + /// The event args. + /// The method parameters. public static void Invoke(object target, string methodName, DependencyObject view = null, FrameworkElement source = null, object eventArgs = null, object[] parameters = null) { - - var message = new ActionMessage {MethodName = methodName}; - + var message = new ActionMessage { MethodName = methodName }; var context = new ActionExecutionContext { Target = target, #if WINDOWS_UWP @@ -137,12 +127,10 @@ public static void Invoke(object target, string methodName, DependencyObject vie Message = message, View = view, Source = source, - EventArgs = eventArgs + EventArgs = eventArgs, }; - if (parameters != null) { - parameters.Apply(x => context.Message.Parameters.Add(x as Parameter ?? new Parameter { Value = x })); - } + parameters?.Apply(x => context.Message.Parameters.Add(x as Parameter ?? new Parameter { Value = x })); ActionMessage.InvokeAction(context); @@ -151,38 +139,33 @@ public static void Invoke(object target, string methodName, DependencyObject vie } #endif - static void OnTargetWithoutContextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - SetTargetCore(e, d, false); - } + private static void OnTargetWithoutContextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => SetTargetCore(e, d, false); - static void OnTargetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - SetTargetCore(e, d, true); - } + private static void OnTargetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => SetTargetCore(e, d, true); - static void SetTargetCore(DependencyPropertyChangedEventArgs e, DependencyObject d, bool setContext) { + private static void SetTargetCore(DependencyPropertyChangedEventArgs e, DependencyObject d, bool setContext) { if (e.NewValue == e.OldValue || (Execute.InDesignMode && e.NewValue is string)) { return; } - var target = e.NewValue; + object target = e.NewValue; #if XFORMS || MAUI Log.Info("Attaching message handler {0} to {1}.", target, d); Message.SetHandler(d, target); - if (setContext && d is FrameworkElement) { + if (setContext && d is FrameworkElement element) { Log.Info("Setting DC of {0} to {1}.", d, target); - ((FrameworkElement)d).BindingContext = target; + element.BindingContext = target; } #else - if (setContext && d is FrameworkElement) { + if (setContext && d is FrameworkElement element) { Log.Info("Setting DC of {0} to {1}.", d, target); - ((FrameworkElement)d).DataContext = target; + element.DataContext = target; } - Log.Info("Attaching message handler {0} to {1}.", target, d); - Message.SetHandler(d, target); + Log.Info("Attaching message handler {0} to {1}.", target, d); + Message.SetHandler(d, target); #endif - } } diff --git a/src/Caliburn.Micro.Platform/ActionExecutionContext.cs b/src/Caliburn.Micro.Platform/ActionExecutionContext.cs index 895791432..a47e7d7d9 100644 --- a/src/Caliburn.Micro.Platform/ActionExecutionContext.cs +++ b/src/Caliburn.Micro.Platform/ActionExecutionContext.cs @@ -1,4 +1,23 @@ -#if XFORMS +using System; +using System.Collections.Generic; +using System.Reflection; + +#if WINDOWS_UWP +using Windows.UI.Xaml; +#elif XFORMS +using Xamarin.Forms; + +using DependencyObject = Xamarin.Forms.BindableObject; +using DependencyProperty = Xamarin.Forms.BindableProperty; +using FrameworkElement = Xamarin.Forms.VisualElement; +#elif MAUI +using DependencyObject = Microsoft.Maui.Controls.BindableObject; +using FrameworkElement = Microsoft.Maui.Controls.VisualElement; +#else +using System.Windows; +#endif + +#if XFORMS namespace Caliburn.Micro.Xamarin.Forms #elif MAUI namespace Caliburn.Micro.Maui @@ -6,25 +25,6 @@ namespace Caliburn.Micro.Maui namespace Caliburn.Micro #endif { - using System; - using System.Collections.Generic; - using System.Reflection; -#if WINDOWS_UWP - using Windows.UI.Xaml; -#elif XFORMS - using global::Xamarin.Forms; - using DependencyObject = global::Xamarin.Forms.BindableObject; - using DependencyProperty = global::Xamarin.Forms.BindableProperty; - using FrameworkElement = global::Xamarin.Forms.VisualElement; -#elif MAUI - using global::Microsoft.Maui; - using DependencyObject = global::Microsoft.Maui.Controls.BindableObject; - using DependencyProperty = global::Microsoft.Maui.Controls.BindableProperty; - using FrameworkElement = global::Microsoft.Maui.Controls.VisualElement; -#else - using System.Windows; -#endif - /// /// The context used during the execution of an Action or its guard. /// @@ -34,53 +34,59 @@ public class ActionExecutionContext : IDisposable { private WeakReference target; private WeakReference view; private Dictionary values; + private bool _isDisposed; /// - /// Determines whether the action can execute. + /// Called when the execution context is disposed + /// + public event EventHandler Disposing = (sender, e) => { }; + + /// + /// Gets or sets func to determines whether the action can execute. /// /// Returns true if the action can execute, false otherwise. - public Func CanExecute; + public Func CanExecute { get; set; } /// - /// Any event arguments associated with the action's invocation. + /// Gets or sets any event arguments associated with the action's invocation. /// - public object EventArgs; + public object EventArgs { get; set; } /// - /// The actual method info to be invoked. + /// Gets or sets the actual method info to be invoked. /// - public MethodInfo Method; + public MethodInfo Method { get; set; } /// - /// The message being executed. + /// Gets or sets the message being executed. /// public ActionMessage Message { - get { return message == null ? null : message.Target as ActionMessage; } - set { message = new WeakReference(value); } + get => message == null ? null : message.Target as ActionMessage; + set => message = new WeakReference(value); } /// - /// The source from which the message originates. + /// Gets or sets the source from which the message originates. /// public FrameworkElement Source { - get { return source == null ? null : source.Target as FrameworkElement; } - set { source = new WeakReference(value); } + get => source == null ? null : source.Target as FrameworkElement; + set => source = new WeakReference(value); } /// - /// The instance on which the action is invoked. + /// Gets or sets the instance on which the action is invoked. /// public object Target { - get { return target == null ? null : target.Target; } - set { target = new WeakReference(value); } + get => target?.Target; + set => target = new WeakReference(value); } /// - /// The view associated with the target. + /// Gets or sets the view associated with the target. /// public DependencyObject View { - get { return view == null ? null : view.Target as DependencyObject; } - set { view = new WeakReference(value); } + get => view == null ? null : view.Target as DependencyObject; + set => view = new WeakReference(value); } /// @@ -90,17 +96,19 @@ public DependencyObject View { /// Custom data associated with the context. public object this[string key] { get { - if (values == null) + if (values == null) { values = new Dictionary(); + } - object result; - values.TryGetValue(key, out result); + values.TryGetValue(key, out object result); return result; } + set { - if (values == null) + if (values == null) { values = new Dictionary(); + } values[key] = value; } @@ -110,12 +118,30 @@ public object this[string key] { /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { - Disposing(this, System.EventArgs.Empty); + Dispose(disposing: true); + GC.SuppressFinalize(this); } /// - /// Called when the execution context is disposed + /// Perform Dispose. /// - public event EventHandler Disposing = delegate { }; + /// Dispose managed resources. + protected virtual void Dispose(bool disposing) { + if (_isDisposed) { + return; + } + + if (disposing) { + Disposing(this, System.EventArgs.Empty); + } + + message = null; + source = null; + target = null; + view = null; + values = null; + + _isDisposed = true; + } } } diff --git a/src/Caliburn.Micro.Platform/ActionMessage.cs b/src/Caliburn.Micro.Platform/ActionMessage.cs index faaa9cc87..9d08987fb 100644 --- a/src/Caliburn.Micro.Platform/ActionMessage.cs +++ b/src/Caliburn.Micro.Platform/ActionMessage.cs @@ -1,29 +1,33 @@ -namespace Caliburn.Micro -{ - using System; - using System.Collections.Generic; - using System.ComponentModel; - using System.Linq; - using System.Reflection; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.Linq; +using System.Reflection; + #if WINDOWS_UWP - using Windows.UI.Xaml; - using Windows.UI.Xaml.Data; - using Windows.UI.Xaml.Markup; - using Windows.UI.Xaml.Media; - using Windows.UI.Xaml.Controls; - using Microsoft.Xaml.Interactivity; - using TriggerBase = Microsoft.Xaml.Interactivity.IBehavior; - using EventTrigger = Microsoft.Xaml.Interactions.Core.EventTriggerBehavior; +using Microsoft.Xaml.Interactivity; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Markup; +using Windows.UI.Xaml.Media; + +using EventTrigger = Microsoft.Xaml.Interactions.Core.EventTriggerBehavior; +using TriggerBase = Microsoft.Xaml.Interactivity.IBehavior; + #else - using System.Windows; - using System.Windows.Controls.Primitives; - using System.Windows.Data; - using System.Windows.Markup; - using Microsoft.Xaml.Behaviors; - using EventTrigger = Microsoft.Xaml.Behaviors.EventTrigger; -#endif +using System.Windows; +using System.Windows.Controls.Primitives; +using System.Windows.Data; +using System.Windows.Markup; + +using Microsoft.Xaml.Behaviors; +using EventTrigger = Microsoft.Xaml.Behaviors.EventTrigger; +#endif +namespace Caliburn.Micro { /// /// Used to send a message from the UI to a presentation model class, indicating that a particular Action should be invoked. /// @@ -36,516 +40,543 @@ [TypeConstraint(typeof(FrameworkElement))] #endif public class ActionMessage : TriggerAction, IHaveParameters { - static readonly ILog Log = LogManager.GetLog(typeof(ActionMessage)); - ActionExecutionContext context; - - internal static readonly DependencyProperty HandlerProperty = DependencyProperty.RegisterAttached( - "Handler", - typeof(object), - typeof(ActionMessage), - new PropertyMetadata(null, HandlerPropertyChanged) - ); - - /// - /// Causes the action invocation to "double check" if the action should be invoked by executing the guard immediately before hand. - /// - /// This is disabled by default. If multiple actions are attached to the same element, you may want to enable this so that each individaul action checks its guard regardless of how the UI state appears. - public static bool EnforceGuardsDuringInvocation = false; - - /// - /// Causes the action to throw if it cannot locate the target or the method at invocation time. - /// - /// True by default. - public static bool ThrowsExceptions = true; - /// /// Represents the method name of an action message. /// - public static readonly DependencyProperty MethodNameProperty = - DependencyProperty.Register( + public static readonly DependencyProperty MethodNameProperty + = DependencyProperty.Register( "MethodName", typeof(string), typeof(ActionMessage), - null - ); + null); /// /// Represents the parameters of an action message. /// - public static readonly DependencyProperty ParametersProperty = - DependencyProperty.Register( - "Parameters", - typeof(AttachedCollection), - typeof(ActionMessage), - null - ); + public static readonly DependencyProperty ParametersProperty + = DependencyProperty.Register( + "Parameters", + typeof(AttachedCollection), + typeof(ActionMessage), + null); + + internal static readonly DependencyProperty HandlerProperty + = DependencyProperty.RegisterAttached( + "Handler", + typeof(object), + typeof(ActionMessage), + new PropertyMetadata(null, HandlerPropertyChanged)); + + private static readonly ILog Log = LogManager.GetLog(typeof(ActionMessage)); + + private ActionExecutionContext context; /// - /// Creates an instance of . + /// Initializes a new instance of the class. /// - public ActionMessage() { - SetValue(ParametersProperty, new AttachedCollection()); - } + public ActionMessage() + => SetValue(ParametersProperty, new AttachedCollection()); /// - /// Gets or sets the name of the method to be invoked on the presentation model class. + /// Occurs before the message detaches from the associated object. /// - /// The name of the method. -#if !WINDOWS_UWP - [Category("Common Properties")] -#endif - public string MethodName { - get { return (string)GetValue(MethodNameProperty); } - set { SetValue(MethodNameProperty, value); } - } + public event EventHandler Detaching + = (sender, e) => { }; /// - /// Gets the parameters to pass as part of the method invocation. + /// Gets or sets a value indicating whether the action invocation to "double check" if the action should be invoked by executing the guard immediately before hand. /// - /// The parameters. -#if !WINDOWS_UWP - [Category("Common Properties")] -#endif - public AttachedCollection Parameters { - get { return (AttachedCollection)GetValue(ParametersProperty); } - } + /// This is disabled by default. If multiple actions are attached to the same element, you may want to enable this so that each individaul action checks its guard regardless of how the UI state appears. + public static bool EnforceGuardsDuringInvocation { get; set; } /// - /// Occurs before the message detaches from the associated object. + /// Gets or sets a value indicating whether the action throw if it cannot locate the target or the method at invocation time. /// - public event EventHandler Detaching = delegate { }; + /// True by default. + public static bool ThrowsExceptions { get; set; } + = true; /// - /// Called after the action is attached to an AssociatedObject. + /// Gets or sets func to return the list of possible names of guard methods / properties for the given method. /// -#if WINDOWS_UWP - protected override void OnAttached() { - if (!View.InDesignMode) { - Parameters.Attach(AssociatedObject); - Parameters.OfType().Apply(x => x.MakeAwareOf(this)); + public static Func> BuildPossibleGuardNames { get; set; } + = method + => { + var guardNames = new List(); - - if (View.ExecuteOnLoad(AssociatedObject, ElementLoaded)) { - // Not yet sure if this will be needed - //var trigger = Interaction.GetTriggers(AssociatedObject) - // .FirstOrDefault(t => t.Actions.Contains(this)) as EventTrigger; - //if (trigger != null && trigger.EventName == "Loaded") - // Invoke(new RoutedEventArgs()); - } + const string GuardPrefix = "Can"; - View.ExecuteOnUnload(AssociatedObject, ElementUnloaded); - } + string methodName = method.Name; - base.OnAttached(); - } + guardNames.Add(GuardPrefix + methodName); - void ElementUnloaded(object sender, RoutedEventArgs e) - { - OnDetaching(); - } -#else - protected override void OnAttached() { - if (!View.InDesignMode) { - Parameters.Attach(AssociatedObject); - Parameters.Apply(x => x.MakeAwareOf(this)); + const string AsyncMethodSuffix = "Async"; - if (View.ExecuteOnLoad(AssociatedObject, ElementLoaded)) { - var trigger = Interaction.GetTriggers(AssociatedObject) - .FirstOrDefault(t => t.Actions.Contains(this)) as EventTrigger; - if (trigger != null && trigger.EventName == "Loaded") - Invoke(new RoutedEventArgs()); + if (!methodName.EndsWith(AsyncMethodSuffix, StringComparison.OrdinalIgnoreCase)) { + return guardNames; } - } - base.OnAttached(); - } -#endif + guardNames.Add(GuardPrefix + methodName.Substring(0, methodName.Length - AsyncMethodSuffix.Length)); - static void HandlerPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - ((ActionMessage)d).UpdateContext(); - } + return guardNames; + }; /// - /// Called when the action is being detached from its AssociatedObject, but before it has actually occurred. + /// Gets or sets action to invoke the action using the specified . /// - protected override void OnDetaching() { - if (!View.InDesignMode) { - Detaching(this, EventArgs.Empty); - AssociatedObject.Loaded -= ElementLoaded; - Parameters.Detach(); - } + public static Action InvokeAction { get; set; } + = context + => { + object[] values = MessageBinder.DetermineParameters(context, context.Method.GetParameters()); + object returnValue = context.Method.Invoke(context.Target, values); + + if (returnValue is System.Threading.Tasks.Task task) { + returnValue = task.AsResult(); + } - base.OnDetaching(); - } + if (returnValue is IResult result) { + returnValue = new[] { result }; + } - void ElementLoaded(object sender, RoutedEventArgs e) { - UpdateContext(); + if (returnValue is IEnumerable enumerable) { + returnValue = enumerable.GetEnumerator(); + } - DependencyObject currentElement; - if (context.View == null) { - currentElement = AssociatedObject; - while (currentElement != null) { - if (Action.HasTargetSet(currentElement)) - break; + if (returnValue is IEnumerator enumerator) { + Coroutine.BeginExecute( + enumerator, + new CoroutineExecutionContext { + Source = context.Source, + View = context.View, + Target = context.Target, + }); + } + }; - currentElement = BindingScope.GetVisualParent(currentElement); - } - } - else currentElement = context.View; + /// + /// Gets or sets func to apply an availability effect, such as IsEnabled, to an element. + /// + /// Returns a value indicating whether or not the action is available. + public static Func ApplyAvailabilityEffect { get; set; } + = context + => { +#if WINDOWS_UWP + if (context.Source is not Control source) { + return true; + } +#else + FrameworkElement source = context.Source; + if (source == null) { + return true; + } +#endif -#if NET || CAL_NETCORE - var binding = new Binding { - Path = new PropertyPath(Message.HandlerProperty), - Source = currentElement - }; -#elif WINDOWS_UWP - var binding = new Binding { - Source = currentElement - }; +#if WINDOWS_UWP + bool hasBinding = ConventionManager.HasBinding(source, Control.IsEnabledProperty); #else - const string bindingText = ""; + bool hasBinding = ConventionManager.HasBinding(source, UIElement.IsEnabledProperty); +#endif + if (!hasBinding && context.CanExecute != null) { + source.IsEnabled = context.CanExecute(); + } - var binding = (Binding)XamlReader.Load(bindingText); - binding.Source = currentElement; + return source.IsEnabled; + }; + + /// + /// Gets or sets func to find the method on the target matching the specified message. + /// + /// The matching method, if available. + public static Func GetTargetMethod { get; set; } + = (message, target) + => +#if WINDOWS_UWP + (from method in target.GetType().GetRuntimeMethods() + where method.Name == message.MethodName + let methodParameters = method.GetParameters() + where message.Parameters.Count == methodParameters.Length + select method).FirstOrDefault(); +#else + (from method in target.GetType().GetMethods() + where method.Name == message.MethodName + let methodParameters = method.GetParameters() + where message.Parameters.Count == methodParameters.Length + select method).FirstOrDefault(); #endif - BindingOperations.SetBinding(this, HandlerProperty, binding); - } - void UpdateContext() { - if (context != null) - context.Dispose(); + /// + /// Gets or sets action to Set the target, method and view on the context. Uses a bubbling strategy by default. + /// + public static Action SetMethodBinding { get; set; } + = context + => { + FrameworkElement source = context.Source; + + DependencyObject currentElement = source; + while (currentElement != null) { + if (Action.HasTargetSet(currentElement)) { + object target = Message.GetHandler(currentElement); + if (target != null) { + MethodInfo method = GetTargetMethod(context.Message, target); + if (method != null) { + context.Method = method; + context.Target = target; + context.View = currentElement; + return; + } + } else { + context.View = currentElement; + return; + } + } - context = new ActionExecutionContext { - Message = this, - Source = AssociatedObject - }; + currentElement = BindingScope.GetVisualParent(currentElement); + } - PrepareContext(context); - UpdateAvailabilityCore(); - } + if (source != null && source.DataContext != null) { + object target = source.DataContext; + MethodInfo method = GetTargetMethod(context.Message, target); + + if (method != null) { + context.Target = target; + context.Method = method; + context.View = source; + } + } + }; /// - /// Invokes the action. + /// Gets or sets action to prepare the action execution context for use. /// - /// The parameter to the action. If the action does not require a parameter, the parameter may be set to a null reference. - protected override void Invoke(object eventArgs) { - Log.Info("Invoking {0}.", this); + public static Action PrepareContext { get; set; } + = context + => { + SetMethodBinding(context); + if (context.Target == null || context.Method == null) { + return; + } - if (context == null) { - UpdateContext(); - } + var possibleGuardNames = BuildPossibleGuardNames(context.Method).ToList(); - if (context.Target == null || context.View == null) { - PrepareContext(context); - if (context.Target == null) { - var ex = new Exception(string.Format("No target found for method {0}.", context.Message.MethodName)); - Log.Error(ex); + MethodInfo guard = TryFindGuardMethod(context, possibleGuardNames); + + if (guard != null) { + context.CanExecute = () => (bool)guard.Invoke(context.Target, MessageBinder.DetermineParameters(context, guard.GetParameters())); - if (!ThrowsExceptions) return; - throw ex; - } + } - if (!UpdateAvailabilityCore()) { - return; - } - } + if (context.Target is not INotifyPropertyChanged inpc) { + return; + } - if (context.Method == null) { - var ex = new Exception(string.Format("Method {0} not found on target of type {1}.", context.Message.MethodName, context.Target.GetType())); - Log.Error(ex); + Type targetType = context.Target.GetType(); + string matchingGuardName = null; + foreach (string possibleGuardName in possibleGuardNames) { + matchingGuardName = possibleGuardName; + guard = GetMethodInfo(targetType, "get_" + matchingGuardName); + if (guard != null) { + break; + } + } - if (!ThrowsExceptions) - return; - throw ex; - } + if (guard == null) { + return; + } - context.EventArgs = eventArgs; + void OnPropertyChanged(object s, PropertyChangedEventArgs e) { + if (string.IsNullOrEmpty(e.PropertyName) || e.PropertyName == matchingGuardName) { + Caliburn.Micro.Execute.OnUIThread(() => { + ActionMessage message = context.Message; + if (message == null) { + inpc.PropertyChanged -= OnPropertyChanged; + return; + } + + message.UpdateAvailability(); + }); + } + } - if (EnforceGuardsDuringInvocation && context.CanExecute != null && !context.CanExecute()) { - return; - } + inpc.PropertyChanged += OnPropertyChanged; + context.Disposing += (sender, e) => inpc.PropertyChanged -= OnPropertyChanged; + context.Message.Detaching += (sender, e) => inpc.PropertyChanged -= OnPropertyChanged; + context.CanExecute = () => (bool)guard.Invoke(context.Target, MessageBinder.DetermineParameters(context, guard.GetParameters())); + }; - InvokeAction(context); - context.EventArgs = null; + /// + /// Gets or sets the name of the method to be invoked on the presentation model class. + /// + /// The name of the method. +#if !WINDOWS_UWP + [Category("Common Properties")] +#endif + public string MethodName { + get => (string)GetValue(MethodNameProperty); + set => SetValue(MethodNameProperty, value); } + /// + /// Gets the parameters to pass as part of the method invocation. + /// + /// The parameters. +#if !WINDOWS_UWP + [Category("Common Properties")] +#endif + public AttachedCollection Parameters + => (AttachedCollection)GetValue(ParametersProperty); + /// /// Forces an update of the UI's Enabled/Disabled state based on the the preconditions associated with the method. /// public virtual void UpdateAvailability() { - if (context == null) + if (context == null) { return; + } - if (context.Target == null || context.View == null) + if (context.Target == null || context.View == null) { PrepareContext(context); + } UpdateAvailabilityCore(); } - bool UpdateAvailabilityCore() { - Log.Info("{0} availability update.", this); - return ApplyAvailabilityEffect(context); - } - /// - /// Returns a that represents the current . + /// Returns a that represents the current . /// /// - /// A that represents the current . + /// A that represents the current . /// - public override string ToString() { - return "Action: " + MethodName; - } + public override string ToString() + => "Action: " + MethodName; /// - /// Invokes the action using the specified + /// Called when the action is being detached from its AssociatedObject, but before it has actually occurred. /// - public static Action InvokeAction = context => { - var values = MessageBinder.DetermineParameters(context, context.Method.GetParameters()); - var returnValue = context.Method.Invoke(context.Target, values); - - var task = returnValue as System.Threading.Tasks.Task; - if (task != null) { - returnValue = task.AsResult(); - } - - var result = returnValue as IResult; - if (result != null) { - returnValue = new[] { result }; - } - - var enumerable = returnValue as IEnumerable; - if (enumerable != null) { - returnValue = enumerable.GetEnumerator(); - } - - var enumerator = returnValue as IEnumerator; - if (enumerator != null) { - Coroutine.BeginExecute(enumerator, - new CoroutineExecutionContext - { - Source = context.Source, - View = context.View, - Target = context.Target - }); + protected override void OnDetaching() { + if (!View.InDesignMode) { + Detaching(this, EventArgs.Empty); + AssociatedObject.Loaded -= ElementLoaded; + Parameters.Detach(); } - }; - /// - /// Applies an availability effect, such as IsEnabled, to an element. - /// - /// Returns a value indicating whether or not the action is available. - public static Func ApplyAvailabilityEffect = context => { + base.OnDetaching(); + } -#if WINDOWS_UWP - var source = context.Source as Control; + /* + * Change in the public API of Microsoft.Xaml.Behaviors causing CA1725 issue. + * The parameter name changed from 'parameter' to 'parmeter' (without second 'a') + * This if statement to reslove + * CA1725: Parameter names should match base declaration. + */ +#if UAP10_0_19041 + /// Invokes the action. + /// The parameter to the action. If the action does not require a parameter, the parameter may be set to a null reference. + protected override void Invoke(object parmeter) { #else - var source = context.Source; + /// Invokes the action. + /// The parameter to the action. If the action does not require a parameter, the parameter may be set to a null reference. + protected override void Invoke(object parameter) { #endif - if (source == null) { - return true; - } + Log.Info("Invoking {0}.", this); -#if WINDOWS_UWP - var hasBinding = ConventionManager.HasBinding(source, Control.IsEnabledProperty); -#else - var hasBinding = ConventionManager.HasBinding(source, UIElement.IsEnabledProperty); -#endif - if (!hasBinding && context.CanExecute != null) { - source.IsEnabled = context.CanExecute(); + if (context == null) { + UpdateContext(); } - return source.IsEnabled; - }; - - /// - /// Finds the method on the target matching the specified message. - /// - /// The matching method, if available. - public static Func GetTargetMethod = (message, target) => { -#if WINDOWS_UWP - return (from method in target.GetType().GetRuntimeMethods() - where method.Name == message.MethodName - let methodParameters = method.GetParameters() - where message.Parameters.Count == methodParameters.Length - select method).FirstOrDefault(); -#else - return (from method in target.GetType().GetMethods() - where method.Name == message.MethodName - let methodParameters = method.GetParameters() - where message.Parameters.Count == methodParameters.Length - select method).FirstOrDefault(); -#endif - }; + if (context.Target == null || context.View == null) { + PrepareContext(context); + if (context.Target == null) { + var ex = new Exception(string.Format(CultureInfo.InvariantCulture, "No target found for method {0}.", context.Message.MethodName)); + Log.Error(ex); - /// - /// Sets the target, method and view on the context. Uses a bubbling strategy by default. - /// - public static Action SetMethodBinding = context => { - var source = context.Source; - - DependencyObject currentElement = source; - while (currentElement != null) { - if (Action.HasTargetSet(currentElement)) { - var target = Message.GetHandler(currentElement); - if (target != null) { - var method = GetTargetMethod(context.Message, target); - if (method != null) { - context.Method = method; - context.Target = target; - context.View = currentElement; - return; - } - } - else { - context.View = currentElement; + if (!ThrowsExceptions) { return; } + + throw ex; } - currentElement = BindingScope.GetVisualParent(currentElement); + if (!UpdateAvailabilityCore()) { + return; + } } - if (source != null && source.DataContext != null) { - var target = source.DataContext; - var method = GetTargetMethod(context.Message, target); + if (context.Method == null) { + var ex = new Exception(string.Format(CultureInfo.InvariantCulture, "Method {0} not found on target of type {1}.", context.Message.MethodName, context.Target.GetType())); + Log.Error(ex); - if (method != null) { - context.Target = target; - context.Method = method; - context.View = source; + if (!ThrowsExceptions) { + return; } + + throw ex; } - }; - /// - /// Prepares the action execution context for use. - /// - public static Action PrepareContext = context => { - SetMethodBinding(context); - if (context.Target == null || context.Method == null) - { +#if UAP10_0_19041 + context.EventArgs = parmeter; +#else + context.EventArgs = parameter; +#endif + + if (EnforceGuardsDuringInvocation && context.CanExecute != null && !context.CanExecute()) { return; } - var possibleGuardNames = BuildPossibleGuardNames(context.Method).ToList(); - var guard = TryFindGuardMethod(context, possibleGuardNames); + InvokeAction(context); + context.EventArgs = null; + } - if (guard == null) - { - var inpc = context.Target as INotifyPropertyChanged; - if (inpc == null) - return; + /// + /// Called after the action is attached to an AssociatedObject. + /// +#if WINDOWS_UWP + protected override void OnAttached() { + if (!View.InDesignMode) { + Parameters.Attach(AssociatedObject); + Parameters.OfType().Apply(x => x.MakeAwareOf(this)); - var targetType = context.Target.GetType(); - string matchingGuardName = null; - foreach (string possibleGuardName in possibleGuardNames) - { - matchingGuardName = possibleGuardName; - guard = GetMethodInfo(targetType, "get_" + matchingGuardName); - if (guard != null) break; + if (View.ExecuteOnLoad(AssociatedObject, ElementLoaded)) { + // Not yet sure if this will be needed + // var trigger = Interaction.GetTriggers(AssociatedObject) + // .FirstOrDefault(t => t.Actions.Contains(this)) as EventTrigger; + // if (trigger != null && trigger.EventName == "Loaded") + // Invoke(new RoutedEventArgs()); } - if (guard == null) - return; + View.ExecuteOnUnload(AssociatedObject, (s, e) => OnDetaching()); + } - PropertyChangedEventHandler handler = null; - handler = (s, e) => { - if (string.IsNullOrEmpty(e.PropertyName) || e.PropertyName == matchingGuardName) - { - Caliburn.Micro.Execute.OnUIThread(() => { - var message = context.Message; - if (message == null) - { - inpc.PropertyChanged -= handler; - return; - } - message.UpdateAvailability(); - }); - } - }; + base.OnAttached(); + } +#else + protected override void OnAttached() { + if (!View.InDesignMode) { + Parameters.Attach(AssociatedObject); + Parameters.Apply(x => x.MakeAwareOf(this)); - inpc.PropertyChanged += handler; - context.Disposing += delegate { inpc.PropertyChanged -= handler; }; - context.Message.Detaching += delegate { inpc.PropertyChanged -= handler; }; + if (View.ExecuteOnLoad(AssociatedObject, ElementLoaded)) { + if (Interaction.GetTriggers(AssociatedObject) + .FirstOrDefault(t => t.Actions.Contains(this)) is EventTrigger trigger && trigger.EventName == "Loaded") { + Invoke(new RoutedEventArgs()); + } + } } - context.CanExecute = () => (bool)guard.Invoke( - context.Target, - MessageBinder.DetermineParameters(context, guard.GetParameters())); - }; + base.OnAttached(); + } +#endif /// - /// Try to find a candidate for guard function, having: + /// Try to find a candidate for guard function, having: /// - a name matching any of /// - no generic parameters /// - a bool return type - /// - no parameters or a set of parameters corresponding to the action method + /// - no parameters or a set of parameters corresponding to the action method. /// - /// The execution context + /// The execution context. /// Method names to look for. - ///A MethodInfo, if found; null otherwise - static MethodInfo TryFindGuardMethod(ActionExecutionContext context, IEnumerable possibleGuardNames) { - var targetType = context.Target.GetType(); + /// A MethodInfo, if found; null otherwise. + private static MethodInfo TryFindGuardMethod(ActionExecutionContext context, IEnumerable possibleGuardNames) { + Type targetType = context.Target.GetType(); MethodInfo guard = null; - foreach (string possibleGuardName in possibleGuardNames) - { + foreach (string possibleGuardName in possibleGuardNames) { guard = GetMethodInfo(targetType, possibleGuardName); - if (guard != null) break; + if (guard != null) { + break; + } } - if (guard == null) return null; - if (guard.ContainsGenericParameters) return null; - if (!typeof(bool).Equals(guard.ReturnType)) return null; + if (guard == null) { + return null; + } + + if (guard.ContainsGenericParameters) { + return null; + } - var guardPars = guard.GetParameters(); - var actionPars = context.Method.GetParameters(); - if (guardPars.Length == 0) return guard; - if (guardPars.Length != actionPars.Length) return null; + if (!typeof(bool).Equals(guard.ReturnType)) { + return null; + } - var comparisons = guardPars.Zip( - context.Method.GetParameters(), - (x, y) => x.ParameterType == y.ParameterType - ); + ParameterInfo[] guardPars = guard.GetParameters(); + ParameterInfo[] actionPars = context.Method.GetParameters(); + if (guardPars.Length == 0) { + return guard; + } - if (comparisons.Any(x => !x)) - { + if (guardPars.Length != actionPars.Length) { return null; } - return guard; + IEnumerable comparisons = guardPars.Zip( + context.Method.GetParameters(), + (x, y) => x.ParameterType == y.ParameterType); + + return comparisons.Any(x => !x) ? null : guard; } - /// - /// Returns the list of possible names of guard methods / properties for the given method. - /// - public static Func> BuildPossibleGuardNames = method => { + private static void HandlerPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + => ((ActionMessage)d).UpdateContext(); - var guardNames = new List(); + private static MethodInfo GetMethodInfo(Type t, string methodName) => +#if WINDOWS_UWP + t.GetRuntimeMethods().SingleOrDefault(m => m.Name == methodName); +#else + t.GetMethod(methodName); +#endif - const string GuardPrefix = "Can"; + private bool UpdateAvailabilityCore() { + Log.Info("{0} availability update.", this); - var methodName = method.Name; + return ApplyAvailabilityEffect(context); + } - guardNames.Add(GuardPrefix + methodName); + private void UpdateContext() { + context?.Dispose(); - const string AsyncMethodSuffix = "Async"; + context = new ActionExecutionContext { + Message = this, + Source = AssociatedObject, + }; - if (methodName.EndsWith(AsyncMethodSuffix, StringComparison.OrdinalIgnoreCase)) { - guardNames.Add(GuardPrefix + methodName.Substring(0, methodName.Length - AsyncMethodSuffix.Length)); - } + PrepareContext(context); + UpdateAvailabilityCore(); + } - return guardNames; - }; + private void ElementLoaded(object sender, RoutedEventArgs e) { + UpdateContext(); - static MethodInfo GetMethodInfo(Type t, string methodName) - { -#if WINDOWS_UWP - return t.GetRuntimeMethods().SingleOrDefault(m => m.Name == methodName); + DependencyObject currentElement; + if (context.View == null) { + currentElement = AssociatedObject; + while (currentElement != null) { + if (Action.HasTargetSet(currentElement)) { + break; + } + + currentElement = BindingScope.GetVisualParent(currentElement); + } + } else { + currentElement = context.View; + } + +#if NET || CAL_NETCORE + var binding = new Binding { + Source = currentElement, + Path = new PropertyPath(Message.HandlerProperty), + }; +#elif WINDOWS_UWP + var binding = new Binding { + Source = currentElement, + }; #else - return t.GetMethod(methodName); + const string bindingText = ""; + + var binding = (Binding)XamlReader.Load(bindingText); + binding.Source = currentElement; #endif + BindingOperations.SetBinding(this, HandlerProperty, binding); } } } diff --git a/src/Caliburn.Micro.Platform/Bind.cs b/src/Caliburn.Micro.Platform/Bind.cs index d5dab8175..972552727 100644 --- a/src/Caliburn.Micro.Platform/Bind.cs +++ b/src/Caliburn.Micro.Platform/Bind.cs @@ -1,4 +1,28 @@ -#if XFORMS +#if WINDOWS_UWP +using System.Globalization; + +using Windows.UI.Xaml; +using Windows.UI.Xaml.Data; +#elif XFORMS +using System; + +using Xamarin.Forms; + +using DependencyObject =Xamarin.Forms.BindableObject; +using DependencyProperty = Xamarin.Forms.BindableProperty; +using FrameworkElement = Xamarin.Forms.VisualElement; + +#elif MAUI +using DependencyObject = Microsoft.Maui.Controls.BindableObject; +using DependencyProperty = Microsoft.Maui.Controls.BindableProperty; +using FrameworkElement = Microsoft.Maui.Controls.VisualElement; +#else +using System.Globalization; +using System.Windows; +using System.Windows.Data; +#endif + +#if XFORMS namespace Caliburn.Micro.Xamarin.Forms #elif MAUI namespace Caliburn.Micro.Maui @@ -6,27 +30,6 @@ namespace Caliburn.Micro.Maui namespace Caliburn.Micro #endif { - using System; -#if WINDOWS_UWP - using Windows.UI.Xaml; - using Windows.UI.Xaml.Data; -#elif XFORMS - using global::Xamarin.Forms; - using UIElement = global::Xamarin.Forms.Element; - using FrameworkElement = global::Xamarin.Forms.VisualElement; - using DependencyProperty = global::Xamarin.Forms.BindableProperty; - using DependencyObject =global::Xamarin.Forms.BindableObject; -#elif MAUI - using global::Microsoft.Maui; - using UIElement = global::Microsoft.Maui.Controls.Element; - using FrameworkElement = global::Microsoft.Maui.Controls.VisualElement; - using DependencyProperty = global::Microsoft.Maui.Controls.BindableProperty; - using DependencyObject =global::Microsoft.Maui.Controls.BindableObject; -#else - using System.Windows; - using System.Windows.Data; -#endif - /// /// Hosts dependency properties for binding. /// @@ -34,88 +37,120 @@ public static class Bind { /// /// Allows binding on an existing view. Use this on root UserControls, Pages and Windows; not in a DataTemplate. /// - public static DependencyProperty ModelProperty = - DependencyPropertyHelper.RegisterAttached( + public static readonly DependencyProperty ModelProperty + = DependencyPropertyHelper.RegisterAttached( "Model", typeof(object), typeof(Bind), - null, + null, ModelChanged); /// /// Allows binding on an existing view without setting the data context. Use this from within a DataTemplate. /// - public static DependencyProperty ModelWithoutContextProperty = - DependencyPropertyHelper.RegisterAttached( + public static readonly DependencyProperty ModelWithoutContextProperty + = DependencyPropertyHelper.RegisterAttached( "ModelWithoutContext", typeof(object), typeof(Bind), - null, + null, ModelWithoutContextChanged); - internal static DependencyProperty NoContextProperty = - DependencyPropertyHelper.RegisterAttached( + /// + /// Allows application of conventions at design-time. + /// + public static readonly DependencyProperty AtDesignTimeProperty + = DependencyPropertyHelper.RegisterAttached( + "AtDesignTime", + typeof(bool), + typeof(Bind), + false, + AtDesignTimeChanged); + + internal static readonly DependencyProperty NoContextProperty + = DependencyPropertyHelper.RegisterAttached( "NoContext", typeof(bool), typeof(Bind), false); + private static readonly DependencyProperty DataContextProperty + = DependencyPropertyHelper.RegisterAttached( + "DataContext", + typeof(object), + typeof(Bind), + null, + DataContextChanged); + /// /// Gets the model to bind to. /// /// The dependency object to bind to. /// The model. - public static object GetModelWithoutContext(DependencyObject dependencyObject) { - return dependencyObject.GetValue(ModelWithoutContextProperty); - } + public static object GetModelWithoutContext(DependencyObject dependencyObject) + => dependencyObject.GetValue(ModelWithoutContextProperty); /// /// Sets the model to bind to. /// /// The dependency object to bind to. /// The model. - public static void SetModelWithoutContext(DependencyObject dependencyObject, object value) { - dependencyObject.SetValue(ModelWithoutContextProperty, value); - } + public static void SetModelWithoutContext(DependencyObject dependencyObject, object value) + => dependencyObject.SetValue(ModelWithoutContextProperty, value); /// /// Gets the model to bind to. /// /// The dependency object to bind to. /// The model. - public static object GetModel(DependencyObject dependencyObject) { - return dependencyObject.GetValue(ModelProperty); - } + public static object GetModel(DependencyObject dependencyObject) => dependencyObject.GetValue(ModelProperty); /// /// Sets the model to bind to. /// /// The dependency object to bind to. /// The model. - public static void SetModel(DependencyObject dependencyObject, object value) { - dependencyObject.SetValue(ModelProperty, value); - } + public static void SetModel(DependencyObject dependencyObject, object value) + => dependencyObject.SetValue(ModelProperty, value); + + /// + /// Gets whether or not conventions are being applied at design-time. + /// + /// The ui to apply conventions to. + /// Whether or not conventions are applied. +#if !MAUI && (NET || CAL_NETCORE) + [AttachedPropertyBrowsableForTypeAttribute(typeof(DependencyObject))] +#endif + public static bool GetAtDesignTime(DependencyObject dependencyObject) + => (bool)dependencyObject.GetValue(AtDesignTimeProperty); - static void ModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { + /// + /// Sets whether or not do bind conventions at design-time. + /// + /// The ui to apply conventions to. + /// Whether or not to apply conventions. + public static void SetAtDesignTime(DependencyObject dependencyObject, bool value) + => dependencyObject.SetValue(AtDesignTimeProperty, value); + + private static void ModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (View.InDesignMode || e.NewValue == null || e.NewValue == e.OldValue) { return; } - var fe = d as FrameworkElement; - if (fe == null) { + if (!(d is FrameworkElement fe)) { return; } View.ExecuteOnLoad(fe, delegate { - var target = e.NewValue; + object target = e.NewValue; d.SetValue(View.IsScopeRootProperty, true); #if XFORMS || MAUI - var context = fe.Id.ToString("N"); + string context = fe.Id.ToString("N"); #else - var context = string.IsNullOrEmpty(fe.Name) - ? fe.GetHashCode().ToString() + string context = string.IsNullOrEmpty(fe.Name) + ? fe.GetHashCode().ToString(CultureInfo.InvariantCulture) : fe.Name; #endif @@ -123,25 +158,24 @@ static void ModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs }); } - static void ModelWithoutContextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { + private static void ModelWithoutContextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (View.InDesignMode || e.NewValue == null || e.NewValue == e.OldValue) { return; } - var fe = d as FrameworkElement; - if (fe == null) { + if (!(d is FrameworkElement fe)) { return; } View.ExecuteOnLoad(fe, delegate { - var target = e.NewValue; + object target = e.NewValue; d.SetValue(View.IsScopeRootProperty, true); #if XFORMS || MAUI - var context = fe.Id.ToString("N"); + string context = fe.Id.ToString("N"); #else - var context = string.IsNullOrEmpty(fe.Name) - ? fe.GetHashCode().ToString() + string context = string.IsNullOrEmpty(fe.Name) + ? fe.GetHashCode().ToString(CultureInfo.InvariantCulture) : fe.Name; #endif @@ -150,47 +184,17 @@ static void ModelWithoutContextChanged(DependencyObject d, DependencyPropertyCha }); } - /// - /// Allows application of conventions at design-time. - /// - public static DependencyProperty AtDesignTimeProperty = - DependencyPropertyHelper.RegisterAttached( - "AtDesignTime", - typeof(bool), - typeof(Bind), - false, - AtDesignTimeChanged); - - /// - /// Gets whether or not conventions are being applied at design-time. - /// - /// The ui to apply conventions to. - /// Whether or not conventions are applied. -#if !MAUI && (NET || CAL_NETCORE) - [AttachedPropertyBrowsableForTypeAttribute(typeof(DependencyObject))] -#endif - public static bool GetAtDesignTime(DependencyObject dependencyObject) { - return (bool)dependencyObject.GetValue(AtDesignTimeProperty); - } - - /// - /// Sets whether or not do bind conventions at design-time. - /// - /// The ui to apply conventions to. - /// Whether or not to apply conventions. - public static void SetAtDesignTime(DependencyObject dependencyObject, bool value) { - dependencyObject.SetValue(AtDesignTimeProperty, value); - } - - static void AtDesignTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - if (!View.InDesignMode) + private static void AtDesignTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { + if (!View.InDesignMode) { return; + } - var atDesignTime = (bool) e.NewValue; - if (!atDesignTime) + bool atDesignTime = (bool)e.NewValue; + if (!atDesignTime) { return; + } #if XFORMS - d.SetBinding(DataContextProperty, String.Empty); + d.SetBinding(DataContextProperty, string.Empty); #elif MAUI d.SetBinding(DataContextProperty, null); #else @@ -198,28 +202,23 @@ static void AtDesignTimeChanged(DependencyObject d, DependencyPropertyChangedEve #endif } - static readonly DependencyProperty DataContextProperty = - DependencyPropertyHelper.RegisterAttached( - "DataContext", - typeof(object), - typeof(Bind), - null, DataContextChanged); - - static void DataContextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - if (!View.InDesignMode) + private static void DataContextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { + if (!View.InDesignMode) { return; + } - var enable = d.GetValue(AtDesignTimeProperty); - if (enable == null || ((bool)enable) == false || e.NewValue == null) + object enable = d.GetValue(AtDesignTimeProperty); + if (enable == null || ((bool)enable) == false || e.NewValue == null) { return; + } - var fe = d as FrameworkElement; - if (fe == null) + if (!(d is FrameworkElement fe)) { return; + } #if XFORMS || MAUI ViewModelBinder.Bind(e.NewValue, d, fe.Id.ToString("N")); #else - ViewModelBinder.Bind(e.NewValue, d, string.IsNullOrEmpty(fe.Name) ? fe.GetHashCode().ToString() : fe.Name); + ViewModelBinder.Bind(e.NewValue, d, string.IsNullOrEmpty(fe.Name) ? fe.GetHashCode().ToString(CultureInfo.InvariantCulture) : fe.Name); #endif } } diff --git a/src/Caliburn.Micro.Platform/BindingScope.cs b/src/Caliburn.Micro.Platform/BindingScope.cs index 12a31fe57..361350397 100644 --- a/src/Caliburn.Micro.Platform/BindingScope.cs +++ b/src/Caliburn.Micro.Platform/BindingScope.cs @@ -1,51 +1,215 @@ -namespace Caliburn.Micro { - using System; - using System.Collections.Generic; - using System.Linq; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; + #if WINDOWS_UWP - using System.ServiceModel; - using Windows.UI.Xaml; - using Windows.UI.Xaml.Controls; - using Windows.UI.Xaml.Controls.Primitives; - using Windows.UI.Xaml.Media; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; +using Windows.UI.Xaml.Media; #else - using System.Windows; - using System.Windows.Controls; - using System.Windows.Media; - using System.Windows.Media.Media3D; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using System.Windows.Media.Media3D; #endif +namespace Caliburn.Micro { /// /// Provides methods for searching a given scope for named elements. /// public static class BindingScope { - static readonly List ChildResolvers = new List(); - static readonly Dictionary NonResolvableChildTypes = new Dictionary(); + private static readonly List ChildResolvers = new List(); + private static readonly Dictionary NonResolvableChildTypes = new Dictionary(); - static BindingScope() - { + static BindingScope() { AddChildResolver(e => new[] { e.Content as DependencyObject }); - AddChildResolver(e => e.Items.OfType().ToArray() ); -#if !WINDOWS_UWP - AddChildResolver(e => new[] { e.Header as DependencyObject }); - AddChildResolver(e => new[] { e.Header as DependencyObject }); -#endif + AddChildResolver(e => e.Items.OfType().ToArray()); #if WINDOWS_UWP AddChildResolver(e => new[] { e.ZoomedInView as DependencyObject, e.ZoomedOutView as DependencyObject }); AddChildResolver(e => new[] { e.Header as DependencyObject }); -#endif -#if WINDOWS_UWP AddChildResolver(e => new[] { e.Footer as DependencyObject }); AddChildResolver(ResolveHub); AddChildResolver(e => new[] { e.Header as DependencyObject }); AddChildResolver(ResolveCommandBar); AddChildResolver