From 1146c9651e3e892bfe1aefa764375a4aa5582e8e Mon Sep 17 00:00:00 2001 From: Ian Griffiths Date: Mon, 12 Feb 2024 18:28:54 +0000 Subject: [PATCH 1/8] Move UI and platform types out of System.Reactive Deprecate all UI-framework-specific and platform-specific types in System.Reactive. Add various System.Reactive.Integration.... packages with the replacement types. --- Rx.NET/Source/System.Reactive.sln | 78 +++ .../Strings_PlatformServices.Designer.cs | 73 +++ .../Strings_PlatformServices.resx | 123 +++++ .../System.Reactive.Integration.Uwp/Stubs.cs | 12 + .../System.Reactive.Integration.Uwp.csproj | 56 ++ .../ThreadPoolTimerExtensions.cs | 18 + .../UwpThreadPoolScheduler.cs | 184 +++++++ .../build/NuGet.Readme.md | 43 ++ .../ControlScheduler.cs | 213 ++++++++ ...m.Reactive.Integration.WindowsForms.csproj | 29 + .../WindowsFormsControlObservable.cs | 73 +++ .../build/NuGet.Readme.md | 26 + .../AsyncInfoExtensions.cs | 17 + .../AsyncInfoObservableExtensions.cs | 276 ++++++++++ .../AsyncInfoToObservableBridge.cs | 108 ++++ .../CoreDispatcherScheduler.cs | 266 ++++++++++ .../EventPatternSource.cs | 29 + .../ITypedEventPatternSource.cs | 25 + .../StableCompositeDisposable.cs | 65 +++ .../Strings_WindowsThreading.Designer.cs | 81 +++ .../Strings_WindowsThreading.resx | 126 +++++ ...Reactive.Integration.WindowsRuntime.csproj | 44 ++ .../WindowsRuntimeAsyncInfoObservable.cs | 230 ++++++++ .../WindowsRuntimeCoreDispatcherObservable.cs | 315 +++++++++++ .../WindowsRuntimeObservable.Events.cs | 116 ++++ ...imeObservable.StandardSequenceOperators.cs | 135 +++++ .../build/NuGet.Readme.md | 30 ++ .../DispatcherScheduler.cs | 215 ++++++++ .../Strings_WindowsThreading.Designer.cs | 72 +++ .../Strings_WindowsThreading.resx | 123 +++++ .../System.Reactive.Integration.Wpf.csproj | 44 ++ .../WpfDispatcherObservable.cs | 498 ++++++++++++++++++ .../build/NuGet.Readme.md | 26 + .../System.Reactive/Concurrency/AsyncLock.cs | 2 +- .../ThreadPoolScheduler.Windows.cs | 31 +- .../src/System.Reactive/Notification.cs | 8 +- .../Desktop/Concurrency/ControlScheduler.cs | 11 +- .../Concurrency/DispatcherScheduler.cs | 10 +- .../Desktop/Linq/ControlObservable.cs | 49 +- .../Desktop/Linq/DispatcherObservable.cs | 125 ++++- .../Concurrency/CoreDispatcherScheduler.cs | 13 +- .../Platforms/UWP/EventPatternSource.cs | 4 + .../UWP/Foundation/AsyncInfoExtensions.cs | 13 +- .../Foundation/AsyncInfoToObservableBridge.cs | 9 + .../Platforms/UWP/IEventPatternSource.cs | 56 +- .../Platforms/UWP/Linq/AsyncInfoObservable.cs | 103 +++- .../UWP/Linq/CoreDispatcherObservable.cs | 117 +++- .../UWP/Linq/WindowsObservable.Events.cs | 71 ++- ...owsObservable.StandardSequenceOperators.cs | 4 + .../Tests.System.Reactive.csproj | 5 + .../Tests/Concurrency/ControlSchedulerTest.cs | 266 ++++++++++ .../Concurrency/DispatcherSchedulerTest.cs | 253 +++++++++ .../Tests/Concurrency/SchedulerTest.cs | 23 +- .../Tests/Linq/Observable/ObserveOnTest.cs | 122 ++++- .../Tests/Linq/Observable/SubscribeOnTest.cs | 156 +++++- .../Tests/Linq/QbservableTest.cs | 34 +- 56 files changed, 5172 insertions(+), 82 deletions(-) create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.Uwp/Strings_PlatformServices.Designer.cs create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.Uwp/Strings_PlatformServices.resx create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.Uwp/Stubs.cs create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.Uwp/System.Reactive.Integration.Uwp.csproj create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.Uwp/ThreadPoolTimerExtensions.cs create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.Uwp/UwpThreadPoolScheduler.cs create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.Uwp/build/NuGet.Readme.md create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.WindowsForms/ControlScheduler.cs create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.WindowsForms/System.Reactive.Integration.WindowsForms.csproj create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.WindowsForms/System.Reactive.Linq/WindowsFormsControlObservable.cs create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.WindowsForms/build/NuGet.Readme.md create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/AsyncInfoExtensions.cs create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/AsyncInfoObservableExtensions.cs create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/AsyncInfoToObservableBridge.cs create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/CoreDispatcherScheduler.cs create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/EventPatternSource.cs create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/ITypedEventPatternSource.cs create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/StableCompositeDisposable.cs create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/Strings_WindowsThreading.Designer.cs create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/Strings_WindowsThreading.resx create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Integration.WindowsRuntime.csproj create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeAsyncInfoObservable.cs create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeCoreDispatcherObservable.cs create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeObservable.Events.cs create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeObservable.StandardSequenceOperators.cs create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/build/NuGet.Readme.md create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.Wpf/DispatcherScheduler.cs create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.Wpf/Strings_WindowsThreading.Designer.cs create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.Wpf/Strings_WindowsThreading.resx create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.Wpf/System.Reactive.Integration.Wpf.csproj create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.Wpf/System.Reactive.Linq/WpfDispatcherObservable.cs create mode 100644 Rx.NET/Source/src/System.Reactive.Integration.Wpf/build/NuGet.Readme.md diff --git a/Rx.NET/Source/System.Reactive.sln b/Rx.NET/Source/System.Reactive.sln index 6b821dc17..c03970699 100644 --- a/Rx.NET/Source/System.Reactive.sln +++ b/Rx.NET/Source/System.Reactive.sln @@ -66,6 +66,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmarks.System.Reactive" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Benchmarks", "Benchmarks", "{C8E480ED-B592-4341-A0C9-183E822EB6B9}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FrameworkIntegrations", "FrameworkIntegrations", "{1873A545-87AA-4C22-BA1A-8A6602F65749}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Reactive.Integration.WindowsForms", "src\System.Reactive.Integration.WindowsForms\System.Reactive.Integration.WindowsForms.csproj", "{DCD4D74D-FEED-4606-B9C6-6669A5D70B85}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Reactive.Integration.Wpf", "src\System.Reactive.Integration.Wpf\System.Reactive.Integration.Wpf.csproj", "{D548C2CA-5C32-4FFF-B9E9-A251971ED7B4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Reactive.Integration.Uwp", "src\System.Reactive.Integration.Uwp\System.Reactive.Integration.Uwp.csproj", "{C3FC6098-AC7F-4825-B292-4049BC6FC76E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Reactive.Integration.WindowsRuntime", "src\System.Reactive.Integration.WindowsRuntime\System.Reactive.Integration.WindowsRuntime.csproj", "{EB27A089-56EC-4621-BF88-E3B0DA8E6557}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -356,6 +366,70 @@ Global {5C7906F6-232E-455C-9269-68EF84F393C9}.Release|x64.Build.0 = Rx.net 4.0|Any CPU {5C7906F6-232E-455C-9269-68EF84F393C9}.Release|x86.ActiveCfg = Rx.net 4.0|Any CPU {5C7906F6-232E-455C-9269-68EF84F393C9}.Release|x86.Build.0 = Rx.net 4.0|Any CPU + {DCD4D74D-FEED-4606-B9C6-6669A5D70B85}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DCD4D74D-FEED-4606-B9C6-6669A5D70B85}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DCD4D74D-FEED-4606-B9C6-6669A5D70B85}.Debug|ARM.ActiveCfg = Debug|Any CPU + {DCD4D74D-FEED-4606-B9C6-6669A5D70B85}.Debug|ARM.Build.0 = Debug|Any CPU + {DCD4D74D-FEED-4606-B9C6-6669A5D70B85}.Debug|x64.ActiveCfg = Debug|Any CPU + {DCD4D74D-FEED-4606-B9C6-6669A5D70B85}.Debug|x64.Build.0 = Debug|Any CPU + {DCD4D74D-FEED-4606-B9C6-6669A5D70B85}.Debug|x86.ActiveCfg = Debug|Any CPU + {DCD4D74D-FEED-4606-B9C6-6669A5D70B85}.Debug|x86.Build.0 = Debug|Any CPU + {DCD4D74D-FEED-4606-B9C6-6669A5D70B85}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DCD4D74D-FEED-4606-B9C6-6669A5D70B85}.Release|Any CPU.Build.0 = Release|Any CPU + {DCD4D74D-FEED-4606-B9C6-6669A5D70B85}.Release|ARM.ActiveCfg = Release|Any CPU + {DCD4D74D-FEED-4606-B9C6-6669A5D70B85}.Release|ARM.Build.0 = Release|Any CPU + {DCD4D74D-FEED-4606-B9C6-6669A5D70B85}.Release|x64.ActiveCfg = Release|Any CPU + {DCD4D74D-FEED-4606-B9C6-6669A5D70B85}.Release|x64.Build.0 = Release|Any CPU + {DCD4D74D-FEED-4606-B9C6-6669A5D70B85}.Release|x86.ActiveCfg = Release|Any CPU + {DCD4D74D-FEED-4606-B9C6-6669A5D70B85}.Release|x86.Build.0 = Release|Any CPU + {D548C2CA-5C32-4FFF-B9E9-A251971ED7B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D548C2CA-5C32-4FFF-B9E9-A251971ED7B4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D548C2CA-5C32-4FFF-B9E9-A251971ED7B4}.Debug|ARM.ActiveCfg = Debug|Any CPU + {D548C2CA-5C32-4FFF-B9E9-A251971ED7B4}.Debug|ARM.Build.0 = Debug|Any CPU + {D548C2CA-5C32-4FFF-B9E9-A251971ED7B4}.Debug|x64.ActiveCfg = Debug|Any CPU + {D548C2CA-5C32-4FFF-B9E9-A251971ED7B4}.Debug|x64.Build.0 = Debug|Any CPU + {D548C2CA-5C32-4FFF-B9E9-A251971ED7B4}.Debug|x86.ActiveCfg = Debug|Any CPU + {D548C2CA-5C32-4FFF-B9E9-A251971ED7B4}.Debug|x86.Build.0 = Debug|Any CPU + {D548C2CA-5C32-4FFF-B9E9-A251971ED7B4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D548C2CA-5C32-4FFF-B9E9-A251971ED7B4}.Release|Any CPU.Build.0 = Release|Any CPU + {D548C2CA-5C32-4FFF-B9E9-A251971ED7B4}.Release|ARM.ActiveCfg = Release|Any CPU + {D548C2CA-5C32-4FFF-B9E9-A251971ED7B4}.Release|ARM.Build.0 = Release|Any CPU + {D548C2CA-5C32-4FFF-B9E9-A251971ED7B4}.Release|x64.ActiveCfg = Release|Any CPU + {D548C2CA-5C32-4FFF-B9E9-A251971ED7B4}.Release|x64.Build.0 = Release|Any CPU + {D548C2CA-5C32-4FFF-B9E9-A251971ED7B4}.Release|x86.ActiveCfg = Release|Any CPU + {D548C2CA-5C32-4FFF-B9E9-A251971ED7B4}.Release|x86.Build.0 = Release|Any CPU + {C3FC6098-AC7F-4825-B292-4049BC6FC76E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C3FC6098-AC7F-4825-B292-4049BC6FC76E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C3FC6098-AC7F-4825-B292-4049BC6FC76E}.Debug|ARM.ActiveCfg = Debug|Any CPU + {C3FC6098-AC7F-4825-B292-4049BC6FC76E}.Debug|ARM.Build.0 = Debug|Any CPU + {C3FC6098-AC7F-4825-B292-4049BC6FC76E}.Debug|x64.ActiveCfg = Debug|Any CPU + {C3FC6098-AC7F-4825-B292-4049BC6FC76E}.Debug|x64.Build.0 = Debug|Any CPU + {C3FC6098-AC7F-4825-B292-4049BC6FC76E}.Debug|x86.ActiveCfg = Debug|Any CPU + {C3FC6098-AC7F-4825-B292-4049BC6FC76E}.Debug|x86.Build.0 = Debug|Any CPU + {C3FC6098-AC7F-4825-B292-4049BC6FC76E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C3FC6098-AC7F-4825-B292-4049BC6FC76E}.Release|Any CPU.Build.0 = Release|Any CPU + {C3FC6098-AC7F-4825-B292-4049BC6FC76E}.Release|ARM.ActiveCfg = Release|Any CPU + {C3FC6098-AC7F-4825-B292-4049BC6FC76E}.Release|ARM.Build.0 = Release|Any CPU + {C3FC6098-AC7F-4825-B292-4049BC6FC76E}.Release|x64.ActiveCfg = Release|Any CPU + {C3FC6098-AC7F-4825-B292-4049BC6FC76E}.Release|x64.Build.0 = Release|Any CPU + {C3FC6098-AC7F-4825-B292-4049BC6FC76E}.Release|x86.ActiveCfg = Release|Any CPU + {C3FC6098-AC7F-4825-B292-4049BC6FC76E}.Release|x86.Build.0 = Release|Any CPU + {EB27A089-56EC-4621-BF88-E3B0DA8E6557}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EB27A089-56EC-4621-BF88-E3B0DA8E6557}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EB27A089-56EC-4621-BF88-E3B0DA8E6557}.Debug|ARM.ActiveCfg = Debug|Any CPU + {EB27A089-56EC-4621-BF88-E3B0DA8E6557}.Debug|ARM.Build.0 = Debug|Any CPU + {EB27A089-56EC-4621-BF88-E3B0DA8E6557}.Debug|x64.ActiveCfg = Debug|Any CPU + {EB27A089-56EC-4621-BF88-E3B0DA8E6557}.Debug|x64.Build.0 = Debug|Any CPU + {EB27A089-56EC-4621-BF88-E3B0DA8E6557}.Debug|x86.ActiveCfg = Debug|Any CPU + {EB27A089-56EC-4621-BF88-E3B0DA8E6557}.Debug|x86.Build.0 = Debug|Any CPU + {EB27A089-56EC-4621-BF88-E3B0DA8E6557}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EB27A089-56EC-4621-BF88-E3B0DA8E6557}.Release|Any CPU.Build.0 = Release|Any CPU + {EB27A089-56EC-4621-BF88-E3B0DA8E6557}.Release|ARM.ActiveCfg = Release|Any CPU + {EB27A089-56EC-4621-BF88-E3B0DA8E6557}.Release|ARM.Build.0 = Release|Any CPU + {EB27A089-56EC-4621-BF88-E3B0DA8E6557}.Release|x64.ActiveCfg = Release|Any CPU + {EB27A089-56EC-4621-BF88-E3B0DA8E6557}.Release|x64.Build.0 = Release|Any CPU + {EB27A089-56EC-4621-BF88-E3B0DA8E6557}.Release|x86.ActiveCfg = Release|Any CPU + {EB27A089-56EC-4621-BF88-E3B0DA8E6557}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -375,6 +449,10 @@ Global {A31DDC7E-E883-4DBD-8FB8-D7DFC56059F6} = {A0F39260-B8F8-4FCB-9679-0ED917A22BDF} {01CCDA6D-4D00-4DF2-82B0-359FD5E0CDC6} = {D324579D-CBE6-4867-8980-D7842C7C45A2} {5C7906F6-232E-455C-9269-68EF84F393C9} = {C8E480ED-B592-4341-A0C9-183E822EB6B9} + {DCD4D74D-FEED-4606-B9C6-6669A5D70B85} = {1873A545-87AA-4C22-BA1A-8A6602F65749} + {D548C2CA-5C32-4FFF-B9E9-A251971ED7B4} = {1873A545-87AA-4C22-BA1A-8A6602F65749} + {C3FC6098-AC7F-4825-B292-4049BC6FC76E} = {1873A545-87AA-4C22-BA1A-8A6602F65749} + {EB27A089-56EC-4621-BF88-E3B0DA8E6557} = {1873A545-87AA-4C22-BA1A-8A6602F65749} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {2483F58F-A8D6-4FFE-A3C1-10F3A36DBE69} diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Uwp/Strings_PlatformServices.Designer.cs b/Rx.NET/Source/src/System.Reactive.Integration.Uwp/Strings_PlatformServices.Designer.cs new file mode 100644 index 000000000..21c2e42dd --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.Uwp/Strings_PlatformServices.Designer.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace System.Reactive.Integration.Uwp { + using System; + using System.Reflection; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Strings_PlatformServices { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Strings_PlatformServices() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Reactive.Integration.Uwp.Strings_PlatformServices", typeof(Strings_PlatformServices).GetTypeInfo().Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to The WinRT thread pool doesn't support creating periodic timers with a period below 1 millisecond.. + /// + internal static string WINRT_NO_SUB1MS_TIMERS { + get { + return ResourceManager.GetString("WINRT_NO_SUB1MS_TIMERS", resourceCulture); + } + } + } +} diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Uwp/Strings_PlatformServices.resx b/Rx.NET/Source/src/System.Reactive.Integration.Uwp/Strings_PlatformServices.resx new file mode 100644 index 000000000..f796d0aee --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.Uwp/Strings_PlatformServices.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + The WinRT thread pool doesn't support creating periodic timers with a period below 1 millisecond. + + \ No newline at end of file diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Uwp/Stubs.cs b/Rx.NET/Source/src/System.Reactive.Integration.Uwp/Stubs.cs new file mode 100644 index 000000000..62b69c6d2 --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.Uwp/Stubs.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT License. +// See the LICENSE file in the project root for more information. + +namespace System.Reactive.Integration.Uwp +{ + internal static class Stubs + { + public static readonly Func I = static _ => _; + } +} + diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Uwp/System.Reactive.Integration.Uwp.csproj b/Rx.NET/Source/src/System.Reactive.Integration.Uwp/System.Reactive.Integration.Uwp.csproj new file mode 100644 index 000000000..17b2a108d --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.Uwp/System.Reactive.Integration.Uwp.csproj @@ -0,0 +1,56 @@ + + + + + uap10.0.18362 + + Rx;Reactive;Extensions;Observable;LINQ;Events;Windows Forms + Reactive Extensions (Rx) for .NET + + readme.md + + + + enable + + + + + + + + + + + + + + + + + $([MSBuild]::ValueOrDefault('%(Filename)', '').Replace('$(ExtrasDefaultDesignerFileSuffix)', '.resx')) + + + + + + True + True + Strings_PlatformServices.resx + + + + + + ResXFileCodeGenerator + Strings_PlatformServices.Designer.cs + + + + + + + diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Uwp/ThreadPoolTimerExtensions.cs b/Rx.NET/Source/src/System.Reactive.Integration.Uwp/ThreadPoolTimerExtensions.cs new file mode 100644 index 000000000..a00cbf618 --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.Uwp/ThreadPoolTimerExtensions.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT License. +// See the LICENSE file in the project root for more information. + +using System.Reactive.Disposables; + +using Windows.System.Threading; + +namespace System.Reactive.Integration.Uwp +{ + internal static class ThreadPoolTimerExtensions + { + public static IDisposable AsDisposable(this ThreadPoolTimer threadPoolTimer) + { + return Disposable.Create(threadPoolTimer, static t => t!.Cancel()); + } + } +} diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Uwp/UwpThreadPoolScheduler.cs b/Rx.NET/Source/src/System.Reactive.Integration.Uwp/UwpThreadPoolScheduler.cs new file mode 100644 index 000000000..68d47813c --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.Uwp/UwpThreadPoolScheduler.cs @@ -0,0 +1,184 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT License. +// See the LICENSE file in the project root for more information. + +using System.Reactive.Concurrency; +using System.Reactive.Integration.WindowsRuntime; +using Windows.System.Threading; + +namespace System.Reactive.Integration.Uwp +{ + /// + /// Schedules units of work on the Windows Runtime thread pool. + /// + /// Singleton instance of this type exposed through this static property. + [CLSCompliant(false)] + public sealed class UwpThreadPoolScheduler : LocalScheduler, ISchedulerPeriodic + { + private static readonly Lazy LazyDefault = new(static () => new UwpThreadPoolScheduler()); + + /// + /// Constructs a ThreadPoolScheduler that schedules units of work on the Windows ThreadPool. + /// + public UwpThreadPoolScheduler() + { + } + + /// + /// Constructs a ThreadPoolScheduler that schedules units of work on the Windows ThreadPool with the given priority. + /// + /// Priority for scheduled units of work. + public UwpThreadPoolScheduler(WorkItemPriority priority) + { + Priority = priority; + Options = WorkItemOptions.None; + } + + /// + /// Constructs a ThreadPoolScheduler that schedules units of work on the Windows ThreadPool with the given priority. + /// + /// Priority for scheduled units of work. + /// Options that configure how work is scheduled. + public UwpThreadPoolScheduler(WorkItemPriority priority, WorkItemOptions options) + { + Priority = priority; + Options = options; + } + + /// + /// Gets the singleton instance of the Windows Runtime thread pool scheduler. + /// + public static UwpThreadPoolScheduler Instance => LazyDefault.Value; + + /// + /// Gets the priority at which work is scheduled. + /// + public WorkItemPriority Priority { get; } + + /// + /// Gets the options that configure how work is scheduled. + /// + public WorkItemOptions Options { get; } + + /// + /// Schedules an action to be executed. + /// + /// The type of the state passed to the scheduled action. + /// State passed to the action to be executed. + /// Action to be executed. + /// The disposable object used to cancel the scheduled action (best effort). + /// is null. + public override IDisposable Schedule(TState state, Func action) + { + if (action == null) + throw new ArgumentNullException(nameof(action)); + + var userWorkItem = new UserWorkItem(this, state, action); + + var res = ThreadPool.RunAsync( + iaa => userWorkItem.Run(), + Priority, + Options); + + userWorkItem.CancelQueueDisposable = res.AsDisposable(); + + return userWorkItem; + } + + /// + /// Schedules an action to be executed after dueTime, using a Windows.System.Threading.ThreadPoolTimer object. + /// + /// The type of the state passed to the scheduled action. + /// State passed to the action to be executed. + /// Action to be executed. + /// Relative time after which to execute the action. + /// The disposable object used to cancel the scheduled action (best effort). + /// is null. + public override IDisposable Schedule(TState state, TimeSpan dueTime, Func action) + { + if (action == null) + throw new ArgumentNullException(nameof(action)); + + var dt = Scheduler.Normalize(dueTime); + + if (dt.Ticks == 0) + { + return Schedule(state, action); + } + + return ScheduleSlow(state, dt, action); + } + + private IDisposable ScheduleSlow(TState state, TimeSpan dueTime, Func action) + { + var userWorkItem = new UserWorkItem(this, state, action); + + var res = ThreadPoolTimer.CreateTimer( + tpt => userWorkItem.Run(), + dueTime); + + userWorkItem.CancelQueueDisposable = res.AsDisposable(); + + return userWorkItem; + } + + /// + /// Schedules a periodic piece of work, using a Windows.System.Threading.ThreadPoolTimer object. + /// + /// The type of the state passed to the scheduled action. + /// Initial state passed to the action upon the first iteration. + /// Period for running the work periodically. + /// Action to be executed, potentially updating the state. + /// The disposable object used to cancel the scheduled recurring action (best effort). + /// is null. + /// is less than one millisecond. + public IDisposable SchedulePeriodic(TState state, TimeSpan period, Func action) + { + // + // The WinRT thread pool is based on the Win32 thread pool and cannot handle + // sub-1ms resolution. When passing a lower period, we get single-shot + // timer behavior instead. See MSDN documentation for CreatePeriodicTimer + // for more information. + // + if (period < TimeSpan.FromMilliseconds(1)) + throw new ArgumentOutOfRangeException(nameof(period), Strings_PlatformServices.WINRT_NO_SUB1MS_TIMERS); + if (action == null) + throw new ArgumentNullException(nameof(action)); + + return new PeriodicallyScheduledWorkItem(state, period, action); + } + + private sealed class PeriodicallyScheduledWorkItem : IDisposable + { + private TState _state; + private Func _action; + + private readonly ThreadPoolTimer _timer; + private readonly AsyncLock _gate = new(); + + public PeriodicallyScheduledWorkItem(TState state, TimeSpan period, Func action) + { + _state = state; + _action = action; + + _timer = ThreadPoolTimer.CreatePeriodicTimer( + Tick, + period); + } + + private void Tick(ThreadPoolTimer timer) + { + _gate.Wait( + this, + static @this => @this._state = @this._action(@this._state)); + } + + public void Dispose() + { + _timer.Cancel(); + _gate.Dispose(); + _action = Stubs.I; + } + } + } +} diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Uwp/build/NuGet.Readme.md b/Rx.NET/Source/src/System.Reactive.Integration.Uwp/build/NuGet.Readme.md new file mode 100644 index 000000000..3ebfd13a5 --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.Uwp/build/NuGet.Readme.md @@ -0,0 +1,43 @@ +# UWP Support for Rx.NET (Reactive Extensions for .NET) + +This library provides UWP (Universal Windows Platform) support for the Reactive Extensions for .NET (Rx.NET). + +See the main Rx.NET package at https://www.nuget.org/packages/System.Reactive for more information about Rx.NET. + +## Rx.NET and UI Frameworks + +Up as far as Rx.NET v6.0, UI framework support has been built directly into the main `System.Reactive` package. +Unfortunately, this has caused problems since support for WPF and Windows Forms was added in .NET Core 3.1. +Because .NET Core 3.1, and all subsequent versions of .NET have supported cross-platform use, WPF and Windows +Forms are not universally available. Rx.NET used to make WPF and Windows Forms support if you targetted a +sufficiently recent version of Windows in your application TFM. But this turns out to cause problems in +some deployment models, adding as much as 90MB to the deployable size of an application. + +Consequently, starting in Rx.NET v7.0 we are moving all UI-framework-specific types, and also platform-specific +types out into separate packages. + +## Features + +This package defines one public type, `UwpThreadPoolScheduler`. It provides a replacement for deprecated functionality on the +`ThreadPoolScheduler` in the `uap10.0.18362` target of `System.Reactive`. In a future version of Rx.NET, the UWP-specific +target will be removed the main `System.Reactive` package, at which point UWP applications will use the `netstandard2.0` +target, and will get only the common `ThreadPoolScheduler` functionality available on all platforms. + +The specialized `ThreadPoolScheduler` currently still available in the `uap10.0.18362` target of `System.Reactive` is +very nearly the same as the common one. It has some extra properties and constructors providing access to some features +specific to the `Windows.System.Threading` thread pool (which is available only on UWP). It allows the use of +`WorkItemPriority` and `WorkItemOptions`. These features are now deprecated on the `ThreadPoolScheduler` in the +`uap10.0.18362` target of `System.Reactive`, making its remaining non-deprecated surface area the same as in +other targets. + +Applications still needing access to the UWP-specific functionality can switch to the `UwpThreadPoolScheduler` +in this library. + + +## Windows Runtime Support + +The `uap10.0.18362` target of `System.Reactive` also offers support for some Windows Runtime types, such as `IAsyncOperation`, +that are often used in UWP applications. Those types are also available outside of UWP, so they are also available in +the Windows-specific .NET target, but they have also been deprecated, as part of the drive to remove all platform- and +UI-framework-specific code from `System.Reactive`. You can find support for those in the `System.Reactive.Integration.WindowsRuntime` +NuGet package. \ No newline at end of file diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsForms/ControlScheduler.cs b/Rx.NET/Source/src/System.Reactive.Integration.WindowsForms/ControlScheduler.cs new file mode 100644 index 000000000..9af2ac0e4 --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.WindowsForms/ControlScheduler.cs @@ -0,0 +1,213 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT License. +// See the LICENSE file in the project root for more information. + +using System.Reactive.Concurrency; +using System.Reactive.Disposables; +using System.Threading; +using System.Windows.Forms; + +namespace System.Reactive.Integration.WindowsForms +{ + /// + /// Represents an object that schedules units of work on the message loop associated with a Windows Forms control. + /// + public class ControlScheduler : LocalScheduler, ISchedulerPeriodic + { + private readonly Control _control; + + /// + /// Constructs a ControlScheduler that schedules units of work on the message loop associated with the specified Windows Forms control. + /// + /// Windows Forms control to get the message loop from. + /// is null. + /// + /// This scheduler type is typically used indirectly through the and method overloads that take a Windows Forms control. + /// + public ControlScheduler(Control control) + { + _control = control ?? throw new ArgumentNullException(nameof(control)); + } + + /// + /// Gets the control associated with the ControlScheduler. + /// + public Control Control => _control; + + /// + /// Schedules an action to be executed on the message loop associated with the control. + /// + /// The type of the state passed to the scheduled action. + /// State passed to the action to be executed. + /// Action to be executed. + /// The disposable object used to cancel the scheduled action (best effort). + /// is null. + public override IDisposable Schedule(TState state, Func action) + { + if (action == null) + { + throw new ArgumentNullException(nameof(action)); + } + + if (_control.IsDisposed) + { + return Disposable.Empty; + } + + var d = new SingleAssignmentDisposable(); + + _control.BeginInvoke(new Action(() => + { + if (!_control.IsDisposed && !d.IsDisposed) + { + d.Disposable = action(this, state); + } + })); + + return d; + } + + /// + /// Schedules an action to be executed after dueTime on the message loop associated with the control, using a Windows Forms Timer object. + /// + /// The type of the state passed to the scheduled action. + /// State passed to the action to be executed. + /// Action to be executed. + /// Relative time after which to execute the action. + /// The disposable object used to cancel the scheduled action (best effort). + /// is null. + public override IDisposable Schedule(TState state, TimeSpan dueTime, Func action) + { + if (action == null) + { + throw new ArgumentNullException(nameof(action)); + } + + var dt = Scheduler.Normalize(dueTime); + if (dt.Ticks == 0) + { + return Schedule(state, action); + } + + var createTimer = new Func((scheduler1, state1) => + { + var d = new MultipleAssignmentDisposable(); + + var timer = new System.Windows.Forms.Timer(); + + timer.Tick += (s, e) => + { + var t = Interlocked.Exchange(ref timer, null); + if (t != null) + { + try + { + if (!_control.IsDisposed && !d.IsDisposed) + { + d.Disposable = action(scheduler1, state1); + } + } + finally + { + t.Stop(); + action = static (s, t) => Disposable.Empty; + } + } + }; + + timer.Interval = (int)dt.TotalMilliseconds; + timer.Start(); + + d.Disposable = Disposable.Create(() => + { + var t = Interlocked.Exchange(ref timer, null); + if (t != null) + { + t.Stop(); + action = static (s, t) => Disposable.Empty; + } + }); + + return d; + }); + + // + // This check is critical. When creating and enabling a Timer object on another thread than + // the UI thread, it won't fire. + // + if (_control.InvokeRequired) + { + return Schedule(state, createTimer); + } + else + { + return createTimer(this, state); + } + } + + /// + /// Schedules a periodic piece of work on the message loop associated with the control, using a Windows Forms Timer object. + /// + /// The type of the state passed to the scheduled action. + /// Initial state passed to the action upon the first iteration. + /// Period for running the work periodically. + /// Action to be executed, potentially updating the state. + /// The disposable object used to cancel the scheduled recurring action (best effort). + /// is null. + /// is less than one millisecond. + public IDisposable SchedulePeriodic(TState state, TimeSpan period, Func action) + { + // + // Threshold derived from Interval property setter in ndp\fx\src\winforms\managed\system\winforms\Timer.cs. + // + if (period.TotalMilliseconds < 1) + { + throw new ArgumentOutOfRangeException(nameof(period)); + } + + if (action == null) + { + throw new ArgumentNullException(nameof(action)); + } + + var createTimer = new Func((scheduler1, state1) => + { + var timer = new System.Windows.Forms.Timer(); + + timer.Tick += (s, e) => + { + if (!_control.IsDisposed) + { + state1 = action(state1); + } + }; + + timer.Interval = (int)period.TotalMilliseconds; + timer.Start(); + + return Disposable.Create(() => + { + var t = Interlocked.Exchange(ref timer, null); + if (t != null) + { + t.Stop(); + action = static _ => _; + } + }); + }); + + // + // This check is critical. When creating and enabling a Timer object on another thread than + // the UI thread, it won't fire. + // + if (_control.InvokeRequired) + { + return Schedule(state, createTimer); + } + else + { + return createTimer(this, state); + } + } + } +} diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsForms/System.Reactive.Integration.WindowsForms.csproj b/Rx.NET/Source/src/System.Reactive.Integration.WindowsForms/System.Reactive.Integration.WindowsForms.csproj new file mode 100644 index 000000000..8f57f238c --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.WindowsForms/System.Reactive.Integration.WindowsForms.csproj @@ -0,0 +1,29 @@ + + + + net472;net6.0-windows + true + + Rx;Reactive;Extensions;Observable;LINQ;Events;Windows Forms + Reactive Extensions (Rx) for .NET + + readme.md + + + + enable + + + + + + + + + + + + + + + diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsForms/System.Reactive.Linq/WindowsFormsControlObservable.cs b/Rx.NET/Source/src/System.Reactive.Integration.WindowsForms/System.Reactive.Linq/WindowsFormsControlObservable.cs new file mode 100644 index 000000000..70a31752c --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.WindowsForms/System.Reactive.Linq/WindowsFormsControlObservable.cs @@ -0,0 +1,73 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT License. +// See the LICENSE file in the project root for more information. + +using System.Windows.Forms; + +using ControlScheduler = System.Reactive.Integration.WindowsForms.ControlScheduler; +using Synchronization = System.Reactive.Concurrency.Synchronization; + +namespace System.Reactive.Linq +{ + /// + /// Provides a set of static methods for subscribing to IObservables using Windows Forms controls. + /// + /// + /// + /// This replaces the obsolete System.Reactive.Linq.ControlObservable class in + /// System.Reactive. + /// + /// + public static class WindowsFormsControlObservable + { + /// + /// Wraps the source sequence in order to run its subscription and unsubscription logic on the Windows Forms message loop associated with the specified control. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// Windows Forms control whose associated message loop is used to perform subscription and unsubscription actions on. + /// The source sequence whose subscriptions and unsubscriptions happen on the Windows Forms message loop associated with the specified control. + /// or is null. + /// + /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the specified control. + /// In order to invoke observer callbacks on the specified control, e.g. to render results in a control, use . + /// + public static IObservable SubscribeOnWindowFormsControl(this IObservable source, Control control) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (control == null) + { + throw new ArgumentNullException(nameof(control)); + } + + return Synchronization.SubscribeOn(source, new ControlScheduler(control)); + } + + /// + /// Wraps the source sequence in order to run its observer callbacks on the Windows Forms message loop associated with the specified control. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// Windows Forms control whose associated message loop is used to notify observers on. + /// The source sequence whose observations happen on the Windows Forms message loop associated with the specified control. + /// or is null. + public static IObservable ObserveOnWindowsFormsControl(this IObservable source, Control control) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (control == null) + { + throw new ArgumentNullException(nameof(control)); + } + + return Synchronization.ObserveOn(source, new ControlScheduler(control)); + } + } +} diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsForms/build/NuGet.Readme.md b/Rx.NET/Source/src/System.Reactive.Integration.WindowsForms/build/NuGet.Readme.md new file mode 100644 index 000000000..84d58409b --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.WindowsForms/build/NuGet.Readme.md @@ -0,0 +1,26 @@ +# Windows Forms Support for Rx.NET (Reactive Extensions for .NET) + +This library provides Windows Forms support for the Reactive Extensions for .NET (Rx.NET). + +See the main Rx.NET package at https://www.nuget.org/packages/System.Reactive for more information about Rx.NET. + +## Rx.NET and UI Frameworks + +Up as far as Rx.NET v6.0, UI framework support has been built directly into the main `System.Reactive` package. +Unfortunately, this has caused problems since support for WPF and Windows Forms was added in .NET Core 3.1. +Because .NET Core 3.1, and all subsequent versions of .NET have supported cross-platform use, WPF and Windows +Forms are not universally available. Rx.NET used to make WPF and Windows Forms support if you targetted a +sufficiently recent version of Windows in your application TFM. But this turns out to cause problems in +some deployment models, adding as much as 90MB to the deployable size of an application. + +Consequently, starting in Rx.NET v7.0 we are moving all UI-framework-specific types, and also platform-specific +types out into separate packages. + +## Features + +This package provides replacements for two deprecated types in `System.Reactive`: + +|Type in `System.Reactive` | Replacement | Purpose | +|---|---|---| +|`ControlScheduler` (in `System.Reactive.Concurrency`) | `ControlScheduler` (in `System.Reactive.Integration.WindowsForms`) | Provides a scheduler that schedules work on the UI thread of a Windows Forms application. | +|`ControlObservable` (in `System.Reactive.Linq`) | `WindowsFormsControlObservable` (in `System.Reactive.Linq`) | Provides a set of extension methods for scheduling work on the UI thread of a Windows Forms application. | diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/AsyncInfoExtensions.cs b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/AsyncInfoExtensions.cs new file mode 100644 index 000000000..dbd6d8531 --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/AsyncInfoExtensions.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT License. +// See the LICENSE file in the project root for more information. + +using System.Reactive.Disposables; +using Windows.Foundation; + +namespace System.Reactive.Integration.WindowsRuntime +{ + internal static class AsyncInfoExtensions + { + public static IDisposable AsDisposable(this IAsyncInfo asyncInfo) + { + return Disposable.Create(asyncInfo, static i => i!.Cancel()); + } + } +} diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/AsyncInfoObservableExtensions.cs b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/AsyncInfoObservableExtensions.cs new file mode 100644 index 000000000..013065c03 --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/AsyncInfoObservableExtensions.cs @@ -0,0 +1,276 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT License. +// See the LICENSE file in the project root for more information. + +using System.Reactive.Linq; +using Windows.Foundation; + +namespace System.Reactive.Integration.WindowsRuntime +{ + /// + /// Provides conversions from Windows Runtime asynchronous actions and operations to observable sequences. + /// + [CLSCompliant(false)] + public static class AsyncInfoObservableExtensions + { + #region IAsyncAction and IAsyncActionWithProgress + + /// + /// Converts a Windows Runtime asynchronous action to an observable sequence. + /// Each observer subscribed to the resulting observable sequence will be notified about the action's successful or exceptional completion. + /// + /// Asynchronous action to convert. + /// An observable sequence that produces a unit value when the asynchronous action completes, or propagates the exception produced by the asynchronous action. + /// is null. + public static IObservable ToObservable(this IAsyncAction source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return new AsyncInfoToObservableBridge( + source, + static (iai, a) => ((IAsyncAction)iai).Completed += new AsyncActionCompletedHandler((iaa, status) => a(iaa, status)), + iai => Unit.Default, + onProgress: null, + progress: null, + multiValue: false + ); + } + + /// + /// Converts a Windows Runtime asynchronous action to an observable sequence, ignoring its progress notifications. + /// Each observer subscribed to the resulting observable sequence will be notified about the action's successful or exceptional completion. + /// + /// The type of the reported progress objects, which get ignored by this conversion. + /// Asynchronous action to convert. + /// An observable sequence that produces a unit value when the asynchronous action completes, or propagates the exception produced by the asynchronous action. + /// is null. + public static IObservable ToObservable(this IAsyncActionWithProgress source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return source.ToObservable_(null); + } + + /// + /// Converts a Windows Runtime asynchronous action to an observable sequence, reporting its progress through the supplied progress object. + /// Each observer subscribed to the resulting observable sequence will be notified about the action's successful or exceptional completion. + /// + /// The type of the reported progress objects. + /// Asynchronous action to convert. + /// Progress object to receive progress notifications on. + /// An observable sequence that produces a unit value when the asynchronous action completes, or propagates the exception produced by the asynchronous action. + /// or is null. + public static IObservable ToObservable(this IAsyncActionWithProgress source, IProgress progress) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (progress == null) + { + throw new ArgumentNullException(nameof(progress)); + } + + return source.ToObservable_(progress); + } + + /// + /// Converts a Windows Runtime asynchronous action to an observable sequence reporting its progress. + /// Each observer subscribed to the resulting observable sequence will be notified about the action's successful or exceptional completion. + /// + /// The type of the reported progress objects. + /// Asynchronous action to convert. + /// An observable sequence that produces progress values from the asynchronous action and notifies observers about the action's completion. + /// is null. + public static IObservable ToObservableProgress(this IAsyncActionWithProgress source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return Observable.Create(observer => + { + var progress = observer.ToProgress(); + var src = source.ToObservable_(progress); + return src.Subscribe(static _ => { }, observer.OnError, observer.OnCompleted); + }); + } + + private static IObservable ToObservable_(this IAsyncActionWithProgress source, IProgress? progress) + { + return new AsyncInfoToObservableBridge( + source, + static (iai, a) => ((IAsyncActionWithProgress)iai).Completed += new AsyncActionWithProgressCompletedHandler((iaa, status) => a(iaa, status)), + iai => Unit.Default, + static (iai, a) => ((IAsyncActionWithProgress)iai).Progress += new AsyncActionProgressHandler((iap, p) => a(iap, p)), + progress, + multiValue: false + ); + } + + #endregion + + #region IAsyncOperation and IAsyncOperationWithProgress + + /// + /// Converts a Windows Runtime asynchronous operation to an observable sequence reporting its result. + /// Each observer subscribed to the resulting observable sequence will be notified about the operation's single result and its successful exceptional completion. + /// + /// The type of the asynchronous operation's result. + /// Asynchronous operation to convert. + /// An observable sequence that notifies observers about the asynchronous operation's result value and completion. + /// is null. + public static IObservable ToObservable(this IAsyncOperation source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return new AsyncInfoToObservableBridge( + source, + static (iai, a) => ((IAsyncOperation)iai).Completed += new AsyncOperationCompletedHandler((iao, status) => a(iao, status)), + static iai => ((IAsyncOperation)iai).GetResults(), + onProgress: null, + progress: null, + multiValue: false + ); + } + + /// + /// Converts a Windows Runtime asynchronous operation to an observable sequence reporting its result but ignoring its progress notifications. + /// Each observer subscribed to the resulting observable sequence will be notified about the operations's single result and its successful or exceptional completion. + /// + /// The type of the asynchronous operation's result. + /// The type of the reported progress objects, which get ignored by this conversion. + /// Asynchronous action to convert. + /// An observable sequence that notifies observers about the asynchronous operation's result value and completion. + /// is null. + public static IObservable ToObservable(this IAsyncOperationWithProgress source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return source.ToObservable_(null, false); + } + + /// + /// Converts a Windows Runtime asynchronous operation to an observable sequence reporting its result and reporting its progress through the supplied progress object. + /// Each observer subscribed to the resulting observable sequence will be notified about the operations's single result and its successful or exceptional completion. + /// + /// The type of the asynchronous operation's result. + /// The type of the reported progress objects. + /// Asynchronous action to convert. + /// Progress object to receive progress notifications on. + /// An observable sequence that notifies observers about the asynchronous operation's result value and completion. + /// or is null. + public static IObservable ToObservable(this IAsyncOperationWithProgress source, IProgress progress) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (progress == null) + { + throw new ArgumentNullException(nameof(progress)); + } + + return source.ToObservable_(progress, false); + } + + /// + /// Converts a Windows Runtime asynchronous operation to an observable sequence reporting its progress but ignoring its result value. + /// Each observer subscribed to the resulting observable sequence will be notified about the action's successful or exceptional completion. + /// + /// The type of the asynchronous operation's result, which gets ignored by this conversion. + /// The type of the reported progress objects. + /// Asynchronous action to convert. + /// An observable sequence that produces progress values from the asynchronous operation and notifies observers about the operations's completion. + /// is null. + public static IObservable ToObservableProgress(this IAsyncOperationWithProgress source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return Observable.Create(observer => + { + var progress = observer.ToProgress(); + var src = source.ToObservable_(progress, false); + return src.Subscribe(static _ => { }, observer.OnError, observer.OnCompleted); + }); + } + + /// + /// Converts a Windows Runtime asynchronous operation to an observable sequence by retrieving the operation's results whenever progress is reported and when the operation completes. + /// Each observer subscribed to the resulting observable sequence will be notified about the action's successful or exceptional completion. + /// + /// The type of the asynchronous operation's result. + /// The type of the reported progress objects, which are used internally in the conversion but aren't exposed. + /// Asynchronous operation to convert. + /// An observable sequence that notifies observers about the asynchronous operation's (incremental) result value(s) and completion. + /// This conversion can be used with Windows Runtime APIs that support incremental retrieval of results during an asynchronous operation's execution. + /// is null. + public static IObservable ToObservableMultiple(this IAsyncOperationWithProgress source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return source.ToObservable_(null, true); + } + + /// + /// Converts a Windows Runtime asynchronous operation to an observable sequence by retrieving the operation's results whenever progress is reported and when the operation completes. The operation's progress is reported through the supplied progress object. + /// Each observer subscribed to the resulting observable sequence will be notified about the action's successful or exceptional completion. + /// + /// The type of the asynchronous operation's result. + /// The type of the reported progress objects. + /// Asynchronous operation to convert. + /// Progress object to receive progress notifications on. + /// An observable sequence that notifies observers about the asynchronous operation's (incremental) result value(s) and completion. + /// This conversion can be used with Windows Runtime APIs that support incremental retrieval of results during an asynchronous operation's execution. + /// or is null. + public static IObservable ToObservableMultiple(this IAsyncOperationWithProgress source, IProgress progress) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (progress == null) + { + throw new ArgumentNullException(nameof(progress)); + } + + return source.ToObservable_(progress, true); + } + + private static IObservable ToObservable_(this IAsyncOperationWithProgress source, IProgress? progress, bool supportsMultiple) + { + return new AsyncInfoToObservableBridge( + source, + static (iai, a) => ((IAsyncOperationWithProgress)iai).Completed += new AsyncOperationWithProgressCompletedHandler((iao, status) => a(iao, status)), + iai => ((IAsyncOperationWithProgress)iai).GetResults(), + static (iai, a) => ((IAsyncOperationWithProgress)iai).Progress += new AsyncOperationProgressHandler((iap, p) => a(iap, p)), + progress, + supportsMultiple + ); + } + + #endregion + } +} diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/AsyncInfoToObservableBridge.cs b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/AsyncInfoToObservableBridge.cs new file mode 100644 index 000000000..e757b738e --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/AsyncInfoToObservableBridge.cs @@ -0,0 +1,108 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT License. +// See the LICENSE file in the project root for more information. + +using System.Reactive.Subjects; +using Windows.Foundation; + +namespace System.Reactive.Integration.WindowsRuntime +{ + internal sealed class AsyncInfoToObservableBridge : ObservableBase + { + private readonly Action> _onCompleted; + private readonly Func _getResult; + private readonly AsyncSubject _subject; + + public AsyncInfoToObservableBridge(IAsyncInfo info, Action> onCompleted, Func getResult, Action>? onProgress, IProgress? progress, bool multiValue) + { + _onCompleted = onCompleted; + _getResult = getResult; + + _subject = new AsyncSubject(); + + onProgress?.Invoke(info, (iai, p) => + { + if (multiValue && getResult != null) + { + _subject.OnNext(getResult(iai)); + } + + progress?.Report(p); + }); + + Done(info, info.Status, true); + } + + private void Done(IAsyncInfo info, AsyncStatus status, bool initial) + { + var error = default(Exception); + var result = default(TResult); + + // + // Initial interactions with the IAsyncInfo object. Those could fail, which indicates + // a rogue implementation. Failure is just propagated out. + // + switch (status) + { + case AsyncStatus.Error: + error = info.ErrorCode; + if (error == null) + { + throw new InvalidOperationException("The asynchronous operation failed with a null error code."); + } + + break; + case AsyncStatus.Canceled: + error = new OperationCanceledException(); + break; + case AsyncStatus.Completed: + if (_getResult != null) + { + result = _getResult(info); + } + + break; + default: + if (!initial) + { + throw new InvalidOperationException("The asynchronous operation completed unexpectedly."); + } + + _onCompleted(info, (iai, s) => Done(iai, s, false)); + return; + } + + // + // Close as early as possible, before running continuations which could fail. In case of + // failure above, we don't close out the object in order to allow for debugging of the + // rogue implementation without losing state prematurely. Notice _getResult is merely + // an indirect call to the appropriate GetResults method, which is not supposed to throw. + // Instead, an Error status should be returned. + // + info.Close(); + + // + // Now we run the continuations, which could take a long time. Failure here is catastrophic + // and under control of the upstream subscriber. + // + if (error != null) + { + _subject.OnError(error); + } + else + { + if (_getResult != null) + { + _subject.OnNext(result!); // NB: Has been assigned in switch statement above. + } + + _subject.OnCompleted(); + } + } + + protected override IDisposable SubscribeCore(IObserver observer) + { + return _subject.Subscribe(observer); + } + } +} diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/CoreDispatcherScheduler.cs b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/CoreDispatcherScheduler.cs new file mode 100644 index 000000000..dcea221c9 --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/CoreDispatcherScheduler.cs @@ -0,0 +1,266 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT License. +// See the LICENSE file in the project root for more information. + +using System.Reactive.Disposables; +using System.Reactive.Concurrency; +using System.Runtime.ExceptionServices; +using System.Threading; +using Windows.System; +using Windows.UI.Core; + +namespace System.Reactive.Integration.WindowsRuntime +{ + /// + /// Schedules units of work on a . + /// + /// + /// This scheduler type is typically used indirectly through the extension methods defined by + /// . + /// + [CLSCompliant(false)] + public sealed class CoreDispatcherScheduler : LocalScheduler, ISchedulerPeriodic + { + /// + /// Constructs a that schedules units of work on the given . + /// + /// Dispatcher to schedule work on. + /// is null. + public CoreDispatcherScheduler(CoreDispatcher dispatcher) + { + Dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher)); + Priority = CoreDispatcherPriority.Normal; + } + + /// + /// Constructs a that schedules units of work on the given with the given priority. + /// + /// Dispatcher to schedule work on. + /// Priority for scheduled units of work. + /// is null. + public CoreDispatcherScheduler(CoreDispatcher dispatcher, CoreDispatcherPriority priority) + { + Dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher)); + Priority = priority; + } + + /// + /// Gets the scheduler that schedules work on the associated with the current Window. + /// + public static CoreDispatcherScheduler Current + { + get + { + var window = CoreWindow.GetForCurrentThread() + ?? throw new InvalidOperationException(Strings_WindowsThreading.NO_WINDOW_CURRENT); + return new CoreDispatcherScheduler(window.Dispatcher); + } + } + + /// + /// Gets the associated with the . + /// + public CoreDispatcher Dispatcher { get; } + + private DispatcherQueue? _dispatcherQueue; + + /// + /// Gets the priority at which work is scheduled. + /// + public CoreDispatcherPriority Priority { get; } + + /// + /// Schedules an action to be executed on the dispatcher. + /// + /// The type of the state passed to the scheduled action. + /// State passed to the action to be executed. + /// Action to be executed. + /// The disposable object used to cancel the scheduled action (best effort). + /// is null. + public override IDisposable Schedule(TState state, Func action) + { + if (action == null) + { + throw new ArgumentNullException(nameof(action)); + } + + var d = new SingleAssignmentDisposable(); + + var res = Dispatcher.RunAsync(Priority, () => + { + if (!d.IsDisposed) + { + try + { + d.Disposable = action(this, state); + } + catch (Exception ex) + { + // + // Work-around for the behavior of throwing from RunAsync not propagating + // the exception to the Application.UnhandledException event (as of W8RP) + // as our users have come to expect from previous XAML stacks using Rx. + // + // If we wouldn't do this, there'd be an observable behavioral difference + // between scheduling with TimeSpan.Zero or using this overload. + // + // For scheduler implementation guidance rules, see TaskPoolScheduler.cs + // in System.Reactive.PlatformServices\Reactive\Concurrency. + // + + var timer = CreateDispatcherQueue().CreateTimer(); + timer.Interval = TimeSpan.Zero; + + timer.Tick += (o, e) => + { + timer.Stop(); + ExceptionDispatchInfo.Capture(ex).Throw(); + }; + + timer.Start(); + } + } + }); + + return StableCompositeDisposable.Create( + d, + res.AsDisposable() + ); + } + + private DispatcherQueue CreateDispatcherQueue() + { + if(_dispatcherQueue != null) + { + return _dispatcherQueue; + } + + if(Dispatcher.HasThreadAccess) + { + _dispatcherQueue = DispatcherQueue.GetForCurrentThread(); + return _dispatcherQueue; + } + + // We're on a different thread, get it from the right one + Dispatcher.RunAsync(CoreDispatcherPriority.High, () => + { + _dispatcherQueue = DispatcherQueue.GetForCurrentThread(); + }).GetAwaiter().GetResult(); // This is a synchronous call and we need the result to proceed + + return _dispatcherQueue!; + } + + /// + /// Schedules an action to be executed after on the dispatcher, using a object. + /// + /// The type of the state passed to the scheduled action. + /// State passed to the action to be executed. + /// Action to be executed. + /// Relative time after which to execute the action. + /// The disposable object used to cancel the scheduled action (best effort). + /// is null. + public override IDisposable Schedule(TState state, TimeSpan dueTime, Func action) + { + if (action == null) + { + throw new ArgumentNullException(nameof(action)); + } + + var dt = Scheduler.Normalize(dueTime); + if (dt.Ticks == 0) + { + return Schedule(state, action); + } + + return ScheduleSlow(state, dt, action); + } + + private IDisposable ScheduleSlow(TState state, TimeSpan dueTime, Func action) + { + var d = new MultipleAssignmentDisposable(); + + var timer = CreateDispatcherQueue().CreateTimer(); + + timer.Tick += (o, e) => + { + var t = Interlocked.Exchange(ref timer, null); + if (t != null) + { + try + { + d.Disposable = action(this, state); + } + finally + { + t.Stop(); + action = static (s, t) => Disposable.Empty; + } + } + }; + + timer.Interval = dueTime; + timer.Start(); + + d.Disposable = Disposable.Create(() => + { + var t = Interlocked.Exchange(ref timer, null); + if (t != null) + { + t.Stop(); + action = static (s, t) => Disposable.Empty; + } + }); + + return d; + } + + /// + /// Schedules a periodic piece of work on the dispatcher, using a object. + /// + /// The type of the state passed to the scheduled action. + /// Initial state passed to the action upon the first iteration. + /// Period for running the work periodically. + /// Action to be executed, potentially updating the state. + /// The disposable object used to cancel the scheduled recurring action (best effort). + /// is null. + /// is less than . + public IDisposable SchedulePeriodic(TState state, TimeSpan period, Func action) + { + // + // According to MSDN documentation, the default is TimeSpan.Zero, so that's definitely valid. + // Empirical observation - negative values seem to be normalized to TimeSpan.Zero, but let's not go there. + // + if (period < TimeSpan.Zero) + { + throw new ArgumentOutOfRangeException(nameof(period)); + } + + if (action == null) + { + throw new ArgumentNullException(nameof(action)); + } + + var timer = CreateDispatcherQueue().CreateTimer(); + + var state1 = state; + + timer.Tick += (o, e) => + { + state1 = action(state1); + }; + + timer.Interval = period; + timer.Start(); + + return Disposable.Create(() => + { + var t = Interlocked.Exchange(ref timer, null); + if (t != null) + { + t.Stop(); + action = static _ => _; + } + }); + } + } +} diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/EventPatternSource.cs b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/EventPatternSource.cs new file mode 100644 index 000000000..72424892e --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/EventPatternSource.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT License. +// See the LICENSE file in the project root for more information. + +using Windows.Foundation; + +namespace System.Reactive.Integration.WindowsRuntime +{ + internal sealed class EventPatternSource : EventPatternSourceBase, ITypedEventPatternSource + { + public EventPatternSource(IObservable> source, Action, /*object,*/ EventPattern> invokeHandler) + : base(source, invokeHandler) + { + } + + event TypedEventHandler ITypedEventPatternSource.OnNext + { + add + { + Add(value, (o, e) => value(o!, e)); + } + + remove + { + Remove(value); + } + } + } +} diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/ITypedEventPatternSource.cs b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/ITypedEventPatternSource.cs new file mode 100644 index 000000000..0f30732cd --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/ITypedEventPatternSource.cs @@ -0,0 +1,25 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT License. +// See the LICENSE file in the project root for more information. + +using Windows.Foundation; + +namespace System.Reactive.Integration.WindowsRuntime +{ + /// + /// Represents a data stream signaling its elements by means of a Windows Runtime + /// . + /// + /// Sender type. + /// Event arguments type. + [CLSCompliant(false)] + public interface ITypedEventPatternSource + { + /// + /// Event signaling the next element in the data stream. + /// +#pragma warning disable CA1003 // (Use generic EventHandler.) The use of the Windows.Foundation handler type is by design + event TypedEventHandler OnNext; +#pragma warning restore CA1003 + } +} diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/StableCompositeDisposable.cs b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/StableCompositeDisposable.cs new file mode 100644 index 000000000..d19ac4a27 --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/StableCompositeDisposable.cs @@ -0,0 +1,65 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT License. +// See the LICENSE file in the project root for more information. + +using System.Threading; + +namespace System.Reactive.Integration.WindowsRuntime +{ + /// + /// Represents a group of disposable resources that are disposed together. + /// + /// + /// This is a copy from System.Reactive and then trimmed down to provide just the one + /// feature + /// needs: access to the internal CreateTrusted method. I didn't want to make that a + /// public-facing part of the main library. (And InternalsVisibleTo effectively makes it + /// somewhat public: it means changes to the internals could break this library.) Better, then + /// to copy over just the functionality required in this library. + /// + internal abstract class StableUncheckedCompositeDisposable : IDisposable + { + /// + /// Creates a group of disposable resources that are disposed together + /// and without copying or checking for nulls inside the group. + /// + /// The array of disposables that is trusted + /// to not contain nulls and gives no need to defensively copy it. + /// Group of disposable resources that are disposed together. + internal static IDisposable CreateTrusted(params IDisposable[] disposables) + { + return new NAryTrustedArray(disposables); + } + + /// + /// Disposes all disposables in the group. + /// + public abstract void Dispose(); + + /// + /// A stable composite that doesn't do defensive copy of + /// the input disposable array nor checks it for null. + /// + private sealed class NAryTrustedArray : StableUncheckedCompositeDisposable + { + private IDisposable[]? _disposables; + + public NAryTrustedArray(IDisposable[] disposables) + { + Volatile.Write(ref _disposables, disposables); + } + + public override void Dispose() + { + var old = Interlocked.Exchange(ref _disposables, null); + if (old != null) + { + foreach (var d in old) + { + d.Dispose(); + } + } + } + } + } +} diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/Strings_WindowsThreading.Designer.cs b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/Strings_WindowsThreading.Designer.cs new file mode 100644 index 000000000..70038e8bb --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/Strings_WindowsThreading.Designer.cs @@ -0,0 +1,81 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace System.Reactive.Integration.WindowsRuntime { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Strings_WindowsThreading { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Strings_WindowsThreading() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Reactive.Integration.WindowsRuntime.Strings_WindowsThreading", typeof(Strings_WindowsThreading).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Disposables collection can not contain null values.. + /// + internal static string DISPOSABLES_CANT_CONTAIN_NULL { + get { + return ResourceManager.GetString("DISPOSABLES_CANT_CONTAIN_NULL", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No current Window object found to obtain a CoreDispatcher from.. + /// + internal static string NO_WINDOW_CURRENT { + get { + return ResourceManager.GetString("NO_WINDOW_CURRENT", resourceCulture); + } + } + } +} diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/Strings_WindowsThreading.resx b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/Strings_WindowsThreading.resx new file mode 100644 index 000000000..9070c521b --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/Strings_WindowsThreading.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Disposables collection can not contain null values. + + + No current Window object found to obtain a CoreDispatcher from. + + \ No newline at end of file diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Integration.WindowsRuntime.csproj b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Integration.WindowsRuntime.csproj new file mode 100644 index 000000000..b45c53dd5 --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Integration.WindowsRuntime.csproj @@ -0,0 +1,44 @@ + + + + + net6.0-windows10.0.17763.0;uap10.0.18362 + + Rx;Reactive;Extensions;Observable;LINQ;Events;Windows Forms + Reactive Extensions (Rx) for .NET + + readme.md + + + + enable + + + + + + + + + + + + + + + diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeAsyncInfoObservable.cs b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeAsyncInfoObservable.cs new file mode 100644 index 000000000..740a89289 --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeAsyncInfoObservable.cs @@ -0,0 +1,230 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT License. +// See the LICENSE file in the project root for more information. + +using System.Reactive.Integration.WindowsRuntime; +using System.Reactive.Threading.Tasks; +using System.Runtime.InteropServices.WindowsRuntime; +using System.Threading.Tasks; +using Windows.Foundation; + +namespace System.Reactive.Linq +{ + /// + /// Provides a set of extension methods to expose observable sequences as Windows Runtime + /// asynchronous actions and operations. + /// + [CLSCompliant(false)] + public static class WindowsRuntimeAsyncInfoObservable + { + #region IAsyncAction + + /// + /// Creates a Windows Runtime asynchronous action that represents the completion of the observable sequence. + /// Upon cancellation of the asynchronous action, the subscription to the source sequence will be disposed. + /// + /// The type of the elements in the source sequence. + /// Source sequence to expose as an asynchronous action. + /// Windows Runtime asynchronous action object representing the completion of the observable sequence. + /// is null. + public static IAsyncAction ToIAsyncAction(this IObservable source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return AsyncInfo.Run(ct => (Task)source.DefaultIfEmpty().ToTask(ct)); + } + + #region Progress + + /// + /// Creates a Windows Runtime asynchronous action that represents the completion of the observable sequence, reporting incremental progress for each element produced by the sequence. + /// Upon cancellation of the asynchronous action, the subscription to the source sequence will be disposed. + /// + /// The type of the elements in the source sequence. + /// Source sequence to expose as an asynchronous action. + /// Windows Runtime asynchronous action object representing the completion of the observable sequence, reporting incremental progress for each source sequence element. + /// is null. + public static IAsyncActionWithProgress ToIAsyncActionWithProgress(this IObservable source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return AsyncInfo.Run((ct, progress) => + { + var i = 0; + return source.Do(_ => progress.Report(i++)).DefaultIfEmpty().ToTask(ct); + }); + } + + /// + /// Creates a Windows Runtime asynchronous action that represents the completion of the observable sequence, using a selector function to map the source sequence on a progress reporting sequence. + /// Upon cancellation of the asynchronous action, the subscription to the source sequence will be disposed. + /// + /// The type of the elements in the source sequence. + /// The type of the elements in the progress sequence. + /// Source sequence to expose as an asynchronous action and to compute a progress sequence that gets reported through the asynchronous action. + /// Selector function to map the source sequence on a progress reporting sequence. + /// Windows Runtime asynchronous action object representing the completion of the result sequence, reporting progress computed through the progress sequence. + /// or is null. + public static IAsyncActionWithProgress ToIAsyncActionWithProgress(this IObservable source, Func, IObservable> progressSelector) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (progressSelector == null) + { + throw new ArgumentNullException(nameof(progressSelector)); + } + + return AsyncInfo.Run((ct, progress) => + { + return Observable.Create(observer => + { + var obs = Observer.Synchronize(observer); + + var data = source.Publish(); + + var progressSubscription = progressSelector(data).Subscribe(progress.Report, obs.OnError); + var dataSubscription = data.DefaultIfEmpty().Subscribe(obs); + var connection = data.Connect(); + + return StableUncheckedCompositeDisposable.CreateTrusted(progressSubscription, dataSubscription, connection); + }).ToTask(ct); + }); + } + + #endregion + + #endregion + + #region IAsyncOperation + + /// + /// Creates a Windows Runtime asynchronous operation that returns the last element of the observable sequence. + /// Upon cancellation of the asynchronous operation, the subscription to the source sequence will be disposed. + /// + /// The type of the elements in the source sequence. + /// Source sequence to expose as an asynchronous operation. + /// Windows Runtime asynchronous operation object that returns the last element of the observable sequence. + /// is null. + public static IAsyncOperation ToIAsyncOperation(this IObservable source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return AsyncInfo.Run(ct => source.ToTask(ct)); + } + + /// + /// Creates a Windows Runtime asynchronous operation that returns the last element of the observable sequence, reporting incremental progress for each element produced by the sequence. + /// Upon cancellation of the asynchronous operation, the subscription to the source sequence will be disposed. + /// + /// The type of the elements in the source sequence. + /// Source sequence to expose as an asynchronous operation. + /// Windows Runtime asynchronous operation object that returns the last element of the observable sequence, reporting incremental progress for each source sequence element. + /// is null. + public static IAsyncOperationWithProgress ToIAsyncOperationWithProgress(this IObservable source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return AsyncInfo.Run((ct, progress) => + { + var i = 0; + return source.Do(_ => progress.Report(i++)).ToTask(ct); + }); + } + + #region Progress + + /// + /// Creates a Windows Runtime asynchronous operation that returns the last element of the result sequence, reporting incremental progress for each element produced by the source sequence. + /// Upon cancellation of the asynchronous operation, the subscription to the source sequence will be disposed. + /// + /// The type of the elements in the source sequence. + /// The type of the elements in the result sequence. + /// Source sequence to compute a result sequence that gets exposed as an asynchronous operation. + /// Selector function to map the source sequence on a result sequence. + /// Windows Runtime asynchronous operation object that returns the last element of the result sequence, reporting incremental progress for each source sequence element. + /// or is null. + public static IAsyncOperationWithProgress ToIAsyncOperationWithProgress(this IObservable source, Func, IObservable> resultSelector) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (resultSelector == null) + { + throw new ArgumentNullException(nameof(resultSelector)); + } + + return AsyncInfo.Run((ct, progress) => + { + var i = 0; + return resultSelector(source.Do(_ => progress.Report(i++))).ToTask(ct); + }); + } + + /// + /// Creates a Windows Runtime asynchronous operation that returns the last element of the result sequence, using a selector function to map the source sequence on a progress reporting sequence. + /// Upon cancellation of the asynchronous operation, the subscription to the source sequence will be disposed. + /// + /// The type of the elements in the source sequence. + /// The type of the elements in the result sequence. + /// The type of the elements in the progress sequence. + /// Source sequence to compute a result sequence that gets exposed as an asynchronous operation and a progress sequence that gets reported through the asynchronous operation. + /// Selector function to map the source sequence on a result sequence. + /// Selector function to map the source sequence on a progress reporting sequence. + /// Windows Runtime asynchronous operation object that returns the last element of the result sequence, reporting progress computed through the progress sequence. + /// or or is null. + public static IAsyncOperationWithProgress ToIAsyncOperationWithProgress(this IObservable source, Func, IObservable> resultSelector, Func, IObservable> progressSelector) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (resultSelector == null) + { + throw new ArgumentNullException(nameof(resultSelector)); + } + + if (progressSelector == null) + { + throw new ArgumentNullException(nameof(progressSelector)); + } + + return AsyncInfo.Run((ct, progress) => + { + return Observable.Create(observer => + { + var obs = Observer.Synchronize(observer); + + var data = source.Publish(); + + var progressSubscription = progressSelector(data).Subscribe(progress.Report, obs.OnError); + var dataSubscription = resultSelector(data).Subscribe(obs); + var connection = data.Connect(); + + return StableUncheckedCompositeDisposable.CreateTrusted(progressSubscription, dataSubscription, connection); + }).ToTask(ct); + }); + } + + #endregion + + #endregion + } +} diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeCoreDispatcherObservable.cs b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeCoreDispatcherObservable.cs new file mode 100644 index 000000000..d7474f781 --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeCoreDispatcherObservable.cs @@ -0,0 +1,315 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT License. +// See the LICENSE file in the project root for more information. + +using Windows.UI.Core; + +#if HAS_OS_XAML +using Windows.UI.Xaml; +#endif + +using CoreDispatcherScheduler = System.Reactive.Integration.WindowsRuntime.CoreDispatcherScheduler; +using Synchronization = System.Reactive.Concurrency.Synchronization; + +namespace System.Reactive.Linq +{ + /// + /// Provides a set of extension methods for scheduling actions performed through observable sequences on UI dispatchers. + /// + [CLSCompliant(false)] + public static class WindowsRuntimeCoreDispatcherObservable + { + #region ObserveOn[Current]CoreDispatcher + + /// + /// Wraps the source sequence in order to run its observer callbacks on the specified dispatcher. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// Dispatcher whose associated message loop is used to notify observers on. + /// The source sequence whose observations happen on the specified dispatcher. + /// or is null. + public static IObservable ObserveOnWindowsRuntimeCoreDispatcher(this IObservable source, CoreDispatcher dispatcher) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (dispatcher == null) + { + throw new ArgumentNullException(nameof(dispatcher)); + } + + return Synchronization.ObserveOn(source, new CoreDispatcherScheduler(dispatcher)); + } + + /// + /// Wraps the source sequence in order to run its observer callbacks on the specified dispatcher. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// Dispatcher whose associated message loop is used to notify observers on. + /// Priority to schedule work items at. + /// The source sequence whose observations happen on the specified dispatcher. + /// or is null. + public static IObservable ObserveOnWindowsRuntimeCoreDispatcher(this IObservable source, CoreDispatcher dispatcher, CoreDispatcherPriority priority) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (dispatcher == null) + { + throw new ArgumentNullException(nameof(dispatcher)); + } + + return Synchronization.ObserveOn(source, new CoreDispatcherScheduler(dispatcher, priority)); + } + +#if HAS_OS_XAML + /// + /// Wraps the source sequence in order to run its observer callbacks on the dispatcher associated with the specified object. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// Object to get the dispatcher from. + /// The source sequence whose observations happen on the specified object's dispatcher. + /// or is null. + public static IObservable ObserveOnWindowsRuntimeCoreDispatcher(this IObservable source, DependencyObject dependencyObject) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (dependencyObject == null) + { + throw new ArgumentNullException(nameof(dependencyObject)); + } + + return Synchronization.ObserveOn(source, new CoreDispatcherScheduler(dependencyObject.Dispatcher)); + } + + /// + /// Wraps the source sequence in order to run its observer callbacks on the dispatcher associated with the specified object. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// Object to get the dispatcher from. + /// Priority to schedule work items at. + /// The source sequence whose observations happen on the specified object's dispatcher. + /// or is null. + public static IObservable ObserveOnWindowsRuntimeCoreDispatcher(this IObservable source, DependencyObject dependencyObject, CoreDispatcherPriority priority) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (dependencyObject == null) + { + throw new ArgumentNullException(nameof(dependencyObject)); + } + + return Synchronization.ObserveOn(source, new CoreDispatcherScheduler(dependencyObject.Dispatcher, priority)); + } +#endif + /// + /// Wraps the source sequence in order to run its observer callbacks on the dispatcher associated with the current window. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// The source sequence whose observations happen on the current window's dispatcher. + /// is null. + public static IObservable ObserveOnCurrentWindowsRuntimeCoreDispatcher(this IObservable source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return Synchronization.ObserveOn(source, CoreDispatcherScheduler.Current); + } + + /// + /// Wraps the source sequence in order to run its observer callbacks on the dispatcher associated with the current window. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// Priority to schedule work items at. + /// The source sequence whose observations happen on the current window's dispatcher. + /// is null. + public static IObservable ObserveOnCurrentWindowsRuntimeCoreDispatcher(this IObservable source, CoreDispatcherPriority priority) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return Synchronization.ObserveOn(source, new CoreDispatcherScheduler(CoreDispatcherScheduler.Current.Dispatcher, priority)); + } + + #endregion + + #region SubscribeOn[CoreDispatcher] + + /// + /// Wraps the source sequence in order to run its subscription and unsubscription logic on the specified dispatcher. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// Dispatcher whose associated message loop is used to perform subscription and unsubscription actions on. + /// The source sequence whose subscriptions and unsubscriptions happen on the specified dispatcher. + /// or is null. + /// + /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the specified dispatcher. + /// In order to invoke observer callbacks on the specified dispatcher, e.g. to render results in a control, use . + /// + public static IObservable SubscribeOnWindowsRuntimeCoreDispatcher(this IObservable source, CoreDispatcher dispatcher) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (dispatcher == null) + { + throw new ArgumentNullException(nameof(dispatcher)); + } + + return Synchronization.SubscribeOn(source, new CoreDispatcherScheduler(dispatcher)); + } + + /// + /// Wraps the source sequence in order to run its subscription and unsubscription logic on the specified dispatcher. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// Dispatcher whose associated message loop is used to perform subscription and unsubscription actions on. + /// Priority to schedule work items at. + /// The source sequence whose subscriptions and unsubscriptions happen on the specified dispatcher. + /// or is null. + /// + /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the specified dispatcher. + /// In order to invoke observer callbacks on the specified dispatcher, e.g. to render results in a control, use . + /// + public static IObservable SubscribeOnWindowsRuntimeCoreDispatcher(this IObservable source, CoreDispatcher dispatcher, CoreDispatcherPriority priority) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (dispatcher == null) + { + throw new ArgumentNullException(nameof(dispatcher)); + } + + return Synchronization.SubscribeOn(source, new CoreDispatcherScheduler(dispatcher, priority)); + } + +#if HAS_OS_XAML + /// + /// Wraps the source sequence in order to run its subscription and unsubscription logic on the dispatcher associated with the specified object. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// Object to get the dispatcher from. + /// The source sequence whose subscriptions and unsubscriptions happen on the specified object's dispatcher. + /// or is null. + /// + /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the dispatcher associated with the specified object. + /// In order to invoke observer callbacks on the dispatcher associated with the specified object, e.g. to render results in a control, use . + /// + public static IObservable SubscribeOnWindowsRuntimeCoreDispatcher(this IObservable source, DependencyObject dependencyObject) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (dependencyObject == null) + { + throw new ArgumentNullException(nameof(dependencyObject)); + } + + return Synchronization.SubscribeOn(source, new CoreDispatcherScheduler(dependencyObject.Dispatcher)); + } + + /// + /// Wraps the source sequence in order to run its subscription and unsubscription logic on the dispatcher associated with the specified object. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// Object to get the dispatcher from. + /// Priority to schedule work items at. + /// The source sequence whose subscriptions and unsubscriptions happen on the specified object's dispatcher. + /// or is null. + /// + /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the dispatcher associated with the specified object. + /// In order to invoke observer callbacks on the dispatcher associated with the specified object, e.g. to render results in a control, use . + /// + public static IObservable SubscribeOnWindowsRuntimeCoreDispatcher(this IObservable source, DependencyObject dependencyObject, CoreDispatcherPriority priority) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (dependencyObject == null) + { + throw new ArgumentNullException(nameof(dependencyObject)); + } + + return Synchronization.SubscribeOn(source, new CoreDispatcherScheduler(dependencyObject.Dispatcher, priority)); + } +#endif + + /// + /// Wraps the source sequence in order to run its subscription and unsubscription logic on the dispatcher associated with the current window. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// The source sequence whose subscriptions and unsubscriptions happen on the current window's dispatcher. + /// is null. + /// + /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the dispatcher associated with the current window. + /// In order to invoke observer callbacks on the dispatcher associated with the current window, e.g. to render results in a control, use . + /// + public static IObservable SubscribeOnCurrentWindowsRuntimeCoreDispatcher(this IObservable source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return Synchronization.SubscribeOn(source, CoreDispatcherScheduler.Current); + } + + /// + /// Wraps the source sequence in order to run its subscription and unsubscription logic on the dispatcher associated with the current window. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// Priority to schedule work items at. + /// The source sequence whose subscriptions and unsubscriptions happen on the current window's dispatcher. + /// is null. + /// + /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the dispatcher associated with the current window. + /// In order to invoke observer callbacks on the dispatcher associated with the current window, e.g. to render results in a control, use . + /// + public static IObservable SubscribeOnCurrentWindowsRuntimeCoreDispatcher(this IObservable source, CoreDispatcherPriority priority) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return Synchronization.SubscribeOn(source, new CoreDispatcherScheduler(CoreDispatcherScheduler.Current.Dispatcher, priority)); + } + + #endregion + } +} diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeObservable.Events.cs b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeObservable.Events.cs new file mode 100644 index 000000000..2aa38d712 --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeObservable.Events.cs @@ -0,0 +1,116 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT License. +// See the LICENSE file in the project root for more information. + +using Windows.Foundation; + +namespace System.Reactive.Linq +{ + /// + /// Provides a set of static methods for importing typed events from Windows Runtime APIs. + /// + [CLSCompliant(false)] + public static partial class WindowsRuntimeObservable + { + /// + /// Converts a typed event, conforming to the standard event pattern, to an observable sequence. + /// + /// The type of the sender that raises the event. + /// The type of the event data generated by the event. + /// Action that attaches the given event handler to the underlying .NET event. + /// Action that detaches the given event handler from the underlying .NET event. + /// The observable sequence that contains data representations of invocations of the underlying typed event. + /// or is null. + /// + public static IObservable> FromEventPattern(Action> addHandler, Action> removeHandler) + { + if (addHandler == null) + { + throw new ArgumentNullException(nameof(addHandler)); + } + + if (removeHandler == null) + { + throw new ArgumentNullException(nameof(removeHandler)); + } + + return Observable.Create>(observer => + { + var h = new TypedEventHandler((sender, args) => + { + observer.OnNext(new EventPattern(sender, args)); + }); + + addHandler(h); + + return () => + { + removeHandler(h); + }; + }); + } + + /// + /// Converts a typed event, conforming to the standard event pattern, to an observable sequence. + /// + /// The delegate type of the event to be converted. + /// The type of the sender that raises the event. + /// The type of the event data generated by the event. + /// A function used to convert the given event handler to a delegate compatible with the underlying typed event. The resulting delegate is used in calls to the addHandler and removeHandler action parameters. + /// Action that attaches the given event handler to the underlying .NET event. + /// Action that detaches the given event handler from the underlying .NET event. + /// The observable sequence that contains data representations of invocations of the underlying typed event. + /// or or is null. + /// + public static IObservable> FromEventPattern(Func, TDelegate> conversion, Action addHandler, Action removeHandler) + { + if (conversion == null) + { + throw new ArgumentNullException(nameof(conversion)); + } + + if (addHandler == null) + { + throw new ArgumentNullException(nameof(addHandler)); + } + + if (removeHandler == null) + { + throw new ArgumentNullException(nameof(removeHandler)); + } + + return Observable.Create>(observer => + { + var h = conversion(new TypedEventHandler((sender, args) => + { + observer.OnNext(new EventPattern(sender, args)); + })); + + addHandler(h); + + return () => + { + removeHandler(h); + }; + }); + } + + /// + /// Exposes an observable sequence as an object with a typed event. + /// + /// The type of the sender that raises the event. + /// The type of the event data generated by the event. + /// Observable source sequence. + /// The event source object. + /// is null. + public static System.Reactive.Integration.WindowsRuntime.ITypedEventPatternSource ToWindowsFoundationEventPattern(this IObservable> source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return new System.Reactive.Integration.WindowsRuntime.EventPatternSource(source, static (h, evt) => h(evt.Sender!, evt.EventArgs)); + } + } +} diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeObservable.StandardSequenceOperators.cs b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeObservable.StandardSequenceOperators.cs new file mode 100644 index 000000000..5f905bdbe --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeObservable.StandardSequenceOperators.cs @@ -0,0 +1,135 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT License. +// See the LICENSE file in the project root for more information. + +using System.Reactive.Integration.WindowsRuntime; +using Windows.Foundation; + +namespace System.Reactive.Linq +{ + public static partial class WindowsRuntimeObservable + { + /// + /// Projects each element of an observable sequence to a Windows Runtime asynchronous operation and merges all of the asynchronous operation results into one observable sequence. + /// + /// The type of the elements in the source sequence. + /// The type of the result produced by the projected asynchronous operations and the elements in the merged result sequence. + /// An observable sequence of elements to project. + /// A transform function to apply to each element. + /// An observable sequence whose elements are the result of the asynchronous operations executed for each element of the input sequence. + /// or is null. + /// + /// + /// This overload supports composition of observable sequences and Windows Runtime + /// asynchronous operations, without requiring manual conversion of the asynchronous + /// operations to observable sequences using + /// . + /// + /// + public static IObservable SelectManyIAsyncOperation(this IObservable source, Func> selector) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (selector == null) + { + throw new ArgumentNullException(nameof(selector)); + } + + return source.SelectMany(x => selector(x).ToObservable()); + } + + /// + /// Projects each element of an observable sequence to a Windows Runtime asynchronous operation and merges all of the asynchronous operation results into one observable sequence. + /// + /// The type of the elements in the source sequence. + /// The type of the result produced by the projected asynchronous operations and the elements in the merged result sequence. + /// The type of the reported progress objects, which get ignored by this query operator. + /// An observable sequence of elements to project. + /// A transform function to apply to each element. + /// An observable sequence whose elements are the result of the asynchronous operations executed for each element of the input sequence. + /// or is null. + /// This overload supports composition of observable sequences and Windows Runtime asynchronous operations, without requiring manual conversion of the asynchronous operations to observable sequences using . + public static IObservable SelectManyIAsyncOperationWithProgress(this IObservable source, Func> selector) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (selector == null) + { + throw new ArgumentNullException(nameof(selector)); + } + + return source.SelectMany(x => selector(x).ToObservable()); + } + + /// + /// Projects each element of an observable sequence to a Windows Runtime asynchronous operation, invokes the result selector for the source element and the asynchronous operation result, and merges the results into one observable sequence. + /// + /// The type of the elements in the source sequence. + /// The type of the results produced by the projected asynchronous operations. + /// The type of the elements in the result sequence, obtained by using the selector to combine source sequence elements with their corresponding intermediate asynchronous operation results. + /// An observable sequence of elements to project. + /// A transform function to apply to each element. + /// A transform function to apply to each element of the intermediate sequence. + /// An observable sequence whose elements are the result of obtaining an asynchronous operation for each element of the input sequence and then mapping the asynchronous operation's result and its corresponding source element to a result element. + /// or or is null. + /// This overload supports using LINQ query comprehension syntax in C# and Visual Basic to compose observable sequences and Windows Runtime asynchronous operations, without requiring manual conversion of the asynchronous operations to observable sequences using . + public static IObservable SelectManyIAsyncOperation(this IObservable source, Func> asyncOperationSelector, Func resultSelector) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (asyncOperationSelector == null) + { + throw new ArgumentNullException(nameof(asyncOperationSelector)); + } + + if (resultSelector == null) + { + throw new ArgumentNullException(nameof(resultSelector)); + } + + return source.SelectMany(x => asyncOperationSelector(x).ToObservable(), resultSelector); + } + + /// + /// Projects each element of an observable sequence to a Windows Runtime asynchronous operation, invokes the result selector for the source element and the asynchronous operation result, and merges the results into one observable sequence. + /// + /// The type of the elements in the source sequence. + /// The type of the results produced by the projected asynchronous operations. + /// The type of the reported progress objects, which get ignored by this query operator. + /// The type of the elements in the result sequence, obtained by using the selector to combine source sequence elements with their corresponding intermediate asynchronous operation results. + /// An observable sequence of elements to project. + /// A transform function to apply to each element. + /// A transform function to apply to each element of the intermediate sequence. + /// An observable sequence whose elements are the result of obtaining an asynchronous operation for each element of the input sequence and then mapping the asynchronous operation's result and its corresponding source element to a result element. + /// or or is null. + /// This overload supports using LINQ query comprehension syntax in C# and Visual Basic to compose observable sequences and Windows Runtime asynchronous operations, without requiring manual conversion of the asynchronous operations to observable sequences using . + public static IObservable SelectManyIAsyncOperationWithProgress(this IObservable source, Func> asyncOperationSelector, Func resultSelector) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (asyncOperationSelector == null) + { + throw new ArgumentNullException(nameof(asyncOperationSelector)); + } + + if (resultSelector == null) + { + throw new ArgumentNullException(nameof(resultSelector)); + } + + return source.SelectMany(x => asyncOperationSelector(x).ToObservable(), resultSelector); + } + } +} diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/build/NuGet.Readme.md b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/build/NuGet.Readme.md new file mode 100644 index 000000000..c7321c896 --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/build/NuGet.Readme.md @@ -0,0 +1,30 @@ +# Windows Runtime Support for Rx.NET (Reactive Extensions for .NET) + +This library provides support for using some common Windows Runtime types from the Reactive Extensions for .NET (Rx.NET). + +See the main Rx.NET package at https://www.nuget.org/packages/System.Reactive for more information about Rx.NET. + +## Rx.NET and UI Frameworks + +Up as far as Rx.NET v6.0, UI framework support has been built directly into the main `System.Reactive` package. +Unfortunately, this has caused problems since support for WPF and Windows Forms was added in .NET Core 3.1. +Because .NET Core 3.1, and all subsequent versions of .NET have supported cross-platform use, WPF and Windows +Forms are not universally available. Rx.NET used to make WPF and Windows Forms support if you targetted a +sufficiently recent version of Windows in your application TFM. But this turns out to cause problems in +some deployment models, adding as much as 90MB to the deployable size of an application. + +Consequently, starting in Rx.NET v7.0 we are moving all UI-framework-specific types, and also platform-specific +types out into separate packages. + +## Features + +This package provides replacements for two deprecated types in `System.Reactive`: + +| Type in `System.Reactive` | Replacement | Purpose | +|---|---|---| +| `CoreDispatcherScheduler` (in `System.Reactive.Concurrency`) | `CoreDispatcherScheduler` (in `System.Reactive.Integration.WPF`) | Provides a scheduler that schedules work on the UI thread of applications using `CoreDispatcher` (e.g., UWP applications). | +| `CoreDispatcherObservable` (in `System.Reactive.Linq`) | `WindowsRuntimeCoreDispatcherObservable` (in `System.Reactive.Linq`) | Provides a set of extension methods for scheduling work on the UI thread of an application using `CoreDispatcher` (e.g., UWP applications). WPF application. | +| `WindowsObservable` (in `System.Reactive.Linq`) | `WindowsRuntimeObservable` (in `System.Reactive.Linq`) | Provides integration between `TypedEventHandler`, and also `SelectMany` support for callbacks using the Windows Runtime asynchronous operation types (`IAsyncOperation` etc.) and `IObservable`. +| `AsyncInfoObservable` (in `System.Reactive.Linq`) | `WindowsRuntimeAsyncInfoObservable` (in `System.Reactive.Integration.WindowsRuntime`) | Provides conversions `IObservable` top Windows Runtime asynchronous operation types (`IAsyncOperation` etc.). | +| `AsyncInfoObservableExtensions` (in `System.Reactive.Windows.Foundation`) | `AsyncInfoObservableExtensions` (in `System.Reactive.Integration.WindowsRuntime` | Provides conversion from Windows Runtime asynchronous operation types (`IAsyncOperation` etc.) and `IObservable`. +| `IEventPatternSource` (in `System.Reactive`) | `ITypedEventPatternSource` in `System.Reactive.Integration.WindowsRuntime` | Represents a source of events exposed as a Windows Runtime `TypedEventHandler`. | \ No newline at end of file diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Wpf/DispatcherScheduler.cs b/Rx.NET/Source/src/System.Reactive.Integration.Wpf/DispatcherScheduler.cs new file mode 100644 index 000000000..6ab8bf278 --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.Wpf/DispatcherScheduler.cs @@ -0,0 +1,215 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT License. +// See the LICENSE file in the project root for more information. + +using System.Reactive.Disposables; +using System.Reactive.Concurrency; +using System.Threading; +using System.Windows.Threading; + +namespace System.Reactive.Integration.Wpf +{ + /// + /// Represents an object that schedules units of work on a . + /// + /// + /// + /// This scheduler type is typically used indirectly through extension methods such as + /// and + /// + /// in cases where you have a you want to use, or methods such as + /// , + /// + /// when you want to use the calling thread's Dispatcher. + /// + /// + public class DispatcherScheduler : LocalScheduler, ISchedulerPeriodic + { + /// + /// Gets the scheduler that schedules work on the for the current thread. + /// + public static DispatcherScheduler Current + { + get + { + var dispatcher = System.Windows.Threading.Dispatcher.FromThread(Thread.CurrentThread) + ?? throw new InvalidOperationException(Strings_WindowsThreading.NO_DISPATCHER_CURRENT_THREAD); + return new DispatcherScheduler(dispatcher); + } + } + + /// + /// Constructs a that schedules units of work on the given . + /// + /// to schedule work on. + /// is null. + public DispatcherScheduler(System.Windows.Threading.Dispatcher dispatcher) + { + Dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher)); + Priority = System.Windows.Threading.DispatcherPriority.Normal; + + } + + /// + /// Constructs a that schedules units of work on the given at the given priority. + /// + /// to schedule work on. + /// Priority at which units of work are scheduled. + /// is null. + public DispatcherScheduler(System.Windows.Threading.Dispatcher dispatcher, System.Windows.Threading.DispatcherPriority priority) + { + Dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher)); + Priority = priority; + } + + /// + /// Gets the associated with the . + /// + public System.Windows.Threading.Dispatcher Dispatcher { get; } + + /// + /// Gets the priority at which work items will be dispatched. + /// + public System.Windows.Threading.DispatcherPriority Priority { get; } + + /// + /// Schedules an action to be executed on the dispatcher. + /// + /// The type of the state passed to the scheduled action. + /// State passed to the action to be executed. + /// Action to be executed. + /// The disposable object used to cancel the scheduled action (best effort). + /// is null. + public override IDisposable Schedule(TState state, Func action) + { + if (action == null) + { + throw new ArgumentNullException(nameof(action)); + } + + var d = new SingleAssignmentDisposable(); + + Dispatcher.BeginInvoke( + new Action(() => + { + if (!d.IsDisposed) + { + d.Disposable = action(this, state); + } + }), + Priority + ); + + return d; + } + + /// + /// Schedules an action to be executed after on the dispatcher, using a object. + /// + /// The type of the state passed to the scheduled action. + /// State passed to the action to be executed. + /// Action to be executed. + /// Relative time after which to execute the action. + /// The disposable object used to cancel the scheduled action (best effort). + /// is null. + public override IDisposable Schedule(TState state, TimeSpan dueTime, Func action) + { + if (action == null) + { + throw new ArgumentNullException(nameof(action)); + } + + var dt = Scheduler.Normalize(dueTime); + if (dt.Ticks == 0) + { + return Schedule(state, action); + } + + return ScheduleSlow(state, dt, action); + } + + private IDisposable ScheduleSlow(TState state, TimeSpan dueTime, Func action) + { + var d = new MultipleAssignmentDisposable(); + + var timer = new System.Windows.Threading.DispatcherTimer(Priority, Dispatcher); + + timer.Tick += (s, e) => + { + var t = Interlocked.Exchange(ref timer, null); + if (t != null) + { + try + { + d.Disposable = action(this, state); + } + finally + { + t.Stop(); + action = static (s, t) => Disposable.Empty; + } + } + }; + + timer.Interval = dueTime; + timer.Start(); + + d.Disposable = Disposable.Create(() => + { + var t = Interlocked.Exchange(ref timer, null); + if (t != null) + { + t.Stop(); + action = static (s, t) => Disposable.Empty; + } + }); + + return d; + } + + /// + /// Schedules a periodic piece of work on the dispatcher, using a object. + /// + /// The type of the state passed to the scheduled action. + /// Initial state passed to the action upon the first iteration. + /// Period for running the work periodically. + /// Action to be executed, potentially updating the state. + /// The disposable object used to cancel the scheduled recurring action (best effort). + /// is null. + /// is less than . + public IDisposable SchedulePeriodic(TState state, TimeSpan period, Func action) + { + if (period < TimeSpan.Zero) + { + throw new ArgumentOutOfRangeException(nameof(period)); + } + + if (action == null) + { + throw new ArgumentNullException(nameof(action)); + } + + var timer = new System.Windows.Threading.DispatcherTimer(Priority, Dispatcher); + + var state1 = state; + + timer.Tick += (s, e) => + { + state1 = action(state1); + }; + + timer.Interval = period; + timer.Start(); + + return Disposable.Create(() => + { + var t = Interlocked.Exchange(ref timer, null); + if (t != null) + { + t.Stop(); + action = static _ => _; + } + }); + } + } +} diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Wpf/Strings_WindowsThreading.Designer.cs b/Rx.NET/Source/src/System.Reactive.Integration.Wpf/Strings_WindowsThreading.Designer.cs new file mode 100644 index 000000000..0cf293393 --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.Wpf/Strings_WindowsThreading.Designer.cs @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace System.Reactive.Integration.Wpf { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Strings_WindowsThreading { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Strings_WindowsThreading() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Reactive.Integration.Wpf.Strings_WindowsThreading", typeof(Strings_WindowsThreading).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to The current thread has no Dispatcher associated with it.. + /// + internal static string NO_DISPATCHER_CURRENT_THREAD { + get { + return ResourceManager.GetString("NO_DISPATCHER_CURRENT_THREAD", resourceCulture); + } + } + } +} diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Wpf/Strings_WindowsThreading.resx b/Rx.NET/Source/src/System.Reactive.Integration.Wpf/Strings_WindowsThreading.resx new file mode 100644 index 000000000..8384193b1 --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.Wpf/Strings_WindowsThreading.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + The current thread has no Dispatcher associated with it. + + \ No newline at end of file diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Wpf/System.Reactive.Integration.Wpf.csproj b/Rx.NET/Source/src/System.Reactive.Integration.Wpf/System.Reactive.Integration.Wpf.csproj new file mode 100644 index 000000000..caf89a25d --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.Wpf/System.Reactive.Integration.Wpf.csproj @@ -0,0 +1,44 @@ + + + + net472;net6.0-windows + true + + Rx;Reactive;Extensions;Observable;LINQ;Events;WPF + Reactive Extensions (Rx) for .NET + + readme.md + + + + enable + + + + + + + + + + + + + True + True + Strings_WindowsThreading.resx + + + + + + ResXFileCodeGenerator + Strings_WindowsThreading.Designer.cs + + + + + + + + diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Wpf/System.Reactive.Linq/WpfDispatcherObservable.cs b/Rx.NET/Source/src/System.Reactive.Integration.Wpf/System.Reactive.Linq/WpfDispatcherObservable.cs new file mode 100644 index 000000000..a748607b3 --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.Wpf/System.Reactive.Linq/WpfDispatcherObservable.cs @@ -0,0 +1,498 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT License. +// See the LICENSE file in the project root for more information. + +using System.Windows.Threading; + +using DispatcherScheduler = System.Reactive.Integration.Wpf.DispatcherScheduler; +using Synchronization = System.Reactive.Concurrency.Synchronization; + +namespace System.Reactive.Linq +{ + /// + /// Provides a set of extension methods for scheduling actions performed through observable + /// sequences on UI dispatchers. + /// + /// + /// + /// This replaces the obsolete System.Reactive.Linq.ControlObservable class in + /// System.Reactive. + /// + /// + public static class WpfDispatcherObservable + + { + #region ObserveOn[Current]Dispatcher + + /// + /// Wraps the source sequence in order to run its observer callbacks on the specified + /// dispatcher. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// Dispatcher whose associated message loop is used to notify observers on. + /// The source sequence whose observations happen on the specified dispatcher. + /// + /// or is null. + /// + public static IObservable ObserveOnWpfDispatcher( + this IObservable source, + Dispatcher dispatcher) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (dispatcher == null) + { + throw new ArgumentNullException(nameof(dispatcher)); + } + + return ObserveOn_(source, dispatcher); + } + + /// + /// Wraps the source sequence in order to run its observer callbacks on the specified + /// dispatcher. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// Dispatcher whose associated message loop is used to notify observers on. + /// Priority to schedule work items at. + /// The source sequence whose observations happen on the specified dispatcher. + /// + /// or is null. + /// + public static IObservable ObserveOnWpfDispatcher( + this IObservable source, + Dispatcher dispatcher, + DispatcherPriority priority) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (dispatcher == null) + { + throw new ArgumentNullException(nameof(dispatcher)); + } + + return ObserveOn_(source, dispatcher, priority); + } + + /// + /// Wraps the source sequence in order to run its observer callbacks on the specified + /// dispatcher scheduler. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// Dispatcher scheduler to notify observers on. + /// The source sequence whose observations happen on the specified dispatcher scheduler. + /// + /// or is null. + /// + public static IObservable ObserveOn( + this IObservable source, + DispatcherScheduler scheduler) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (scheduler == null) + { + throw new ArgumentNullException(nameof(scheduler)); + } + + return ObserveOn_(source, scheduler.Dispatcher, scheduler.Priority); + } + + + /// + /// Wraps the source sequence in order to run its observer callbacks on the dispatcher + /// associated with the specified object. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// Object to get the dispatcher from. + /// The source sequence whose observations happen on the specified object's dispatcher. + /// + /// or is null. + /// + public static IObservable ObserveOnWpfDispatcher( + this IObservable source, + DispatcherObject dispatcherObject) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (dispatcherObject == null) + { + throw new ArgumentNullException(nameof(dispatcherObject)); + } + + return ObserveOn_(source, dispatcherObject.Dispatcher); + } + + /// + /// Wraps the source sequence in order to run its observer callbacks on the dispatcher + /// associated with the specified object. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// Object to get the dispatcher from. + /// Priority to schedule work items at. + /// The source sequence whose observations happen on the specified object's dispatcher. + /// + /// or is null. + /// + public static IObservable ObserveOnWpfDispatcher( + this IObservable source, + DispatcherObject dispatcherObject, + DispatcherPriority priority) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (dispatcherObject == null) + { + throw new ArgumentNullException(nameof(dispatcherObject)); + } + + return ObserveOn_(source, dispatcherObject.Dispatcher, priority); + } + + + /// + /// Wraps the source sequence in order to run its observer callbacks on the dispatcher + /// associated with the current thread. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// The source sequence whose observations happen on the current thread's dispatcher. + /// is null. + public static IObservable ObserveOnCurrentWpfDispatcher( + this IObservable source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return ObserveOn_(source, DispatcherScheduler.Current.Dispatcher); + } + + /// + /// Wraps the source sequence in order to run its observer callbacks on the dispatcher + /// associated with the current thread. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// Priority to schedule work items at. + /// The source sequence whose observations happen on the current thread's dispatcher. + /// is null. + public static IObservable ObserveOnCurrentWpfDispatcher( + this IObservable source, + DispatcherPriority priority) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return ObserveOn_(source, DispatcherScheduler.Current.Dispatcher, priority); + } + + private static IObservable ObserveOn_(IObservable source, Dispatcher dispatcher, DispatcherPriority priority) + { + return Synchronization.ObserveOn(source, new DispatcherSynchronizationContext(dispatcher, priority)); + } + + + private static IObservable ObserveOn_(IObservable source, Dispatcher dispatcher) + { + return Synchronization.ObserveOn(source, new DispatcherSynchronizationContext(dispatcher)); + } + + #endregion + + #region SubscribeOn[Dispatcher] + + /// + /// Wraps the source sequence in order to run its subscription and unsubscription logic on + /// the specified dispatcher. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// + /// Dispatcher whose associated message loop is used to perform subscription and + /// unsubscription actions on. + /// + /// + /// The source sequence whose subscriptions and unsubscriptions happen on the specified dispatcher. + /// + /// + /// or is null. + /// + /// + /// Only the side-effects of subscribing to the source sequence and disposing subscriptions + /// to the source sequence are run on the specified dispatcher. In order to invoke observer + /// callbacks on the specified dispatcher, e.g. to render results in a control, use + /// . + /// + public static IObservable SubscribeOnWpfDispatcher( + this IObservable source, + Dispatcher dispatcher) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (dispatcher == null) + { + throw new ArgumentNullException(nameof(dispatcher)); + } + + return SubscribeOn_(source, dispatcher); + } + + /// + /// Wraps the source sequence in order to run its subscription and unsubscription logic on + /// the specified dispatcher. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// + /// Dispatcher whose associated message loop is used to to perform subscription and + /// unsubscription actions on. + /// + /// Priority to schedule work items at. + /// + /// The source sequence whose subscriptions and unsubscriptions happen on the specified + /// dispatcher. + /// + /// + /// or is null. + /// + /// + /// Only the side-effects of subscribing to the source sequence and disposing subscriptions + /// to the source sequence are run on the specified dispatcher. In order to invoke observer + /// callbacks on the specified dispatcher, e.g. to render results in a control, use + /// . + /// + public static IObservable SubscribeOnWpfDispatcher( + this IObservable source, + Dispatcher dispatcher, + DispatcherPriority priority) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (dispatcher == null) + { + throw new ArgumentNullException(nameof(dispatcher)); + } + + return SubscribeOn_(source, dispatcher, priority); + } + + + /// + /// Wraps the source sequence in order to run its subscription and unsubscription logic on + /// the specified dispatcher scheduler. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// + /// Dispatcher scheduler to perform subscription and unsubscription actions on. + /// + /// + /// The source sequence whose subscriptions and unsubscriptions happen on the specified + /// dispatcher scheduler. + /// + /// + /// or is null. + /// + /// + /// Only the side-effects of subscribing to the source sequence and disposing subscriptions + /// to the source sequence are run on the specified scheduler. In order to invoke observer + /// callbacks on the specified scheduler, e.g. to render results in a control, use + /// . + /// + public static IObservable SubscribeOn( + this IObservable source, + DispatcherScheduler scheduler) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (scheduler == null) + { + throw new ArgumentNullException(nameof(scheduler)); + } + + return SubscribeOn_(source, scheduler.Dispatcher, scheduler.Priority); + } + + /// + /// Wraps the source sequence in order to run its subscription and unsubscription logic on + /// the dispatcher associated with the specified object. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// Object to get the dispatcher from. + /// + /// The source sequence whose subscriptions and unsubscriptions happen on the specified + /// object's dispatcher. + /// + /// + /// or is null. + /// + /// + /// Only the side-effects of subscribing to the source sequence and disposing subscriptions + /// to the source sequence are run on the dispatcher associated with the specified object. + /// In order to invoke observer callbacks on the dispatcher associated with the specified + /// object, e.g. to render results in a control, use + /// . + /// + public static IObservable SubscribeOnWpfDispatcher( + this IObservable source, + DispatcherObject dispatcherObject) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (dispatcherObject == null) + { + throw new ArgumentNullException(nameof(dispatcherObject)); + } + + return SubscribeOn_(source, dispatcherObject.Dispatcher); + } + + /// + /// Wraps the source sequence in order to run its subscription and unsubscription logic on + /// the dispatcher associated with the specified object. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// Object to get the dispatcher from. + /// Priority to schedule work items at. + /// + /// The source sequence whose subscriptions and unsubscriptions happen on the specified object's dispatcher. + /// + /// + /// or is null. + /// + /// + /// Only the side-effects of subscribing to the source sequence and disposing subscriptions + /// to the source sequence are run on the dispatcher associated with the specified object. + /// In order to invoke observer callbacks on the dispatcher associated with the specified + /// object, e.g. to render results in a control, use + /// . + /// + public static IObservable SubscribeOnWpfDispatcher( + this IObservable source, + DispatcherObject dispatcherObject, + DispatcherPriority priority) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (dispatcherObject == null) + { + throw new ArgumentNullException(nameof(dispatcherObject)); + } + + return SubscribeOn_(source, dispatcherObject.Dispatcher, priority); + } + + /// + /// Wraps the source sequence in order to run its subscription and unsubscription logic on + /// the dispatcher associated with the current thread. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// + /// The source sequence whose subscriptions and unsubscriptions happen on the current + /// thread's dispatcher. + /// + /// is null. + /// + /// Only the side-effects of subscribing to the source sequence and disposing subscriptions + /// to the source sequence are run on the dispatcher associated with the current thread. + /// In order to invoke observer callbacks on the dispatcher associated with the current + /// thread, e.g. to render results in a control, use + /// . + /// + public static IObservable SubscribeOnCurrentWpfDispatcher( + this IObservable source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return SubscribeOn_(source, DispatcherScheduler.Current.Dispatcher); + } + + /// + /// Wraps the source sequence in order to run its subscription and unsubscription logic on + /// the dispatcher associated with the current thread. + /// + /// The type of the elements in the source sequence. + /// Source sequence. + /// Priority to schedule work items at. + /// + /// The source sequence whose observations happen on the current thread's dispatcher. + /// + /// is null. + /// + /// Only the side-effects of subscribing to the source sequence and disposing subscriptions + /// to the source sequence are run on the dispatcher associated with the current thread. + /// In order to invoke observer callbacks on the dispatcher associated with the current + /// thread, e.g. to render results in a control, use + /// . + /// + public static IObservable SubscribeOnCurrentWpfDispatcher( + this IObservable source, + DispatcherPriority priority) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return SubscribeOn_(source, DispatcherScheduler.Current.Dispatcher, priority); + } + + private static IObservable SubscribeOn_(IObservable source, Dispatcher dispatcher, DispatcherPriority priority) + { + return Synchronization.SubscribeOn(source, new DispatcherSynchronizationContext(dispatcher, priority)); + } + + + private static IObservable SubscribeOn_(IObservable source, Dispatcher dispatcher) + { + return Synchronization.SubscribeOn(source, new DispatcherSynchronizationContext(dispatcher)); + } + + #endregion + } +} diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Wpf/build/NuGet.Readme.md b/Rx.NET/Source/src/System.Reactive.Integration.Wpf/build/NuGet.Readme.md new file mode 100644 index 000000000..a5256759a --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.Integration.Wpf/build/NuGet.Readme.md @@ -0,0 +1,26 @@ +# WPF Support for Rx.NET (Reactive Extensions for .NET) + +This library provides WPF support for the Reactive Extensions for .NET (Rx.NET). + +See the main Rx.NET package at https://www.nuget.org/packages/System.Reactive for more information about Rx.NET. + +## Rx.NET and UI Frameworks + +Up as far as Rx.NET v6.0, UI framework support has been built directly into the main `System.Reactive` package. +Unfortunately, this has caused problems since support for WPF and Windows Forms was added in .NET Core 3.1. +Because .NET Core 3.1, and all subsequent versions of .NET have supported cross-platform use, WPF and Windows +Forms are not universally available. Rx.NET used to make WPF and Windows Forms support if you targetted a +sufficiently recent version of Windows in your application TFM. But this turns out to cause problems in +some deployment models, adding as much as 90MB to the deployable size of an application. + +Consequently, starting in Rx.NET v7.0 we are moving all UI-framework-specific types, and also platform-specific +types out into separate packages. + +## Features + +This package provides replacements for two deprecated types in `System.Reactive`: + +|Type in `System.Reactive` | Replacement | Purpose | +|---|---|---| +|`DispatcherScheduler` (in `System.Reactive.Concurrency`) | `DispatcherScheduler` (in `System.Reactive.Integration.WPF`) | Provides a scheduler that schedules work on the UI thread of a WPF application. | +|`DispatcherObservable` (in `System.Reactive.Linq`) | `WindowsFormsControlObservable` (in `System.Reactive.Linq`) | Provides a set of extension methods for scheduling work on the UI thread of a WPF application. | diff --git a/Rx.NET/Source/src/System.Reactive/Concurrency/AsyncLock.cs b/Rx.NET/Source/src/System.Reactive/Concurrency/AsyncLock.cs index 9bfce6eaa..2666c4258 100644 --- a/Rx.NET/Source/src/System.Reactive/Concurrency/AsyncLock.cs +++ b/Rx.NET/Source/src/System.Reactive/Concurrency/AsyncLock.cs @@ -43,7 +43,7 @@ public void Wait(Action action) /// is null. /// In case TState is a value type, this operation will involve boxing of . /// However, this is often an improvement over the allocation of a closure object and a delegate. - internal void Wait(TState state, Action action) + public void Wait(TState state, Action action) { if (action == null) { diff --git a/Rx.NET/Source/src/System.Reactive/Concurrency/ThreadPoolScheduler.Windows.cs b/Rx.NET/Source/src/System.Reactive/Concurrency/ThreadPoolScheduler.Windows.cs index c7bd55fc4..8495cd0c1 100644 --- a/Rx.NET/Source/src/System.Reactive/Concurrency/ThreadPoolScheduler.Windows.cs +++ b/Rx.NET/Source/src/System.Reactive/Concurrency/ThreadPoolScheduler.Windows.cs @@ -15,11 +15,14 @@ namespace System.Reactive.Concurrency [CLSCompliant(false)] public sealed class ThreadPoolScheduler : LocalScheduler, ISchedulerPeriodic { +#pragma warning disable CS0618 // Type or member is obsolete. The non-UWP ThreadPoolScheduler (which will eventually supersede this) defines the zero-args constructor as private, so it's only the accessibility of "public" that is obsolete, not the presence of the constructor. So this warning is spurious in this particular case. private static readonly Lazy LazyDefault = new(static () => new ThreadPoolScheduler()); +#pragma warning restore CS0618 /// /// Constructs a ThreadPoolScheduler that schedules units of work on the Windows ThreadPool. /// + [Obsolete("If you require the UWP-specific features of ThreadPoolScheduler use the UwpThreadPoolScheduler in the System.Reactive.Integration.Uwp package. Otherwise, use the Instance property, because this constructor will be removed in a future version (because UWP applications will end up with the same ThreadPoolScheduler as all other application types).")] public ThreadPoolScheduler() { } @@ -28,6 +31,7 @@ public ThreadPoolScheduler() /// Constructs a ThreadPoolScheduler that schedules units of work on the Windows ThreadPool with the given priority. /// /// Priority for scheduled units of work. + [Obsolete("If you require the UWP-specific features of ThreadPoolScheduler use the UwpThreadPoolScheduler in the System.Reactive.Integration.Uwp package. Otherwise, use the Instance property, because this constructor will be removed in a future version (because UWP applications will end up with the same ThreadPoolScheduler as all other application types).")] public ThreadPoolScheduler(WorkItemPriority priority) { Priority = priority; @@ -39,6 +43,7 @@ public ThreadPoolScheduler(WorkItemPriority priority) /// /// Priority for scheduled units of work. /// Options that configure how work is scheduled. + [Obsolete("If you require the UWP-specific features of ThreadPoolScheduler use the UwpThreadPoolScheduler in the System.Reactive.Integration.Uwp package. Otherwise, use the Instance property, because this constructor will be removed in a future version (because UWP applications will end up with the same ThreadPoolScheduler as all other application types).")] public ThreadPoolScheduler(WorkItemPriority priority, WorkItemOptions options) { Priority = priority; @@ -60,11 +65,13 @@ public ThreadPoolScheduler(WorkItemPriority priority, WorkItemOptions options) /// /// Gets the priority at which work is scheduled. /// + [Obsolete("If you require the UWP-specific features of ThreadPoolScheduler use the UwpThreadPoolScheduler in the System.Reactive.Integration.Uwp package. This property will be removed in a future version (because UWP applications will end up with the same ThreadPoolScheduler as all other application types).")] public WorkItemPriority Priority { get; } /// /// Gets the options that configure how work is scheduled. /// + [Obsolete("If you require the UWP-specific features of ThreadPoolScheduler use the UwpThreadPoolScheduler in the System.Reactive.Integration.Uwp package. This property will be removed in a future version (because UWP applications will end up with the same ThreadPoolScheduler as all other application types).")] public WorkItemOptions Options { get; } /// @@ -81,11 +88,33 @@ public override IDisposable Schedule(TState state, Func(this, state, action); - + +#pragma warning disable CS0618 // Type or member is obsolete. + // A note on obsolescence: + // The compiler complains because this uses Priority and Options. We could mark the + // whole method as obsolete, but this would be slightly misleading because when we + // eventually remove the obsoleted UWP support, this whole ThreadPoolScheduler will + // be replaced by the non-UWP implementation, and that continues to support this + // Schedule overload. So the method isn't really obsolete - it will continue to be + // available to UWP apps even after we've removed all UWP-specific code from + // System.Reactive. + // An argument in favour of marking the method as Obsolete anyway is that the + // behaviour will change once we remove UWP code from System.Reactive. However, + // the change in behaviour is interesting only if you've specified either + // priority or options for the work items, and all the public methods we supply + // for that *are* obsolete. So anyone relying on that behaviour will already have + // received an obsolescence warning, and should move to UwpThreadPoolScheduler. + // Code that left these with the default values should not be affected by the + // change to the non-UWP ThreadPoolScheduler, so it would be irksome for them + // to get an obsolescence warning, particularly since there isn't actually + // anything they can do about it. If they want to continue using this type in + // the full knowledge that in a future version that means they'll get the + // non-UWP version, we want to let them. var res = ThreadPool.RunAsync( iaa => userWorkItem.Run(), Priority, Options); +#pragma warning restore CS0618 // Type or member is obsolete userWorkItem.CancelQueueDisposable = res.AsDisposable(); diff --git a/Rx.NET/Source/src/System.Reactive/Notification.cs b/Rx.NET/Source/src/System.Reactive/Notification.cs index 32d8acecc..17016fc34 100644 --- a/Rx.NET/Source/src/System.Reactive/Notification.cs +++ b/Rx.NET/Source/src/System.Reactive/Notification.cs @@ -7,8 +7,8 @@ using System.Globalization; using System.Reactive.Concurrency; -#pragma warning disable 0659 -#pragma warning disable 0661 +#pragma warning disable CS0659 +#pragma warning disable CS0661 namespace System.Reactive { @@ -710,5 +710,5 @@ public static Notification CreateOnCompleted() } } -#pragma warning restore 0659 -#pragma warning restore 0661 +#pragma warning restore CS0659 +#pragma warning restore CS0661 diff --git a/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Concurrency/ControlScheduler.cs b/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Concurrency/ControlScheduler.cs index 1a71b10d7..d8f029a04 100644 --- a/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Concurrency/ControlScheduler.cs +++ b/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Concurrency/ControlScheduler.cs @@ -9,8 +9,17 @@ namespace System.Reactive.Concurrency { /// - /// Represents an object that schedules units of work on the message loop associated with a Windows Forms control. + /// Obsolete. The System.Reactive.Integration.WindowsForms NuGet package defines a + /// ControlScheduler class in the System.Reactive.Integration.WindowsForms + /// namespace that replaces this class. /// + /// + /// This will eventually be removed because all UI-framework-specific functionality is being + /// removed from System.Reactive. This is necessary to fix problems in which + /// System.Reactive causes applications to end up with dependencies on Windows Forms and + /// WPF whether they want them or not. + /// + [Obsolete("Use System.Reactive.Integration.WindowsForms.ControlScheduler in the System.Reactive.Integration.WindowsForms package instead", error: false)] public class ControlScheduler : LocalScheduler, ISchedulerPeriodic { private readonly Control _control; diff --git a/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Concurrency/DispatcherScheduler.cs b/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Concurrency/DispatcherScheduler.cs index 613ec646e..c06984b69 100644 --- a/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Concurrency/DispatcherScheduler.cs +++ b/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Concurrency/DispatcherScheduler.cs @@ -9,11 +9,17 @@ namespace System.Reactive.Concurrency { /// - /// Represents an object that schedules units of work on a . + /// Obsolete. The System.Reactive.Integration.Wpf NuGet package defines a + /// DispatcherScheduler class in the System.Reactive.Integration.Wpf + /// namespace that replaces this class. /// /// - /// This scheduler type is typically used indirectly through the and methods that use the Dispatcher on the calling thread. + /// This will eventually be removed because all UI-framework-specific functionality is being + /// removed from System.Reactive. This is necessary to fix problems in which + /// System.Reactive causes applications to end up with dependencies on Windows Forms and + /// WPF whether they want them or not. /// + [Obsolete("Use System.Reactive.Integration.Wpf.DispatcherScheduler in the System.Reactive.Integration.Wpf package instead", error: false)] public class DispatcherScheduler : LocalScheduler, ISchedulerPeriodic { /// diff --git a/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Linq/ControlObservable.cs b/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Linq/ControlObservable.cs index c9e1f3d8c..77bb9d72a 100644 --- a/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Linq/ControlObservable.cs +++ b/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Linq/ControlObservable.cs @@ -8,12 +8,51 @@ namespace System.Reactive.Linq { /// - /// Provides a set of static methods for subscribing to IObservables using Windows Forms controls. + /// Obsolete. The System.Reactive.Integration.WindowsForms NuGet package defines a + /// WindowsFormsControlObservable class that defines new extension methods to be used in + /// place of these (also in the System.Reactive.Linq namespace). /// + /// + /// + /// The replacement WindowsFormsControlObservable class uses different names for extension + /// methods. When you migrate to that new class from this obsolete one, you will need to change + /// your code to invoke different method names: + /// + /// + /// Rx <= 6.0Now + /// + /// ObserveOn + /// ObserveOnWindowsFormsControl + /// + /// + /// SubscribeOn + /// SubscribeOnWindowFormsControl + /// + /// + /// + /// This will eventually be removed because all UI-framework-specific functionality is being + /// removed from System.Reactive. This is necessary to fix problems in which + /// System.Reactive causes applications to end up with dependencies on Windows Forms and + /// WPF whether they want them or not. + /// + /// + /// Rx defines extension methods for in either the + /// System.Reactive.Linq or System namespaces. This means the replacement for + /// this obsolete class has to use different names. We need to retain these old obsolete + /// extension methods for many years to provide code using Rx with time to adapt, which means + /// the new extension methods must coexist with these old obsolete ones. Extension methods + /// are awkward to fully qualify, making it easier for migrating code if the new methods have + /// visibly different names (and not the same names on a new type). + /// + /// + [Obsolete("Use the extension methods defined by the System.Reactive.Linq.WindowsFormsControlObservable class in the System.Reactive.Integration.WindowsForms package instead", error: false)] + public static class ControlObservable { /// - /// Wraps the source sequence in order to run its subscription and unsubscription logic on the Windows Forms message loop associated with the specified control. + /// Obsolete. Use the SubscribeOnWindowFormsControl extension method defined by + /// System.Reactive.Linq.WindowsFormsControlObservable in the + /// System.Reactive.Integration.WindowsForms package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -24,6 +63,7 @@ public static class ControlObservable /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the specified control. /// In order to invoke observer callbacks on the specified control, e.g. to render results in a control, use . /// + [Obsolete("Use the SubscribeOnWindowFormsControl extension method defined by System.Reactive.Linq.WindowsFormsControlObservable in the System.Reactive.Integration.WindowsForms package instead", error: false)] public static IObservable SubscribeOn(this IObservable source, Control control) { if (source == null) @@ -40,13 +80,16 @@ public static IObservable SubscribeOn(this IObservable - /// Wraps the source sequence in order to run its observer callbacks on the Windows Forms message loop associated with the specified control. + /// Obsolete. Use the ObserveOnWindowsFormsControl extension method defined by + /// System.Reactive.Linq.WindowsFormsControlObservable in the + /// System.Reactive.Integration.WindowsForms package instead. /// /// The type of the elements in the source sequence. /// Source sequence. /// Windows Forms control whose associated message loop is used to notify observers on. /// The source sequence whose observations happen on the Windows Forms message loop associated with the specified control. /// or is null. + [Obsolete("Use the ObserveOnWindowsFormsControl extension method defined by System.Reactive.Linq.WindowsFormsControlObservable in the System.Reactive.Integration.WindowsForms package instead", error: false)] public static IObservable ObserveOn(this IObservable source, Control control) { if (source == null) diff --git a/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Linq/DispatcherObservable.cs b/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Linq/DispatcherObservable.cs index 1044a7ab5..2005fcd4b 100644 --- a/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Linq/DispatcherObservable.cs +++ b/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Linq/DispatcherObservable.cs @@ -9,20 +9,73 @@ namespace System.Reactive.Linq { /// - /// Provides a set of extension methods for scheduling actions performed through observable sequences on UI dispatchers. + /// Obsolete. The System.Reactive.Integration.Wpf NuGet package defines a + /// WpfDispatcherObservable class that defines new extension methods to be used in + /// place of these (also in the System.Reactive.Linq namespace). /// + /// + /// + /// The replacement WpfDispatcherObservable class uses different names for extension + /// methods. When you migrate to that new class from this obsolete one, you will need to change + /// your code to invoke different method names: + /// + /// + /// Rx <= 6.0Now + /// + /// ObserveOn (except for overload taking a DispatcherScheduler + /// ObserveOnWpfDispatcher + /// + /// + /// ObserveOnDispatcher + /// ObserveOnCurrentWpfDispatcher + /// + /// + /// SubscribeOn (except for overload taking a DispatcherScheduler + /// SubscribeOnWpfDispatcher + /// + /// + /// SubscribeOnDispatcher + /// SubscribeOnCurrentWpfDispatcher + /// + /// + /// + /// The overloads accepting a don't need to be renamed because + /// there is no scope for ambiguity: if you pass the non-obsolete + /// defined in this package, you will get the corresponding non-obsolete overload. (Code using + /// the old obsolete DispatcherScheduler will get the old obsolete overload.) + /// + /// + /// This will eventually be removed because all UI-framework-specific functionality is being + /// removed from System.Reactive. This is necessary to fix problems in which + /// System.Reactive causes applications to end up with dependencies on Windows Forms and + /// WPF whether they want them or not. + /// + /// + /// Rx defines extension methods for in either the + /// System.Reactive.Linq or System namespaces. This means the replacement for + /// this obsolete class has to use different names. We need to retain these old obsolete + /// extension methods for many years to provide code using Rx with time to adapt, which means + /// the new extension methods must coexist with these old obsolete ones. Extension methods + /// are awkward to fully qualify, making it easier for migrating code if the new methods have + /// visibly different names (and not the same names on a new type). + /// + /// + [Obsolete("Use the extension methods defined by the System.Reactive.Linq.WpfDispatcherObservable class in the System.Reactive.Integration.Wpf package instead", error: false)] public static class DispatcherObservable { #region ObserveOn[Dispatcher] /// - /// Wraps the source sequence in order to run its observer callbacks on the specified dispatcher. + /// Obsolete. Use the ObserveOnWpfDispatcher extension method defined by + /// System.Reactive.Linq.WpfDispatcherObservable in the + /// System.Reactive.Integration.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. /// Dispatcher whose associated message loop is used to notify observers on. /// The source sequence whose observations happen on the specified dispatcher. /// or is null. + [Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] public static IObservable ObserveOn(this IObservable source, Dispatcher dispatcher) { if (source == null) @@ -39,7 +92,9 @@ public static IObservable ObserveOn(this IObservable } /// - /// Wraps the source sequence in order to run its observer callbacks on the specified dispatcher. + /// Obsolete. Use the ObserveOnWpfDispatcher extension method defined by + /// System.Reactive.Linq.WpfDispatcherObservable in the + /// System.Reactive.Integration.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -47,6 +102,7 @@ public static IObservable ObserveOn(this IObservable /// Priority to schedule work items at. /// The source sequence whose observations happen on the specified dispatcher. /// or is null. + [Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] public static IObservable ObserveOn(this IObservable source, Dispatcher dispatcher, DispatcherPriority priority) { if (source == null) @@ -63,13 +119,16 @@ public static IObservable ObserveOn(this IObservable } /// - /// Wraps the source sequence in order to run its observer callbacks on the specified dispatcher scheduler. + /// Obsolete. Use the ObserveOnWpfDispatcher extension method defined by + /// System.Reactive.Linq.WpfDispatcherObservable in the + /// System.Reactive.Integration.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. /// Dispatcher scheduler to notify observers on. /// The source sequence whose observations happen on the specified dispatcher scheduler. /// or is null. + [Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] public static IObservable ObserveOn(this IObservable source, DispatcherScheduler scheduler) { if (source == null) @@ -85,15 +144,17 @@ public static IObservable ObserveOn(this IObservable return ObserveOn_(source, scheduler.Dispatcher, scheduler.Priority); } - /// - /// Wraps the source sequence in order to run its observer callbacks on the dispatcher associated with the specified object. + /// Obsolete. Use the ObserveOnWpfDispatcher extension method defined by + /// System.Reactive.Linq.WpfDispatcherObservable in the + /// System.Reactive.Integration.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. /// Object to get the dispatcher from. /// The source sequence whose observations happen on the specified object's dispatcher. /// or is null. + [Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] public static IObservable ObserveOn(this IObservable source, DispatcherObject dispatcherObject) { if (source == null) @@ -110,7 +171,9 @@ public static IObservable ObserveOn(this IObservable } /// - /// Wraps the source sequence in order to run its observer callbacks on the dispatcher associated with the specified object. + /// Obsolete. Use the ObserveOnWpfDispatcher extension method defined by + /// System.Reactive.Linq.WpfDispatcherObservable in the + /// System.Reactive.Integration.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -118,6 +181,7 @@ public static IObservable ObserveOn(this IObservable /// Priority to schedule work items at. /// The source sequence whose observations happen on the specified object's dispatcher. /// or is null. + [Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] public static IObservable ObserveOn(this IObservable source, DispatcherObject dispatcherObject, DispatcherPriority priority) { if (source == null) @@ -133,14 +197,16 @@ public static IObservable ObserveOn(this IObservable return ObserveOn_(source, dispatcherObject.Dispatcher, priority); } - /// - /// Wraps the source sequence in order to run its observer callbacks on the dispatcher associated with the current thread. + /// Obsolete. Use the ObserveOnCurrentWpfDispatcher extension method defined by + /// System.Reactive.Linq.WpfDispatcherObservable in the + /// System.Reactive.Integration.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. /// The source sequence whose observations happen on the current thread's dispatcher. /// is null. + [Obsolete("Use the ObserveOnCurrentWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] public static IObservable ObserveOnDispatcher(this IObservable source) { if (source == null) @@ -152,13 +218,16 @@ public static IObservable ObserveOnDispatcher(this IObservable } /// - /// Wraps the source sequence in order to run its observer callbacks on the dispatcher associated with the current thread. + /// Obsolete. Use the ObserveOnCurrentWpfDispatcher extension method defined by + /// System.Reactive.Linq.WpfDispatcherObservable in the + /// System.Reactive.Integration.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. /// Priority to schedule work items at. /// The source sequence whose observations happen on the current thread's dispatcher. /// is null. + [Obsolete("Use the ObserveOnCurrentWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] public static IObservable ObserveOnDispatcher(this IObservable source, DispatcherPriority priority) { if (source == null) @@ -185,7 +254,9 @@ private static IObservable ObserveOn_(IObservable sou #region SubscribeOn[Dispatcher] /// - /// Wraps the source sequence in order to run its subscription and unsubscription logic on the specified dispatcher. + /// Obsolete. Use the SubscribeOnWpfDispatcher extension method defined by + /// System.Reactive.Linq.WpfDispatcherObservable in the + /// System.Reactive.Integration.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -196,6 +267,7 @@ private static IObservable ObserveOn_(IObservable sou /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the specified dispatcher. /// In order to invoke observer callbacks on the specified dispatcher, e.g. to render results in a control, use . /// + [Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] public static IObservable SubscribeOn(this IObservable source, Dispatcher dispatcher) { if (source == null) @@ -212,7 +284,9 @@ public static IObservable SubscribeOn(this IObservable - /// Wraps the source sequence in order to run its subscription and unsubscription logic on the specified dispatcher. + /// Obsolete. Use the SubscribeOnWpfDispatcher extension method defined by + /// System.Reactive.Linq.WpfDispatcherObservable in the + /// System.Reactive.Integration.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -224,6 +298,7 @@ public static IObservable SubscribeOn(this IObservable. /// + [Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] public static IObservable SubscribeOn(this IObservable source, Dispatcher dispatcher, DispatcherPriority priority) { if (source == null) @@ -239,9 +314,10 @@ public static IObservable SubscribeOn(this IObservable - /// Wraps the source sequence in order to run its subscription and unsubscription logic on the specified dispatcher scheduler. + /// Obsolete. Use the SubscribeOnWpfDispatcher extension method defined by + /// System.Reactive.Linq.WpfDispatcherObservable in the + /// System.Reactive.Integration.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -252,6 +328,7 @@ public static IObservable SubscribeOn(this IObservable. /// + [Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] public static IObservable SubscribeOn(this IObservable source, DispatcherScheduler scheduler) { if (source == null) @@ -268,7 +345,9 @@ public static IObservable SubscribeOn(this IObservable - /// Wraps the source sequence in order to run its subscription and unsubscription logic on the dispatcher associated with the specified object. + /// Obsolete. Use the SubscribeOnWpfDispatcher extension method defined by + /// System.Reactive.Linq.WpfDispatcherObservable in the + /// System.Reactive.Integration.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -279,6 +358,7 @@ public static IObservable SubscribeOn(this IObservable. /// + [Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] public static IObservable SubscribeOn(this IObservable source, DispatcherObject dispatcherObject) { if (source == null) @@ -295,7 +375,9 @@ public static IObservable SubscribeOn(this IObservable - /// Wraps the source sequence in order to run its subscription and unsubscription logic on the dispatcher associated with the specified object. + /// Obsolete. Use the SubscribeOnWpfDispatcher extension method defined by + /// System.Reactive.Linq.WpfDispatcherObservable in the + /// System.Reactive.Integration.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -307,6 +389,7 @@ public static IObservable SubscribeOn(this IObservable. /// + [Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] public static IObservable SubscribeOn(this IObservable source, DispatcherObject dispatcherObject, DispatcherPriority priority) { if (source == null) @@ -323,7 +406,9 @@ public static IObservable SubscribeOn(this IObservable - /// Wraps the source sequence in order to run its subscription and unsubscription logic on the dispatcher associated with the current thread. + /// Obsolete. Use the SubscribeOnCurrentWpfDispatcher extension method defined by + /// System.Reactive.Linq.WpfDispatcherObservable in the + /// System.Reactive.Integration.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -333,6 +418,7 @@ public static IObservable SubscribeOn(this IObservable. /// + [Obsolete("Use the SubscribeOnCurrentWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] public static IObservable SubscribeOnDispatcher(this IObservable source) { if (source == null) @@ -344,7 +430,9 @@ public static IObservable SubscribeOnDispatcher(this IObservab } /// - /// Wraps the source sequence in order to run its subscription and unsubscription logic on the dispatcher associated with the current thread. + /// Obsolete. Use the SubscribeOnCurrentWpfDispatcher extension method defined by + /// System.Reactive.Linq.WpfDispatcherObservable in the + /// System.Reactive.Integration.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -355,6 +443,7 @@ public static IObservable SubscribeOnDispatcher(this IObservab /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the dispatcher associated with the current thread. /// In order to invoke observer callbacks on the dispatcher associated with the current thread, e.g. to render results in a control, use . /// + [Obsolete("Use the SubscribeOnCurrentWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] public static IObservable SubscribeOnDispatcher(this IObservable source, DispatcherPriority priority) { if (source == null) diff --git a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Concurrency/CoreDispatcherScheduler.cs b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Concurrency/CoreDispatcherScheduler.cs index ccba5d225..439db5996 100644 --- a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Concurrency/CoreDispatcherScheduler.cs +++ b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Concurrency/CoreDispatcherScheduler.cs @@ -8,18 +8,21 @@ using System.Threading; using Windows.System; using Windows.UI.Core; -#if HAS_OS_XAML -using Windows.UI.Xaml; -#endif namespace System.Reactive.Concurrency { /// - /// Represents an object that schedules units of work on a . + /// Obsolete. The System.Reactive.Integration.WindowsForms NuGet package defines a + /// ControlScheduler class in the System.Reactive.Integration.WindowsForms + /// namespace that replaces this class. /// /// - /// This scheduler type is typically used indirectly through the and methods that use the current CoreDispatcher. + /// This will eventually be removed because all UI-framework-specific functionality is being + /// removed from System.Reactive. This is necessary to fix problems in which + /// System.Reactive causes applications to end up with dependencies on Windows Forms and + /// WPF whether they want them or not. /// + [Obsolete("Use System.Reactive.Integration.WindowsRuntime.CoreDispatcherScheduler in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] [CLSCompliant(false)] public sealed class CoreDispatcherScheduler : LocalScheduler, ISchedulerPeriodic { diff --git a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/EventPatternSource.cs b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/EventPatternSource.cs index 409a4abf8..6a474a651 100644 --- a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/EventPatternSource.cs +++ b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/EventPatternSource.cs @@ -7,6 +7,10 @@ namespace System.Reactive { + /// + /// Legacy implementation of obsolete + /// + [Obsolete] internal class EventPatternSource : EventPatternSourceBase, IEventPatternSource { public EventPatternSource(IObservable> source, Action, /*object,*/ EventPattern> invokeHandler) diff --git a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Foundation/AsyncInfoExtensions.cs b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Foundation/AsyncInfoExtensions.cs index 895db79c4..33817469e 100644 --- a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Foundation/AsyncInfoExtensions.cs +++ b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Foundation/AsyncInfoExtensions.cs @@ -9,9 +9,20 @@ namespace System.Reactive.Windows.Foundation { /// - /// Provides conversions from Windows Runtime asynchronous actions and operations to observable sequences. + /// Obsolete. Use the AsyncInfoObservableExtensions class in the + /// System.Reactive.Integration.WindowsRuntime namespace in the + /// System.Reactive.Integration.WindowsRuntime package instead. /// + /// + /// + /// Since this obsolete class is the only public type in the System.Reactive.Windows.Foundation + /// namespace, existing code will normally need only to replace a using directive of + /// using System.Reactive.Windows.Foundation; with + /// using System.Reactive.Integration.WindowsRuntime;. + /// + /// [CLSCompliant(false)] + [Obsolete("Use the System.Reactive.Integration.WindowsRuntime.AsyncInfoObservableExtensions class in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static class AsyncInfoObservableExtensions { #region IAsyncAction and IAsyncActionWithProgress diff --git a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Foundation/AsyncInfoToObservableBridge.cs b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Foundation/AsyncInfoToObservableBridge.cs index 463b720ba..40b0ebecc 100644 --- a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Foundation/AsyncInfoToObservableBridge.cs +++ b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Foundation/AsyncInfoToObservableBridge.cs @@ -8,6 +8,15 @@ namespace System.Reactive.Windows.Foundation { + /// + /// Used only by the obsolete type. + /// + /// The type of the asynchronous operation's result. + /// The type of the reported progress objects, which get ignored by this conversion. + /// + /// This should be removed when is eventually removed. + /// + [Obsolete] internal class AsyncInfoToObservableBridge : ObservableBase { private readonly Action> _onCompleted; diff --git a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/IEventPatternSource.cs b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/IEventPatternSource.cs index 4d4f267ad..e4e2742fe 100644 --- a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/IEventPatternSource.cs +++ b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/IEventPatternSource.cs @@ -8,11 +8,65 @@ namespace System.Reactive { /// - /// Represents a data stream signaling its elements by means of an event. + /// Obsolete. The System.Reactive.Integration.WindowsRuntime NuGet package defines an + /// ITypedEventPatternSource class that should be used instead. /// /// Sender type. /// Event arguments type. + /// + /// + /// This type is specific to Windows Runtime, because the member uses the + /// type. This interface has therefore been + /// marked as Obsolete as part of a drive to remove all UI-framework-specific and platform- + /// specific types and members from the main System.Reactive package. + /// + /// + /// The replacement type is not just in a different package and namespace. Its name has been + /// changed. There are two reasons. + /// + /// + /// First, the choice of name and namespace implied, wrongly, that this was a general purpose + /// type like or + /// . It is not, because it can't exist in TFMs + /// where Windows Runtime is unavailable, such as net8.0 or netstandard2.0. It + /// was especially confusing to give this the same name as the single-type-argument + /// , which has no such restriction. By differing + /// only in the number of type arguments, these types strongly implied that they were just + /// different forms of the same thing, when one was in fact only possible to use on certain + /// Windows targets. + /// + /// + /// Second, the fact that this was placed in the System.Reactive namespace means that + /// simply adding a replacement type with the same simple name in a different namespace is + /// likely to cause problems, because code may well have System.Reactive in scope for + /// other reasons. This could make it difficult for code to move cleanly onto the new + /// definition for as long as the old one remains present in Obsolete form, because it + /// might not always be possible to replace using System.Reactive; with, say, + /// using System.Reactive.Integration.WindowsRuntime; + /// + /// + /// The main reason for pushing such code out into separate packages is to avoid a problem in + /// which applications with a Windows-specific TFM end up acquiring dependencies on WPF and + /// Windows Forms when they take a dependency on System.Reactive regardless of whether + /// they are actually using those UI frameworks. In principle, we don't need to remove this + /// particular interface because is not + /// technically specific to one framework. (It gets used in both UWP and WinUI. And since you + /// can use WinRT APIs in Windows Forms, WPF, and even Console applications, technically those + /// can use it too, although in most cases they wouldn't.) However, leaving Windows Runtime + /// APIs in the main System.Reactive component would mean we would still need to produce + /// both netX.0 and netX.0-windows10.0.YYYYY TFMs even after we finally remove + /// all of the Obsolete types and members. People regularly get confused by the fact that in + /// the Rx v >=6.0 design, to get WPF or Windows Forms support today you need to use a suitably + /// recent Windows-specific TFM. If we retained that TFM but removed the UI framework support + /// from it leaving just the non-UI-framework-specific WinRT support) it seems likely that we + /// would cause even more confusion. So we want to get System.Reactive to a state where, + /// once we've removed all Obsolete types andmembers, we will need only non-OS-specific TFMs. + /// We are therefore moving all Windows Runtime/Foundation support out into a separate package + /// as well + /// + /// [CLSCompliant(false)] + [Obsolete("Use the System.Reactive.Integration.WindowsRuntime.IEventPatternSource interface in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public interface IEventPatternSource { /// diff --git a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/AsyncInfoObservable.cs b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/AsyncInfoObservable.cs index 0dff13549..ed67e7605 100644 --- a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/AsyncInfoObservable.cs +++ b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/AsyncInfoObservable.cs @@ -12,21 +12,88 @@ namespace System.Reactive.Linq { /// - /// Provides a set of extension methods to expose observable sequences as Windows Runtime asynchronous actions and operations. + /// Obsolete. The System.Reactive.Integration.WindowsRuntime NuGet package defines a + /// WindowsRuntimeAsyncInfoObservable class that defines new extension methods to be used in + /// place of these (also in the System.Reactive.Linq namespace). /// + /// + /// + /// The replacement WindowsRuntimeAsyncInfoObservable class uses different method names. + /// When you migrate to that new class from this obsolete one, you will need to change your code + /// to invoke different method names: + /// + /// + /// Rx <= 6.0Now + /// + /// ToAsyncAction + /// ToIAsyncAction + /// + /// + /// ToAsyncActionWithProgress + /// ToIAsyncActionWithProgress + /// + /// + /// ToAsyncOperation + /// ToIAsyncOperation + /// + /// + /// ToAsyncOperationWithProgress + /// ToIAsyncOperationWithProgress + /// + /// + /// + /// This name change is necessary because of a limitation of the Obsolete attribute: if + /// you want to move an existing method into a different package, and you leave the old one in + /// place (and marked as Obsolete) for a few versions to enable a gradual transition to + /// the new one, you will cause a problem if you keep the method name the same. The problem + /// is that both the old and new extension methods will be in scope simultaneously, so the + /// compiler will complain of ambiguity when you try to use them. In some cases you can + /// mitigate this by defining the new type in a different namespace, but the problem is that + /// these extension methods for are defined in the + /// System.Reactive.Linq namespace. Code often brings that namespace into scope for more + /// than one reason, so we can't just tell developers to replace using + /// System.Reactive.Linq; with some other namespace. While that might fix the ambiguity + /// problem, it's likely to cause a load of new problems instead. + /// + /// + /// The only practical solution for this is for the new methods to have different names than + /// the old ones. (There is a proposal for being able to annotate a method as being for binary + /// compatibility only, but it will be some time before that is available to all projects using + /// Rx.NET.) + /// + /// + /// This type will eventually be removed because all UI-framework-specific functionality is + /// being removed from System.Reactive. This is necessary to fix problems in which + /// System.Reactive causes applications to end up with dependencies on Windows Forms and + /// WPF whether they want them or not. Strictly speaking, the , + /// , + /// and types that this class + /// supports are part of Windows Runtime, and aren't specific to a single UI framework. These + /// types are used routinely in both UWP and WinUI applications, but it's also possible to use + /// them from Windows Forms, WPF, and even console applications. These types are effectively + /// WinRT native way of representing what the TPL's various Task types represent in a purely + /// .NET world. Even so, once support for genuinely UI-framework-specific types (such as + /// WPF's Dispatcher) has been removed from Rx.NET, support for these Windows Runtime + /// types would require us to continue to offer netX.0 and netX.0-windows10.0.YYYYY + /// TFMs. The fact that we offer both has caused confusion because it's quite possible to get the + /// former even when running on Windows. + /// + /// + [Obsolete("Use the extension methods defined by the System.Reactive.Linq.WindowsRuntimeAsyncInfoObservable class in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] [CLSCompliant(false)] public static class AsyncInfoObservable { #region IAsyncAction /// - /// Creates a Windows Runtime asynchronous action that represents the completion of the observable sequence. - /// Upon cancellation of the asynchronous action, the subscription to the source sequence will be disposed. + /// Obsolete. Use the WindowsRuntimeAsyncInfoObservable.ToIAsyncAction method in the + /// System.Reactive.Integration.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence to expose as an asynchronous action. /// Windows Runtime asynchronous action object representing the completion of the observable sequence. /// is null. + [Obsolete("Use the ToIAsyncAction extension method defined by System.Reactive.Linq.WindowsRuntimeAsyncInfoObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IAsyncAction ToAsyncAction(this IObservable source) { if (source == null) @@ -40,13 +107,14 @@ public static IAsyncAction ToAsyncAction(this IObservable sour #region Progress /// - /// Creates a Windows Runtime asynchronous action that represents the completion of the observable sequence, reporting incremental progress for each element produced by the sequence. - /// Upon cancellation of the asynchronous action, the subscription to the source sequence will be disposed. + /// Obsolete. Use the WindowsRuntimeAsyncInfoObservable.ToIAsyncActionWithProgress + /// method in the System.Reactive.Integration.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence to expose as an asynchronous action. /// Windows Runtime asynchronous action object representing the completion of the observable sequence, reporting incremental progress for each source sequence element. /// is null. + [Obsolete("Use the ToIAsyncActionWithProgress extension method defined by System.Reactive.Linq.WindowsRuntimeAsyncInfoObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IAsyncActionWithProgress ToAsyncActionWithProgress(this IObservable source) { if (source == null) @@ -62,8 +130,8 @@ public static IAsyncActionWithProgress ToAsyncActionWithProgress(t } /// - /// Creates a Windows Runtime asynchronous action that represents the completion of the observable sequence, using a selector function to map the source sequence on a progress reporting sequence. - /// Upon cancellation of the asynchronous action, the subscription to the source sequence will be disposed. + /// Obsolete. Use the WindowsRuntimeAsyncInfoObservable.ToIAsyncActionWithProgress + /// method in the System.Reactive.Integration.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// The type of the elements in the progress sequence. @@ -71,6 +139,7 @@ public static IAsyncActionWithProgress ToAsyncActionWithProgress(t /// Selector function to map the source sequence on a progress reporting sequence. /// Windows Runtime asynchronous action object representing the completion of the result sequence, reporting progress computed through the progress sequence. /// or is null. + [Obsolete("Use the ToIAsyncActionWithProgress extension method defined by System.Reactive.Linq.WindowsRuntimeAsyncInfoObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IAsyncActionWithProgress ToAsyncActionWithProgress(this IObservable source, Func, IObservable> progressSelector) { if (source == null) @@ -107,13 +176,14 @@ public static IAsyncActionWithProgress ToAsyncActionWithProgress /// - /// Creates a Windows Runtime asynchronous operation that returns the last element of the observable sequence. - /// Upon cancellation of the asynchronous operation, the subscription to the source sequence will be disposed. + /// Obsolete. Use the WindowsRuntimeAsyncInfoObservable.ToAsyncOperation method in + /// the System.Reactive.Integration.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence to expose as an asynchronous operation. /// Windows Runtime asynchronous operation object that returns the last element of the observable sequence. /// is null. + [Obsolete("Use the ToIAsyncOperation extension method defined by System.Reactive.Linq.WindowsRuntimeAsyncInfoObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IAsyncOperation ToAsyncOperation(this IObservable source) { if (source == null) @@ -125,13 +195,14 @@ public static IAsyncOperation ToAsyncOperation(this IObservabl } /// - /// Creates a Windows Runtime asynchronous operation that returns the last element of the observable sequence, reporting incremental progress for each element produced by the sequence. - /// Upon cancellation of the asynchronous operation, the subscription to the source sequence will be disposed. + /// Obsolete. Use the WindowsRuntimeAsyncInfoObservable.ToIAsyncOperationWithProgress + /// method in the System.Reactive.Integration.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence to expose as an asynchronous operation. /// Windows Runtime asynchronous operation object that returns the last element of the observable sequence, reporting incremental progress for each source sequence element. /// is null. + [Obsolete("Use the ToIAsyncOperationWithProgress extension method defined by System.Reactive.Linq.WindowsRuntimeAsyncInfoObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IAsyncOperationWithProgress ToAsyncOperationWithProgress(this IObservable source) { if (source == null) @@ -149,8 +220,8 @@ public static IAsyncOperationWithProgress ToAsyncOperationWithProg #region Progress /// - /// Creates a Windows Runtime asynchronous operation that returns the last element of the result sequence, reporting incremental progress for each element produced by the source sequence. - /// Upon cancellation of the asynchronous operation, the subscription to the source sequence will be disposed. + /// Obsolete. Use the WindowsRuntimeAsyncInfoObservable.ToIAsyncOperationWithProgress + /// method in the System.Reactive.Integration.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// The type of the elements in the result sequence. @@ -158,6 +229,7 @@ public static IAsyncOperationWithProgress ToAsyncOperationWithProg /// Selector function to map the source sequence on a result sequence. /// Windows Runtime asynchronous operation object that returns the last element of the result sequence, reporting incremental progress for each source sequence element. /// or is null. + [Obsolete("Use the ToIAsyncOperationWithProgress extension method defined by System.Reactive.Linq.WindowsRuntimeAsyncInfoObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IAsyncOperationWithProgress ToAsyncOperationWithProgress(this IObservable source, Func, IObservable> resultSelector) { if (source == null) @@ -178,8 +250,8 @@ public static IAsyncOperationWithProgress ToAsyncOperationWithProg } /// - /// Creates a Windows Runtime asynchronous operation that returns the last element of the result sequence, using a selector function to map the source sequence on a progress reporting sequence. - /// Upon cancellation of the asynchronous operation, the subscription to the source sequence will be disposed. + /// Obsolete. Use the WindowsRuntimeAsyncInfoObservable.ToIAsyncOperationWithProgress + /// method in the System.Reactive.Integration.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// The type of the elements in the result sequence. @@ -189,6 +261,7 @@ public static IAsyncOperationWithProgress ToAsyncOperationWithProg /// Selector function to map the source sequence on a progress reporting sequence. /// Windows Runtime asynchronous operation object that returns the last element of the result sequence, reporting progress computed through the progress sequence. /// or or is null. + [Obsolete("Use the ToIAsyncOperationWithProgress extension method defined by System.Reactive.Linq.WindowsRuntimeAsyncInfoObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IAsyncOperationWithProgress ToAsyncOperationWithProgress(this IObservable source, Func, IObservable> resultSelector, Func, IObservable> progressSelector) { if (source == null) diff --git a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/CoreDispatcherObservable.cs b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/CoreDispatcherObservable.cs index 1e666984e..4a799a3f7 100644 --- a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/CoreDispatcherObservable.cs +++ b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/CoreDispatcherObservable.cs @@ -13,21 +13,79 @@ namespace System.Reactive.Linq { /// - /// Provides a set of extension methods for scheduling actions performed through observable sequences on UI dispatchers. + /// Obsolete. The System.Reactive.Integration.WindowsRuntime NuGet package defines a + /// WindowsRuntimeCoreDispatcherObservable class that defines new extension methods to + /// be used in place of these (also in the System.Reactive.Linq namespace). /// + /// + /// + /// The replacement WindowsRuntimeCoreDispatcherObservable class uses different names for extension + /// methods. When you migrate to that new class from this obsolete one, you will need to change + /// your code to invoke different method names: + /// + /// + /// Rx <= 6.0Now + /// + /// ObserveOn + /// ObserveOnWindowsRuntimeCoreDispatcher + /// + /// + /// ObserveOnCoreDispatcher + /// ObserveOnCurrentWindowsRuntimeCoreDispatcher + /// + /// + /// SubscribeOn + /// SubscribeOnWindowsRuntimeCoreDispatcher + /// + /// + /// SubscribeOnCoreDispatcher + /// SubscribeOnCurrentWindowsRuntimeCoreDispatcher + /// + /// + /// + /// The name changes are necessary because of a limitation of the Obsolete attribute: if + /// you want to move an existing extension method into a different package, and you leave the + /// old one in place (and marked as Obsolete) for a few versions to enable a gradual + /// transition to the new one, you will cause a problem if you keep the method name the same. + /// The problem is that both the old and new extension methods will be in scope simultaneously, + /// so the compiler will complain of ambiguity when you try to use them. In some cases you can + /// mitigate this by defining the new type in a different namespace, but the problem is that + /// these extension methods for are defined in the + /// System.Reactive.Linq namespace. Code often brings that namespace into scope for more + /// than one reason, so we can't just tell developers to replace using + /// System.Reactive.Linq; with some other namespace. While that might fix the ambiguity + /// problem, it's likely to cause a load of new problems instead. + /// + /// + /// The only practical solution for this is for the new methods to have different names than + /// the old ones. (There is a proposal for being able to annotate a method as being for binary + /// compatibility only, but it will be some time before that is available to all projects using + /// Rx.NET.) + /// + /// + /// This type will eventually be removed because all UI-framework-specific functionality is + /// being removed from System.Reactive. This is necessary to fix problems in which + /// System.Reactive causes applications to end up with dependencies on Windows Forms and + /// WPF whether they want them or not. + /// + /// [CLSCompliant(false)] + [Obsolete("Use the extension methods defined by the System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable class in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static class CoreDispatcherObservable { #region ObserveOn[CoreDispatcher] /// - /// Wraps the source sequence in order to run its observer callbacks on the specified dispatcher. + /// Obsolete. Use the ObserveOnWindowsRuntimeCoreDispatcher extension method defined by + /// System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the + /// System.Reactive.Integration.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence. /// Dispatcher whose associated message loop is used to notify observers on. /// The source sequence whose observations happen on the specified dispatcher. /// or is null. + [Obsolete("Use the ObserveOnWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IObservable ObserveOn(this IObservable source, CoreDispatcher dispatcher) { if (source == null) @@ -44,7 +102,9 @@ public static IObservable ObserveOn(this IObservable } /// - /// Wraps the source sequence in order to run its observer callbacks on the specified dispatcher. + /// Obsolete. Use the ObserveOnWindowsRuntimeCoreDispatcher extension method defined by + /// System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the + /// System.Reactive.Integration.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -52,6 +112,7 @@ public static IObservable ObserveOn(this IObservable /// Priority to schedule work items at. /// The source sequence whose observations happen on the specified dispatcher. /// or is null. + [Obsolete("Use the ObserveOnWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IObservable ObserveOn(this IObservable source, CoreDispatcher dispatcher, CoreDispatcherPriority priority) { if (source == null) @@ -69,13 +130,16 @@ public static IObservable ObserveOn(this IObservable #if HAS_OS_XAML /// - /// Wraps the source sequence in order to run its observer callbacks on the dispatcher associated with the specified object. + /// Obsolete. Use the ObserveOnWindowsRuntimeCoreDispatcher extension method defined by + /// System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the + /// System.Reactive.Integration.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence. /// Object to get the dispatcher from. /// The source sequence whose observations happen on the specified object's dispatcher. /// or is null. + [Obsolete("Use the ObserveOnWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IObservable ObserveOn(this IObservable source, DependencyObject dependencyObject) { if (source == null) @@ -92,7 +156,9 @@ public static IObservable ObserveOn(this IObservable } /// - /// Wraps the source sequence in order to run its observer callbacks on the dispatcher associated with the specified object. + /// Obsolete. Use the ObserveOnWindowsRuntimeCoreDispatcher extension method defined by + /// System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the + /// System.Reactive.Integration.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -100,6 +166,7 @@ public static IObservable ObserveOn(this IObservable /// Priority to schedule work items at. /// The source sequence whose observations happen on the specified object's dispatcher. /// or is null. + [Obsolete("Use the ObserveOnWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IObservable ObserveOn(this IObservable source, DependencyObject dependencyObject, CoreDispatcherPriority priority) { if (source == null) @@ -116,12 +183,15 @@ public static IObservable ObserveOn(this IObservable } #endif /// - /// Wraps the source sequence in order to run its observer callbacks on the dispatcher associated with the current window. + /// Obsolete. Use the ObserveOnCurrentWindowsRuntimeCoreDispatcher extension method defined by + /// System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the + /// System.Reactive.Integration.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence. /// The source sequence whose observations happen on the current window's dispatcher. /// is null. + [Obsolete("Use the ObserveOnCurrentWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IObservable ObserveOnCoreDispatcher(this IObservable source) { if (source == null) @@ -133,13 +203,16 @@ public static IObservable ObserveOnCoreDispatcher(this IObserv } /// - /// Wraps the source sequence in order to run its observer callbacks on the dispatcher associated with the current window. + /// Obsolete. Use the ObserveOnCurrentWindowsRuntimeCoreDispatcher extension method defined by + /// System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the + /// System.Reactive.Integration.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence. /// Priority to schedule work items at. /// The source sequence whose observations happen on the current window's dispatcher. /// is null. + [Obsolete("Use the ObserveOnCurrentWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IObservable ObserveOnDispatcher(this IObservable source, CoreDispatcherPriority priority) { if (source == null) @@ -155,7 +228,9 @@ public static IObservable ObserveOnDispatcher(this IObservable #region SubscribeOn[CoreDispatcher] /// - /// Wraps the source sequence in order to run its subscription and unsubscription logic on the specified dispatcher. + /// Obsolete. Use the SubscribeOnWindowsRuntimeCoreDispatcher extension method defined by + /// System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the + /// System.Reactive.Integration.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -166,6 +241,7 @@ public static IObservable ObserveOnDispatcher(this IObservable /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the specified dispatcher. /// In order to invoke observer callbacks on the specified dispatcher, e.g. to render results in a control, use . /// + [Obsolete("Use the SubscribeOnWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IObservable SubscribeOn(this IObservable source, CoreDispatcher dispatcher) { if (source == null) @@ -182,7 +258,9 @@ public static IObservable SubscribeOn(this IObservable - /// Wraps the source sequence in order to run its subscription and unsubscription logic on the specified dispatcher. + /// Obsolete. Use the SubscribeOnWindowsRuntimeCoreDispatcher extension method defined by + /// System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the + /// System.Reactive.Integration.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -194,6 +272,7 @@ public static IObservable SubscribeOn(this IObservable. /// + [Obsolete("Use the SubscribeOnWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IObservable SubscribeOn(this IObservable source, CoreDispatcher dispatcher, CoreDispatcherPriority priority) { if (source == null) @@ -211,7 +290,9 @@ public static IObservable SubscribeOn(this IObservable - /// Wraps the source sequence in order to run its subscription and unsubscription logic on the dispatcher associated with the specified object. + /// Obsolete. Use the SubscribeOnWindowsRuntimeCoreDispatcher extension method defined by + /// System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the + /// System.Reactive.Integration.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -222,6 +303,7 @@ public static IObservable SubscribeOn(this IObservable. /// + [Obsolete("Use the SubscribeOnWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IObservable SubscribeOn(this IObservable source, DependencyObject dependencyObject) { if (source == null) @@ -238,7 +320,9 @@ public static IObservable SubscribeOn(this IObservable - /// Wraps the source sequence in order to run its subscription and unsubscription logic on the dispatcher associated with the specified object. + /// Obsolete. Use the SubscribeOnWindowsRuntimeCoreDispatcher extension method defined by + /// System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the + /// System.Reactive.Integration.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -250,6 +334,7 @@ public static IObservable SubscribeOn(this IObservable. /// + [Obsolete("Use the SubscribeOnWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IObservable SubscribeOn(this IObservable source, DependencyObject dependencyObject, CoreDispatcherPriority priority) { if (source == null) @@ -267,7 +352,9 @@ public static IObservable SubscribeOn(this IObservable - /// Wraps the source sequence in order to run its subscription and unsubscription logic on the dispatcher associated with the current window. + /// Obsolete. Use the SubscribeOnCurrentWindowsRuntimeCoreDispatcher extension method defined by + /// System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the + /// System.Reactive.Integration.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -277,6 +364,7 @@ public static IObservable SubscribeOn(this IObservable. /// + [Obsolete("Use the SubscribeOnCurrentWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IObservable SubscribeOnCoreDispatcher(this IObservable source) { if (source == null) @@ -288,7 +376,9 @@ public static IObservable SubscribeOnCoreDispatcher(this IObse } /// - /// Wraps the source sequence in order to run its subscription and unsubscription logic on the dispatcher associated with the current window. + /// Obsolete. Use the SubscribeOnCurrentWindowsRuntimeCoreDispatcher extension method defined by + /// System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the + /// System.Reactive.Integration.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -299,6 +389,7 @@ public static IObservable SubscribeOnCoreDispatcher(this IObse /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the dispatcher associated with the current window. /// In order to invoke observer callbacks on the dispatcher associated with the current window, e.g. to render results in a control, use . /// + [Obsolete("Use the SubscribeOnCurrentWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IObservable SubscribeOnDispatcher(this IObservable source, CoreDispatcherPriority priority) { if (source == null) diff --git a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/WindowsObservable.Events.cs b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/WindowsObservable.Events.cs index cc35438a8..70a12be1c 100644 --- a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/WindowsObservable.Events.cs +++ b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/WindowsObservable.Events.cs @@ -8,8 +8,74 @@ namespace System.Reactive.Linq { /// - /// Provides a set of static methods for importing typed events from Windows Runtime APIs. + /// Obsolete. The System.Reactive.Integration.WindowsRuntime NuGet package defines a + /// WindowsRuntimeObservable class (also in the System.Reactive.Linq namespace) + /// to use instead. /// + /// + /// + /// The replacement WindowsRuntimeObservable class uses different names for extension + /// methods. When you migrate to that new class from this obsolete one, you will need to change + /// your code to invoke different method names: + /// + /// + /// Rx <= 6.0Now + /// + /// ToEventPattern + /// ToWindowsFoundationEventPattern + /// + /// + /// SelectMany + /// SelectManyIAsyncOperation or SelectManyIAsyncOperationWithProgress + /// + /// + /// + /// (Note that the FromEventPattern method name has not changed.) + /// + /// + /// The name changes are necessary because of a limitation of the Obsolete attribute: if + /// you want to move an existing extension method into a different package, and you leave the + /// old one in place (and marked as Obsolete) for a few versions to enable a gradual + /// transition to the new one, you will cause a problem if you keep the method name the same. + /// The problem is that both the old and new extension methods will be in scope simultaneously, + /// so the compiler will complain of ambiguity when you try to use them. In some cases you can + /// mitigate this by defining the new type in a different namespace, but the problem is that + /// these extension methods for are defined in the + /// System.Reactive.Linq namespace. Code often brings that namespace into scope for more + /// than one reason, so we can't just tell developers to replace using + /// System.Reactive.Linq; with some other namespace. While that might fix the ambiguity + /// problem, it's likely to cause a load of new problems instead. + /// + /// + /// The only practical solution for this is for the new methods to have different names than + /// the old ones. (There is a proposal for being able to annotate a method as being for binary + /// compatibility only, but it will be some time before that is available to all projects using + /// Rx.NET.) + /// + /// + /// The FromEventPattern methods keep the same name because those are not extension + /// methods, so they are always invoked through their class name. The replacement class has a + /// different name, WindowsRuntimeObservable, so there is no ambiguity. + /// + /// + /// This type will eventually be removed because all UI-framework-specific functionality is + /// being removed from System.Reactive. This is necessary to fix problems in which + /// System.Reactive causes applications to end up with dependencies on Windows Forms and + /// WPF whether they want them or not. Strictly speaking, the , + /// , + /// and types that this class + /// supports are part of Windows Runtime, and aren't specific to a single UI framework. These + /// types are used routinely in both UWP and WinUI applications, but it's also possible to use + /// them from Windows Forms, WPF, and even console applications. These types are effectively + /// WinRT native way of representing what the TPL's various Task types represent in a purely + /// .NET world. Even so, once support for genuinely UI-framework-specific types (such as + /// WPF's Dispatcher) has been removed from Rx.NET, support for these Windows Runtime + /// types would require us to continue to offer netX.0 and netX.0-windows10.0.YYYYY + /// TFMs. The fact that we offer both has caused confusion because it's quite possible to get the + /// former even when running on Windows. + /// + /// + [Obsolete("Use the System.Reactive.Linq.WindowsRuntimeObservable class in the System.Reactive.Integration.WindowsRuntime instead", error: false)] [CLSCompliant(false)] public static partial class WindowsObservable { @@ -23,6 +89,7 @@ public static partial class WindowsObservable /// The observable sequence that contains data representations of invocations of the underlying typed event. /// or is null. /// + [Obsolete("Use the FromEventPattern method defined by System.Reactive.Linq.WindowsRuntimeObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IObservable> FromEventPattern(Action> addHandler, Action> removeHandler) { if (addHandler == null) @@ -63,6 +130,7 @@ public static IObservable> FromEventPatternThe observable sequence that contains data representations of invocations of the underlying typed event. /// or or is null. /// + [Obsolete("Use the FromEventPattern method defined by System.Reactive.Linq.WindowsRuntimeObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IObservable> FromEventPattern(Func, TDelegate> conversion, Action addHandler, Action removeHandler) { if (conversion == null) @@ -104,6 +172,7 @@ public static IObservable> FromEventPatternObservable source sequence. /// The event source object. /// is null. + [Obsolete("Use the ToWindowsFoundationEventPattern extension method defined by System.Reactive.Linq.WindowsRuntimeObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IEventPatternSource ToEventPattern(this IObservable> source) { if (source == null) diff --git a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/WindowsObservable.StandardSequenceOperators.cs b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/WindowsObservable.StandardSequenceOperators.cs index 5015c0f38..3c7429d93 100644 --- a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/WindowsObservable.StandardSequenceOperators.cs +++ b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/WindowsObservable.StandardSequenceOperators.cs @@ -20,6 +20,7 @@ public static partial class WindowsObservable /// An observable sequence whose elements are the result of the asynchronous operations executed for each element of the input sequence. /// or is null. /// This overload supports composition of observable sequences and Windows Runtime asynchronous operations, without requiring manual conversion of the asynchronous operations to observable sequences using . + [Obsolete("Use the SelectManyIAsyncOperation extension method defined by System.Reactive.Linq.WindowsRuntimeObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IObservable SelectMany(this IObservable source, Func> selector) { if (source == null) @@ -46,6 +47,7 @@ public static IObservable SelectMany(this IObservable /// An observable sequence whose elements are the result of the asynchronous operations executed for each element of the input sequence. /// or is null. /// This overload supports composition of observable sequences and Windows Runtime asynchronous operations, without requiring manual conversion of the asynchronous operations to observable sequences using . + [Obsolete("Use the SelectManyIAsyncOperationWithProgress extension method defined by System.Reactive.Linq.WindowsRuntimeObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IObservable SelectMany(this IObservable source, Func> selector) { if (source == null) @@ -73,6 +75,7 @@ public static IObservable SelectMany(this /// An observable sequence whose elements are the result of obtaining an asynchronous operation for each element of the input sequence and then mapping the asynchronous operation's result and its corresponding source element to a result element. /// or or is null. /// This overload supports using LINQ query comprehension syntax in C# and Visual Basic to compose observable sequences and Windows Runtime asynchronous operations, without requiring manual conversion of the asynchronous operations to observable sequences using . + [Obsolete("Use the SelectManyIAsyncOperation extension method defined by System.Reactive.Linq.WindowsRuntimeObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IObservable SelectMany(this IObservable source, Func> asyncOperationSelector, Func resultSelector) { if (source == null) @@ -106,6 +109,7 @@ public static IObservable SelectManyAn observable sequence whose elements are the result of obtaining an asynchronous operation for each element of the input sequence and then mapping the asynchronous operation's result and its corresponding source element to a result element. /// or or is null. /// This overload supports using LINQ query comprehension syntax in C# and Visual Basic to compose observable sequences and Windows Runtime asynchronous operations, without requiring manual conversion of the asynchronous operations to observable sequences using . + [Obsolete("Use the SelectManyIAsyncOperationWithProgress extension method defined by System.Reactive.Linq.WindowsRuntimeObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] public static IObservable SelectMany(this IObservable source, Func> asyncOperationSelector, Func resultSelector) { if (source == null) diff --git a/Rx.NET/Source/tests/Tests.System.Reactive/Tests.System.Reactive.csproj b/Rx.NET/Source/tests/Tests.System.Reactive/Tests.System.Reactive.csproj index 00d1d52dc..dbe142c20 100644 --- a/Rx.NET/Source/tests/Tests.System.Reactive/Tests.System.Reactive.csproj +++ b/Rx.NET/Source/tests/Tests.System.Reactive/Tests.System.Reactive.csproj @@ -36,4 +36,9 @@ + + + + + \ No newline at end of file diff --git a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/ControlSchedulerTest.cs b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/ControlSchedulerTest.cs index 1e84ff57a..6da3d65b7 100644 --- a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/ControlSchedulerTest.cs +++ b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/ControlSchedulerTest.cs @@ -14,6 +14,8 @@ using Microsoft.Reactive.Testing; using Assert = Xunit.Assert; +using LegacyControlScheduler = System.Reactive.Concurrency.ControlScheduler; +using ControlScheduler = System.Reactive.Integration.WindowsForms.ControlScheduler; namespace ReactiveTests.Tests { @@ -25,6 +27,7 @@ public void Ctor_ArgumentChecking() { #pragma warning disable CA1806 // (Unused new instance.) We expect the constructor to throw. ReactiveAssert.Throws(() => new ControlScheduler(null)); + ReactiveAssert.Throws(() => new LegacyControlScheduler(null)); #pragma warning restore CA1806 } @@ -33,6 +36,7 @@ public void Control() { var lbl = new Label(); Assert.Same(lbl, new ControlScheduler(lbl).Control); + Assert.Same(lbl, new LegacyControlScheduler(lbl).Control); } [TestMethod] @@ -42,6 +46,13 @@ public void Now() Assert.True(res.Seconds < 1); } + [TestMethod] + public void NowLegacy() + { + var res = new LegacyControlScheduler(new Label()).Now - DateTime.Now; + Assert.True(res.Seconds < 1); + } + [TestMethod] public void Schedule_ArgumentChecking() { @@ -51,6 +62,15 @@ public void Schedule_ArgumentChecking() ReactiveAssert.Throws(() => s.Schedule(42, DateTimeOffset.Now, default(Func))); } + [TestMethod] + public void Schedule_ArgumentChecking_Legacy() + { + var s = new LegacyControlScheduler(new Label()); + ReactiveAssert.Throws(() => s.Schedule(42, default(Func))); + ReactiveAssert.Throws(() => s.Schedule(42, TimeSpan.FromSeconds(1), default(Func))); + ReactiveAssert.Throws(() => s.Schedule(42, DateTimeOffset.Now, default(Func))); + } + [TestMethod] public void Schedule() { @@ -69,6 +89,24 @@ public void Schedule() } } + [TestMethod] + public void Schedule_Legacy() + { + using (WinFormsTestUtils.RunTest(out var lbl)) + { + var evt = new ManualResetEvent(false); + + var id = Environment.CurrentManagedThreadId; + + var sch = new LegacyControlScheduler(lbl); + + sch.Schedule(() => { lbl.Text = "Okay"; Assert.NotEqual(id, Environment.CurrentManagedThreadId); }); + sch.Schedule(() => { Assert.Equal("Okay", lbl.Text); Assert.NotEqual(id, Environment.CurrentManagedThreadId); evt.Set(); }); + + evt.WaitOne(); + } + } + [TestMethod] public void ScheduleError() { @@ -94,18 +132,55 @@ public void ScheduleError() } } + [TestMethod] + public void ScheduleError_Legacy() + { + using (WinFormsTestUtils.RunTest(out var lbl)) + { + var evt = new ManualResetEvent(false); + + var ex = new Exception(); + + lbl.Invoke(new Action(() => + { + Application.ThreadException += (o, e) => + { + Assert.Same(ex, e.Exception); + evt.Set(); + }; + })); + + var sch = new LegacyControlScheduler(lbl); + sch.Schedule(() => { throw ex; }); + + evt.WaitOne(); + } + } + [TestMethod] public void ScheduleRelative() { ScheduleRelative_(TimeSpan.FromSeconds(0.1)); } + [TestMethod] + public void ScheduleRelative_Legacy() + { + ScheduleRelative_Legacy_(TimeSpan.FromSeconds(0.1)); + } + [TestMethod] public void ScheduleRelative_Zero() { ScheduleRelative_(TimeSpan.Zero); } + [TestMethod] + public void ScheduleRelative_Zero_Legacy() + { + ScheduleRelative_Legacy_(TimeSpan.Zero); + } + private void ScheduleRelative_(TimeSpan delay) { using (WinFormsTestUtils.RunTest(out var lbl)) @@ -133,6 +208,33 @@ private void ScheduleRelative_(TimeSpan delay) } } + private void ScheduleRelative_Legacy_(TimeSpan delay) + { + using (WinFormsTestUtils.RunTest(out var lbl)) + { + var evt = new ManualResetEvent(false); + + var id = Environment.CurrentManagedThreadId; + + var sch = new LegacyControlScheduler(lbl); + + sch.Schedule(delay, () => + { + lbl.Text = "Okay"; + Assert.NotEqual(id, Environment.CurrentManagedThreadId); + + sch.Schedule(() => + { + Assert.Equal("Okay", lbl.Text); + Assert.NotEqual(id, Environment.CurrentManagedThreadId); + evt.Set(); + }); + }); + + evt.WaitOne(); + } + } + [TestMethod] public void ScheduleRelative_Nested() { @@ -164,6 +266,37 @@ public void ScheduleRelative_Nested() } } + [TestMethod] + public void ScheduleRelative_Nested_Legacy() + { + using (WinFormsTestUtils.RunTest(out var lbl)) + { + var evt = new ManualResetEvent(false); + + var id = Environment.CurrentManagedThreadId; + + var sch = new LegacyControlScheduler(lbl); + + sch.Schedule(TimeSpan.FromSeconds(0.1), () => + { + sch.Schedule(TimeSpan.FromSeconds(0.1), () => + { + lbl.Text = "Okay"; + Assert.NotEqual(id, Environment.CurrentManagedThreadId); + + sch.Schedule(() => + { + Assert.Equal("Okay", lbl.Text); + Assert.NotEqual(id, Environment.CurrentManagedThreadId); + evt.Set(); + }); + }); + }); + + evt.WaitOne(); + } + } + [TestMethod] public void ScheduleRelative_Cancel() { @@ -202,6 +335,44 @@ public void ScheduleRelative_Cancel() } } + [TestMethod] + public void ScheduleRelative_Cancel_Legacy() + { + using (WinFormsTestUtils.RunTest(out var lbl)) + { + var evt = new ManualResetEvent(false); + + var id = Environment.CurrentManagedThreadId; + + var sch = new LegacyControlScheduler(lbl); + + sch.Schedule(TimeSpan.FromSeconds(0.1), () => + { + lbl.Text = "Okay"; + Assert.NotEqual(id, Environment.CurrentManagedThreadId); + + var d = sch.Schedule(TimeSpan.FromSeconds(0.1), () => + { + lbl.Text = "Oops!"; + }); + + sch.Schedule(() => + { + d.Dispose(); + }); + + sch.Schedule(TimeSpan.FromSeconds(0.2), () => + { + Assert.Equal("Okay", lbl.Text); + Assert.NotEqual(id, Environment.CurrentManagedThreadId); + evt.Set(); + }); + }); + + evt.WaitOne(); + } + } + [TestMethod] public void SchedulePeriodic_ArgumentChecking() { @@ -213,6 +384,17 @@ public void SchedulePeriodic_ArgumentChecking() ReactiveAssert.Throws(() => s.SchedulePeriodic(42, TimeSpan.FromMilliseconds(1).Subtract(TimeSpan.FromTicks(1)), x => x)); } + [TestMethod] + public void SchedulePeriodic_ArgumentChecking_Legacy() + { + var s = new LegacyControlScheduler(new Label()); +#pragma warning disable IDE0034 // (Simplify 'default'.) Want to be explicit about overload being tested. + ReactiveAssert.Throws(() => s.SchedulePeriodic(42, TimeSpan.FromSeconds(1), default(Func))); +#pragma warning restore IDE0034 + ReactiveAssert.Throws(() => s.SchedulePeriodic(42, TimeSpan.Zero, x => x)); + ReactiveAssert.Throws(() => s.SchedulePeriodic(42, TimeSpan.FromMilliseconds(1).Subtract(TimeSpan.FromTicks(1)), x => x)); + } + [TestMethod] public void SchedulePeriodic() { @@ -255,6 +437,48 @@ public void SchedulePeriodic() } } + [TestMethod] + public void SchedulePeriodic_Legacy() + { + using (WinFormsTestUtils.RunTest(out var lbl)) + { + var evt = new ManualResetEvent(false); + + var id = Environment.CurrentManagedThreadId; + + var sch = new LegacyControlScheduler(lbl); + + var d = new SingleAssignmentDisposable(); + + d.Disposable = sch.SchedulePeriodic(1, TimeSpan.FromSeconds(0.1), n => + { + lbl.Text = "Okay " + n; + Assert.NotEqual(id, Environment.CurrentManagedThreadId); + + if (n == 3) + { + d.Dispose(); + + sch.Schedule(TimeSpan.FromSeconds(0.2), () => + { + Assert.Equal("Okay 3", lbl.Text); + Assert.NotEqual(id, Environment.CurrentManagedThreadId); + evt.Set(); + }); + } + + if (n > 3) + { + Assert.True(false); + } + + return n + 1; + }); + + evt.WaitOne(); + } + } + [TestMethod] public void SchedulePeriodic_Nested() { @@ -296,6 +520,48 @@ public void SchedulePeriodic_Nested() evt.WaitOne(); } } + + [TestMethod] + public void SchedulePeriodic_Nested_Legacy() + { + using (WinFormsTestUtils.RunTest(out var lbl)) + { + var evt = new ManualResetEvent(false); + + var id = Environment.CurrentManagedThreadId; + + var sch = new LegacyControlScheduler(lbl); + + sch.Schedule(() => + { + lbl.Text = "Okay"; + + var d = new SingleAssignmentDisposable(); + + d.Disposable = sch.SchedulePeriodic(1, TimeSpan.FromSeconds(0.1), n => + { + lbl.Text = "Okay " + n; + Assert.NotEqual(id, Environment.CurrentManagedThreadId); + + if (n == 3) + { + d.Dispose(); + + sch.Schedule(TimeSpan.FromSeconds(0.2), () => + { + Assert.Equal("Okay 3", lbl.Text); + Assert.NotEqual(id, Environment.CurrentManagedThreadId); + evt.Set(); + }); + } + + return n + 1; + }); + }); + + evt.WaitOne(); + } + } } } #endif diff --git a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/DispatcherSchedulerTest.cs b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/DispatcherSchedulerTest.cs index 8ca6a9543..a2318f3a3 100644 --- a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/DispatcherSchedulerTest.cs +++ b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/DispatcherSchedulerTest.cs @@ -13,6 +13,8 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Assert = Xunit.Assert; +using LegacyDispatcherScheduler = System.Reactive.Concurrency.DispatcherScheduler; +using DispatcherScheduler = System.Reactive.Integration.Wpf.DispatcherScheduler; namespace ReactiveTests.Tests { @@ -27,6 +29,14 @@ public void Ctor_ArgumentChecking() #pragma warning restore CA1806 } + [TestMethod] + public void Ctor_ArgumentChecking_Legacy() + { +#pragma warning disable CA1806 // (Unused new instance.) We expect the constructor to throw. + ReactiveAssert.Throws(() => new LegacyDispatcherScheduler(null)); +#pragma warning restore CA1806 + } + [TestMethod] public void Current() { @@ -44,6 +54,23 @@ public void Current() } } + [TestMethod] + public void Current_Legacy() + { + using (DispatcherHelpers.RunTest(out var d)) + { + var e = new ManualResetEvent(false); + + d.BeginInvoke(() => + { + var c = LegacyDispatcherScheduler.Current; + c.Schedule(() => { e.Set(); }); + }); + + e.WaitOne(); + } + } + [TestMethod] public void Current_None() { @@ -67,6 +94,29 @@ public void Current_None() Assert.True(e != null && e is InvalidOperationException); } + [TestMethod] + public void Current_None_Legacy() + { + var e = default(Exception); + + var t = new Thread(() => + { + try + { + var ignored = LegacyDispatcherScheduler.Current; + } + catch (Exception ex) + { + e = ex; + } + }); + + t.Start(); + t.Join(); + + Assert.True(e != null && e is InvalidOperationException); + } + [TestMethod] public void Dispatcher() { @@ -76,6 +126,15 @@ public void Dispatcher() } } + [TestMethod] + public void Dispatcher_Legacy() + { + using (DispatcherHelpers.RunTest(out var disp)) + { + Assert.Same(disp.Dispatcher, new LegacyDispatcherScheduler(disp).Dispatcher); + } + } + [TestMethod] public void Now() { @@ -86,6 +145,16 @@ public void Now() } } + [TestMethod] + public void Now_Legacy() + { + using (DispatcherHelpers.RunTest(out var disp)) + { + var res = new LegacyDispatcherScheduler(disp).Now - DateTime.Now; + Assert.True(res.Seconds < 1); + } + } + [TestMethod] public void Schedule_ArgumentChecking() { @@ -98,6 +167,18 @@ public void Schedule_ArgumentChecking() } } + [TestMethod] + public void Schedule_ArgumentChecking_Legacy() + { + using (DispatcherHelpers.RunTest(out var disp)) + { + var s = new LegacyDispatcherScheduler(disp); + ReactiveAssert.Throws(() => s.Schedule(42, default(Func))); + ReactiveAssert.Throws(() => s.Schedule(42, TimeSpan.FromSeconds(1), default(Func))); + ReactiveAssert.Throws(() => s.Schedule(42, DateTimeOffset.Now, default(Func))); + } + } + [TestMethod] [Asynchronous] public void Schedule() @@ -117,6 +198,25 @@ public void Schedule() } } + [TestMethod] + [Asynchronous] + public void Schedule_Legacy() + { + using (DispatcherHelpers.RunTest(out var disp)) + { + RunAsync(evt => + { + var id = Environment.CurrentManagedThreadId; + var sch = new LegacyDispatcherScheduler(disp); + sch.Schedule(() => + { + Assert.NotEqual(id, Environment.CurrentManagedThreadId); + evt.Set(); + }); + }); + } + } + [TestMethod] public void ScheduleError() { @@ -142,18 +242,55 @@ public void ScheduleError() } } + [TestMethod] + public void ScheduleError_Legacy() + { + using (DispatcherHelpers.RunTest(out var disp)) + { + var ex = new Exception(); + + var id = Environment.CurrentManagedThreadId; + var evt = new ManualResetEvent(false); + + Exception thrownEx = null; + disp.UnhandledException += (o, e) => + { + thrownEx = e.Exception; + evt.Set(); + e.Handled = true; + }; + var sch = new LegacyDispatcherScheduler(disp); + sch.Schedule(() => { throw ex; }); + evt.WaitOne(); + + Assert.Same(ex, thrownEx); + } + } + [TestMethod] public void ScheduleRelative() { ScheduleRelative_(TimeSpan.FromSeconds(0.2)); } + [TestMethod] + public void ScheduleRelative_Legacy() + { + ScheduleRelative_Legacy_(TimeSpan.FromSeconds(0.2)); + } + [TestMethod] public void ScheduleRelative_Zero() { ScheduleRelative_(TimeSpan.Zero); } + [TestMethod] + public void ScheduleRelative_Zero_Legacy() + { + ScheduleRelative_Legacy_(TimeSpan.Zero); + } + private void ScheduleRelative_(TimeSpan delay) { using (DispatcherHelpers.RunTest(out var disp)) @@ -179,6 +316,31 @@ private void ScheduleRelative_(TimeSpan delay) } } + private void ScheduleRelative_Legacy_(TimeSpan delay) + { + using (DispatcherHelpers.RunTest(out var disp)) + { + var evt = new ManualResetEvent(false); + + var id = Environment.CurrentManagedThreadId; + + var sch = new DispatcherScheduler(disp); + + sch.Schedule(delay, () => + { + Assert.NotEqual(id, Environment.CurrentManagedThreadId); + + sch.Schedule(delay, () => + { + Assert.NotEqual(id, Environment.CurrentManagedThreadId); + evt.Set(); + }); + }); + + evt.WaitOne(); + } + } + [TestMethod] public void ScheduleRelative_Cancel() { @@ -216,6 +378,43 @@ public void ScheduleRelative_Cancel() } } + [TestMethod] + public void ScheduleRelative_Cancel_Legacy() + { + using (DispatcherHelpers.RunTest(out var disp)) + { + var evt = new ManualResetEvent(false); + + var id = Environment.CurrentManagedThreadId; + + var sch = new LegacyDispatcherScheduler(disp); + + sch.Schedule(TimeSpan.FromSeconds(0.1), () => + { + Assert.NotEqual(id, Environment.CurrentManagedThreadId); + + var d = sch.Schedule(TimeSpan.FromSeconds(0.1), () => + { + Assert.True(false); + evt.Set(); + }); + + sch.Schedule(() => + { + d.Dispose(); + }); + + sch.Schedule(TimeSpan.FromSeconds(0.2), () => + { + Assert.NotEqual(id, Environment.CurrentManagedThreadId); + evt.Set(); + }); + }); + + evt.WaitOne(); + } + } + [TestMethod] public void SchedulePeriodic_ArgumentChecking() { @@ -223,6 +422,20 @@ public void SchedulePeriodic_ArgumentChecking() { var s = new DispatcherScheduler(disp); +#pragma warning disable IDE0034 // (Simplify 'default'.) Want to be explicit about overload being tested. + ReactiveAssert.Throws(() => s.SchedulePeriodic(42, TimeSpan.FromSeconds(1), default(Func))); +#pragma warning restore IDE0034 + ReactiveAssert.Throws(() => s.SchedulePeriodic(42, TimeSpan.FromSeconds(-1), x => x)); + } + } + + [TestMethod] + public void SchedulePeriodic_ArgumentChecking_Legacy() + { + using (DispatcherHelpers.RunTest(out var disp)) + { + var s = new LegacyDispatcherScheduler(disp); + #pragma warning disable IDE0034 // (Simplify 'default'.) Want to be explicit about overload being tested. ReactiveAssert.Throws(() => s.SchedulePeriodic(42, TimeSpan.FromSeconds(1), default(Func))); #pragma warning restore IDE0034 @@ -269,6 +482,46 @@ public void SchedulePeriodic() evt.WaitOne(); } } + + [TestMethod] + public void SchedulePeriodic_Legacy() + { + using (DispatcherHelpers.RunTest(out var disp)) + { + var evt = new ManualResetEvent(false); + + var id = Environment.CurrentManagedThreadId; + + var sch = new LegacyDispatcherScheduler(disp); + + var d = new SingleAssignmentDisposable(); + + d.Disposable = sch.SchedulePeriodic(1, TimeSpan.FromSeconds(0.1), n => + { + Assert.NotEqual(id, Environment.CurrentManagedThreadId); + + if (n == 3) + { + d.Dispose(); + + sch.Schedule(TimeSpan.FromSeconds(0.2), () => + { + Assert.NotEqual(id, Environment.CurrentManagedThreadId); + evt.Set(); + }); + } + + if (n > 3) + { + Assert.True(false); + } + + return n + 1; + }); + + evt.WaitOne(); + } + } } } #endif diff --git a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/SchedulerTest.cs b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/SchedulerTest.cs index 008d3c1f8..3dac1ffa2 100644 --- a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/SchedulerTest.cs +++ b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/SchedulerTest.cs @@ -16,6 +16,13 @@ #if HAS_WINFORMS using System.Windows.Forms; +using LegacyControlScheduler = System.Reactive.Concurrency.ControlScheduler; +using ControlScheduler = System.Reactive.Integration.WindowsForms.ControlScheduler; +#endif + +#if HAS_WPF +using LegacyDispatcherScheduler = System.Reactive.Concurrency.DispatcherScheduler; +using DispatcherScheduler = System.Reactive.Integration.Wpf.DispatcherScheduler; #endif using System.Threading.Tasks; @@ -59,10 +66,14 @@ public void Schedulers_ArgumentChecks() ReactiveAssert.Throws(() => Scheduler.CurrentThread.Schedule(TimeSpan.Zero, default(Action))); ReactiveAssert.Throws(() => Scheduler.CurrentThread.Schedule(DateTimeOffset.MaxValue, default(Action))); #if DESKTOPCLR - ReactiveAssert.Throws(() => DispatcherScheduler.Instance.Schedule(default(Action))); - ReactiveAssert.Throws(() => DispatcherScheduler.Instance.ScheduleAction(new object(), default)); - ReactiveAssert.Throws(() => DispatcherScheduler.Instance.Schedule(TimeSpan.Zero, default(Action))); - ReactiveAssert.Throws(() => DispatcherScheduler.Instance.Schedule(DateTimeOffset.MaxValue, default(Action))); + ReactiveAssert.Throws(() => DispatcherScheduler.Current.Schedule(default(Action))); + ReactiveAssert.Throws(() => DispatcherScheduler.Current.ScheduleAction(new object(), default)); + ReactiveAssert.Throws(() => DispatcherScheduler.Current.Schedule(TimeSpan.Zero, default(Action))); + ReactiveAssert.Throws(() => DispatcherScheduler.Current.Schedule(DateTimeOffset.MaxValue, default(Action))); + ReactiveAssert.Throws(() => LegacyDispatcherScheduler.Current.Schedule(default(Action))); + ReactiveAssert.Throws(() => LegacyDispatcherScheduler.Current.ScheduleAction(new object(), default)); + ReactiveAssert.Throws(() => LegacyDispatcherScheduler.Current.Schedule(TimeSpan.Zero, default(Action))); + ReactiveAssert.Throws(() => LegacyDispatcherScheduler.Current.Schedule(DateTimeOffset.MaxValue, default(Action))); #endif ReactiveAssert.Throws(() => Scheduler.Immediate.Schedule(default(Action))); ReactiveAssert.Throws(() => Scheduler.Immediate.ScheduleAction(new object(), default)); @@ -88,6 +99,10 @@ public void Schedulers_ArgumentChecks() ReactiveAssert.Throws(() => new ControlScheduler(lbl).ScheduleAction(new object(), default(Action))); ReactiveAssert.Throws(() => new ControlScheduler(lbl).Schedule(TimeSpan.Zero, default(Action))); ReactiveAssert.Throws(() => new ControlScheduler(lbl).Schedule(DateTimeOffset.MaxValue, default(Action))); + ReactiveAssert.Throws(() => new LegacyControlScheduler(lbl).Schedule(default(Action))); + ReactiveAssert.Throws(() => new LegacyControlScheduler(lbl).ScheduleAction(new object(), default(Action))); + ReactiveAssert.Throws(() => new LegacyControlScheduler(lbl).Schedule(TimeSpan.Zero, default(Action))); + ReactiveAssert.Throws(() => new LegacyControlScheduler(lbl).Schedule(DateTimeOffset.MaxValue, default(Action))); #endif var ctx = new SynchronizationContext(); ReactiveAssert.Throws(() => new SynchronizationContextScheduler(ctx).Schedule(default(Action))); diff --git a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/Observable/ObserveOnTest.cs b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/Observable/ObserveOnTest.cs index edb05142e..faab29df2 100644 --- a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/Observable/ObserveOnTest.cs +++ b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/Observable/ObserveOnTest.cs @@ -16,10 +16,15 @@ #if HAS_DISPATCHER using System.Windows.Threading; + +using LegacyDispatcherScheduler = System.Reactive.Concurrency.DispatcherScheduler; +using DispatcherScheduler = System.Reactive.Integration.Wpf.DispatcherScheduler; #endif #if HAS_WINFORMS using System.Windows.Forms; +using LegacyControlScheduler = System.Reactive.Concurrency.ControlScheduler; +using ControlScheduler = System.Reactive.Integration.WindowsForms.ControlScheduler; #endif using Assert = Xunit.Assert; @@ -40,7 +45,11 @@ public void ObserveOn_ArgumentChecking() #pragma warning disable IDE0034 // (Simplify 'default'.) Want to be explicit about overloads being tested. ReactiveAssert.Throws(() => Observable.ObserveOn(default(IObservable), new ControlScheduler(new Label()))); ReactiveAssert.Throws(() => Observable.ObserveOn(someObservable, default(ControlScheduler))); + ReactiveAssert.Throws(() => Observable.ObserveOn(default(IObservable), new LegacyControlScheduler(new Label()))); + ReactiveAssert.Throws(() => Observable.ObserveOn(someObservable, default(LegacyControlScheduler))); + ReactiveAssert.Throws(() => WindowsFormsControlObservable.ObserveOnWindowsFormsControl(default(IObservable), new Label())); + ReactiveAssert.Throws(() => WindowsFormsControlObservable.ObserveOnWindowsFormsControl(someObservable, default(Label))); ReactiveAssert.Throws(() => ControlObservable.ObserveOn(default(IObservable), new Label())); ReactiveAssert.Throws(() => ControlObservable.ObserveOn(someObservable, default(Label))); #pragma warning restore IDE0034 @@ -50,7 +59,12 @@ public void ObserveOn_ArgumentChecking() #pragma warning disable IDE0034 // (Simplify 'default'.) Want to be explicit about overloads being tested. ReactiveAssert.Throws(() => Observable.ObserveOn(default(IObservable), new DispatcherScheduler(Dispatcher.CurrentDispatcher))); ReactiveAssert.Throws(() => Observable.ObserveOn(someObservable, default(DispatcherScheduler))); + ReactiveAssert.Throws(() => Observable.ObserveOn(default(IObservable), new LegacyDispatcherScheduler(Dispatcher.CurrentDispatcher))); + ReactiveAssert.Throws(() => Observable.ObserveOn(someObservable, default(LegacyDispatcherScheduler))); + ReactiveAssert.Throws(() => WpfDispatcherObservable.ObserveOnWpfDispatcher(default(IObservable), Dispatcher.CurrentDispatcher)); + ReactiveAssert.Throws(() => WpfDispatcherObservable.ObserveOnWpfDispatcher(someObservable, default(Dispatcher))); + ReactiveAssert.Throws(() => WpfDispatcherObservable.ObserveOnCurrentWpfDispatcher(default(IObservable))); ReactiveAssert.Throws(() => DispatcherObservable.ObserveOn(default(IObservable), Dispatcher.CurrentDispatcher)); ReactiveAssert.Throws(() => DispatcherObservable.ObserveOn(someObservable, default(Dispatcher))); ReactiveAssert.Throws(() => DispatcherObservable.ObserveOnDispatcher(default(IObservable))); @@ -66,6 +80,27 @@ public void ObserveOn_Control() { var okay = true; + using (WinFormsTestUtils.RunTest(out var lbl)) + { + var evt = new ManualResetEvent(false); + + Observable.Range(0, 10, NewThreadScheduler.Default).ObserveOnWindowsFormsControl(lbl).Subscribe(x => + { + lbl.Text = x.ToString(); + okay &= (SynchronizationContext.Current is System.Windows.Forms.WindowsFormsSynchronizationContext); + }, () => evt.Set()); + + evt.WaitOne(); + } + + Assert.True(okay); + } + + [TestMethod] + public void ObserveOn_Control_Legacy() + { + var okay = true; + using (WinFormsTestUtils.RunTest(out var lbl)) { var evt = new ManualResetEvent(false); @@ -106,7 +141,28 @@ public void ObserveOn_ControlScheduler() #if HAS_DISPATCHER [TestMethod] [Asynchronous] - public void ObserveOn_Dispatcher() + public void ObserveOnDispatcher() + { + using (DispatcherHelpers.RunTest(out var dispatcher)) + { + RunAsync(evt => + { + var okay = true; + Observable.Range(0, 10, NewThreadScheduler.Default).ObserveOnWpfDispatcher(dispatcher).Subscribe(x => + { + okay &= (SynchronizationContext.Current is System.Windows.Threading.DispatcherSynchronizationContext); + }, () => + { + Assert.True(okay); + evt.Set(); + }); + }); + } + } + + [TestMethod] + [Asynchronous] + public void ObserveOn_Dispatcher_Legacy() { using (DispatcherHelpers.RunTest(out var dispatcher)) { @@ -148,7 +204,31 @@ public void ObserveOn_DispatcherScheduler() [TestMethod] [Asynchronous] - public void ObserveOn_CurrentDispatcher() + public void ObserveOnCurrentDispatcher() + { + using (DispatcherHelpers.RunTest(out var dispatcher)) + { + RunAsync(evt => + { + var okay = true; + dispatcher.BeginInvoke(new Action(() => + { + Observable.Range(0, 10, NewThreadScheduler.Default).ObserveOnCurrentWpfDispatcher().Subscribe(x => + { + okay &= (SynchronizationContext.Current is System.Windows.Threading.DispatcherSynchronizationContext); + }, () => + { + Assert.True(okay); + evt.Set(); + }); + })); + }); + } + } + + [TestMethod] + [Asynchronous] + public void ObserveOn_CurrentDispatcher_Legacy() { using (DispatcherHelpers.RunTest(out var dispatcher)) { @@ -160,9 +240,43 @@ public void ObserveOn_CurrentDispatcher() Observable.Range(0, 10, NewThreadScheduler.Default).ObserveOnDispatcher().Subscribe(x => { okay &= (SynchronizationContext.Current is System.Windows.Threading.DispatcherSynchronizationContext); - }, () => + }, () => + { + Assert.True(okay); + evt.Set(); + }); + })); + }); + } + } + + + [TestMethod] + [Asynchronous] + public void ObserveOnCurrentDispatcher_Error() + { + using (DispatcherHelpers.RunTest(out var dispatcher)) + { + RunAsync(evt => + { + var ex = new Exception(); + var okay = true; + + dispatcher.BeginInvoke(new Action(() => + { + Observable.Throw(ex).ObserveOnCurrentWpfDispatcher().Subscribe(x => + { + okay &= (SynchronizationContext.Current is System.Windows.Threading.DispatcherSynchronizationContext); + }, + e => { Assert.True(okay); + Assert.Same(ex, e); + evt.Set(); + }, + () => + { + Assert.True(false); evt.Set(); }); })); @@ -172,7 +286,7 @@ public void ObserveOn_CurrentDispatcher() [TestMethod] [Asynchronous] - public void ObserveOn_Error() + public void ObserveOn_Error_Legacy() { using (DispatcherHelpers.RunTest(out var dispatcher)) { diff --git a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/Observable/SubscribeOnTest.cs b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/Observable/SubscribeOnTest.cs index 4c1d61984..2192a6543 100644 --- a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/Observable/SubscribeOnTest.cs +++ b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/Observable/SubscribeOnTest.cs @@ -15,10 +15,14 @@ using System.Reactive; using System.Reactive.Subjects; +using LegacyDispatcherScheduler = System.Reactive.Concurrency.DispatcherScheduler; +using DispatcherScheduler = System.Reactive.Integration.Wpf.DispatcherScheduler; #endif #if HAS_WINFORMS using System.Windows.Forms; +using LegacyControlScheduler = System.Reactive.Concurrency.ControlScheduler; +using ControlScheduler = System.Reactive.Integration.WindowsForms.ControlScheduler; #endif using Assert = Xunit.Assert; @@ -40,7 +44,11 @@ public void SubscribeOn_ArgumentChecking() #pragma warning disable IDE0034 // (Simplify 'default'.) Want to be explicit about overload being tested. ReactiveAssert.Throws(() => Observable.SubscribeOn(default(IObservable), new ControlScheduler(new Label()))); ReactiveAssert.Throws(() => Observable.SubscribeOn(someObservable, default(ControlScheduler))); + ReactiveAssert.Throws(() => Observable.SubscribeOn(default(IObservable), new LegacyControlScheduler(new Label()))); + ReactiveAssert.Throws(() => Observable.SubscribeOn(someObservable, default(LegacyControlScheduler))); + ReactiveAssert.Throws(() => WindowsFormsControlObservable.SubscribeOnWindowFormsControl(default(IObservable), new Label())); + ReactiveAssert.Throws(() => WindowsFormsControlObservable.SubscribeOnWindowFormsControl(someObservable, default(Label))); ReactiveAssert.Throws(() => ControlObservable.SubscribeOn(default(IObservable), new Label())); ReactiveAssert.Throws(() => ControlObservable.SubscribeOn(someObservable, default(Label))); #pragma warning restore IDE0034 @@ -49,7 +57,12 @@ public void SubscribeOn_ArgumentChecking() #pragma warning disable IDE0034 // (Simplify 'default'.) Want to be explicit about overload being tested. ReactiveAssert.Throws(() => Observable.SubscribeOn(default(IObservable), new DispatcherScheduler(Dispatcher.CurrentDispatcher))); ReactiveAssert.Throws(() => Observable.SubscribeOn(someObservable, default(DispatcherScheduler))); + ReactiveAssert.Throws(() => Observable.SubscribeOn(default(IObservable), new LegacyDispatcherScheduler(Dispatcher.CurrentDispatcher))); + ReactiveAssert.Throws(() => Observable.SubscribeOn(someObservable, default(LegacyDispatcherScheduler))); + ReactiveAssert.Throws(() => WpfDispatcherObservable.SubscribeOnWpfDispatcher(default(IObservable), Dispatcher.CurrentDispatcher)); + ReactiveAssert.Throws(() => WpfDispatcherObservable.SubscribeOnWpfDispatcher(someObservable, default(Dispatcher))); + ReactiveAssert.Throws(() => WpfDispatcherObservable.SubscribeOnCurrentWpfDispatcher(default(IObservable))); ReactiveAssert.Throws(() => DispatcherObservable.SubscribeOn(default(IObservable), Dispatcher.CurrentDispatcher)); ReactiveAssert.Throws(() => DispatcherObservable.SubscribeOn(someObservable, default(Dispatcher))); ReactiveAssert.Throws(() => DispatcherObservable.SubscribeOnDispatcher(default(IObservable))); @@ -61,7 +74,7 @@ public void SubscribeOn_ArgumentChecking() #if HAS_WINFORMS [TestMethod] - public void SubscribeOn_Control() + public void SubscribeOn_Control_Legacy() { var okay = true; @@ -94,6 +107,75 @@ public void SubscribeOn_Control() Assert.True(okay); } + [TestMethod] + public void SubscribeOnControl() + { + var okay = true; + + using (WinFormsTestUtils.RunTest(out var lbl)) + { + var evt2 = new ManualResetEvent(false); + var evt = new ManualResetEvent(false); + var d = Observable.Create(obs => + { + lbl.Text = "Subscribe"; + okay &= (SynchronizationContext.Current is System.Windows.Forms.WindowsFormsSynchronizationContext); + evt2.Set(); + + return () => + { + lbl.Text = "Unsubscribe"; + okay &= (SynchronizationContext.Current is System.Windows.Forms.WindowsFormsSynchronizationContext); + evt.Set(); + }; + }) + .SubscribeOnWindowFormsControl(lbl) + .Subscribe(_ => { }); + + evt2.WaitOne(); + d.Dispose(); + + evt.WaitOne(); + } + + Assert.True(okay); + } + + [TestMethod] + public void SubscribeOn_ControlScheduler_Legacy() + { + var okay = true; + + using (WinFormsTestUtils.RunTest(out var lbl)) + { + var evt2 = new ManualResetEvent(false); + var evt = new ManualResetEvent(false); + + var d = Observable.Create(obs => + { + lbl.Text = "Subscribe"; + okay &= (SynchronizationContext.Current is System.Windows.Forms.WindowsFormsSynchronizationContext); + evt2.Set(); + + return () => + { + lbl.Text = "Unsubscribe"; + okay &= (SynchronizationContext.Current is System.Windows.Forms.WindowsFormsSynchronizationContext); + evt.Set(); + }; + }) + .SubscribeOn(new ControlScheduler(lbl)) + .Subscribe(_ => { }); + + evt2.WaitOne(); + d.Dispose(); + + evt.WaitOne(); + } + + Assert.True(okay); + } + [TestMethod] public void SubscribeOn_ControlScheduler() { @@ -117,7 +199,7 @@ public void SubscribeOn_ControlScheduler() evt.Set(); }; }) - .SubscribeOn(new ControlScheduler(lbl)) + .SubscribeOn(new System.Reactive.Integration.WindowsForms.ControlScheduler(lbl)) .Subscribe(_ => { }); evt2.WaitOne(); @@ -133,7 +215,7 @@ public void SubscribeOn_ControlScheduler() #if HAS_DISPATCHER [TestMethod] [Asynchronous] - public void SubscribeOn_Dispatcher() + public void SubscribeOn_Dispatcher_Legacy() { using (DispatcherHelpers.RunTest(out var dispatcher)) { @@ -162,6 +244,37 @@ public void SubscribeOn_Dispatcher() } } + [TestMethod] + [Asynchronous] + public void SubscribeOnDispatcher() + { + using (DispatcherHelpers.RunTest(out var dispatcher)) + { + RunAsync(evt => + { + var s = new AsyncSubject(); + var okay = true; + var d = Observable.Create(obs => + { + okay &= (SynchronizationContext.Current is System.Windows.Threading.DispatcherSynchronizationContext); + s.OnNext(Unit.Default); + s.OnCompleted(); + + return () => + { + okay &= (SynchronizationContext.Current is System.Windows.Threading.DispatcherSynchronizationContext); + Assert.True(okay); + evt.Set(); + }; + }) + .SubscribeOnWpfDispatcher(dispatcher) + .Subscribe(_ => { }); + + s.Subscribe(_ => d.Dispose()); + }); + } + } + [TestMethod] [Asynchronous] public void SubscribeOn_DispatcherScheduler() @@ -195,7 +308,7 @@ public void SubscribeOn_DispatcherScheduler() [TestMethod] [Asynchronous] - public void SubscribeOn_CurrentDispatcher() + public void SubscribeOn_CurrentDispatcher_Legacy() { using (DispatcherHelpers.RunTest(out var dispatcher)) { @@ -227,6 +340,41 @@ public void SubscribeOn_CurrentDispatcher() }); } } + + [TestMethod] + [Asynchronous] + public void SubscribeOnCurrentDispatcher() + { + using (DispatcherHelpers.RunTest(out var dispatcher)) + { + RunAsync(evt => + { + var s = new AsyncSubject(); + var okay = true; + + dispatcher.BeginInvoke(new Action(() => + { + var d = Observable.Create(obs => + { + okay &= (SynchronizationContext.Current is System.Windows.Threading.DispatcherSynchronizationContext); + s.OnNext(Unit.Default); + s.OnCompleted(); + + return () => + { + okay &= (SynchronizationContext.Current is System.Windows.Threading.DispatcherSynchronizationContext); + Assert.True(okay); + evt.Set(); + }; + }) + .SubscribeOnCurrentWpfDispatcher() + .Subscribe(_ => { }); + + s.Subscribe(_ => d.Dispose()); + })); + }); + } + } #endif #endregion + TestBase + diff --git a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/QbservableTest.cs b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/QbservableTest.cs index 7a8249f37..655d62307 100644 --- a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/QbservableTest.cs +++ b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/QbservableTest.cs @@ -20,6 +20,15 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Assert = Xunit.Assert; +#if HAS_WINFORMS +using LegacyControlScheduler = System.Reactive.Concurrency.ControlScheduler; +using ControlScheduler = System.Reactive.Integration.WindowsForms.ControlScheduler; +#endif + +#if HAS_WPF +using LegacyDispatcherScheduler = System.Reactive.Concurrency.DispatcherScheduler; +using DispatcherScheduler = System.Reactive.Integration.Wpf.DispatcherScheduler; +#endif namespace ReactiveTests.Tests { @@ -870,12 +879,14 @@ public void ObserveOn_ArgumentNullChecks() #endif #if HAS_WINFORMS ReactiveAssert.Throws(() => Qbservable.ObserveOn(_qbMy, default(ControlScheduler))); + ReactiveAssert.Throws(() => Qbservable.ObserveOn(_qbMy, default(LegacyControlScheduler))); ReactiveAssert.Throws(() => Qbservable.ObserveOn(_qbNull, new ControlScheduler(new System.Windows.Forms.Form()))); #endif ReactiveAssert.Throws(() => Qbservable.ObserveOn(_qbNull, Scheduler.Immediate)); ReactiveAssert.Throws(() => Qbservable.ObserveOn(_qbNull, new SynchronizationContext())); #if HAS_DISPATCHER - ReactiveAssert.Throws(() => Qbservable.ObserveOn(_qbNull, DispatcherScheduler.Instance)); + ReactiveAssert.Throws(() => Qbservable.ObserveOn(_qbNull, DispatcherScheduler.Current)); + ReactiveAssert.Throws(() => Qbservable.ObserveOn(_qbNull, LegacyDispatcherScheduler.Current)); #endif } @@ -885,7 +896,8 @@ public void ObserveOn() { _qbMy.ObserveOn(Scheduler.Immediate); _qbMy.ObserveOn(new SynchronizationContext()); - Qbservable.ObserveOn(_qbMy, DispatcherScheduler.Instance); + Qbservable.ObserveOn(_qbMy, DispatcherScheduler.Current); + Qbservable.ObserveOn(_qbMy, LegacyDispatcherScheduler.Current); } #endif @@ -1158,7 +1170,8 @@ public void SubscribeOn_ArgumentNullChecks() ReactiveAssert.Throws(() => Qbservable.SubscribeOn(_qbNull, Scheduler.Immediate)); ReactiveAssert.Throws(() => Qbservable.SubscribeOn(_qbNull, new SynchronizationContext())); #if HAS_DISPATCHER - ReactiveAssert.Throws(() => Qbservable.SubscribeOn(_qbNull, DispatcherScheduler.Instance)); + ReactiveAssert.Throws(() => Qbservable.SubscribeOn(_qbNull, DispatcherScheduler.Current)); + ReactiveAssert.Throws(() => Qbservable.SubscribeOn(_qbNull, LegacyDispatcherScheduler.Current)); #endif #if HAS_WINFORMS ReactiveAssert.Throws(() => Qbservable.SubscribeOn(_qbMy, default(ControlScheduler))); @@ -1166,13 +1179,26 @@ public void SubscribeOn_ArgumentNullChecks() #endif } + [TestMethod] + public void SubscribeOn_Legacy() + { + _qbMy.SubscribeOn(Scheduler.Immediate); + _qbMy.SubscribeOn(new SynchronizationContext()); +#if HAS_DISPATCHER + Qbservable.SubscribeOn(_qbMy, LegacyDispatcherScheduler.Current); +#endif +#if HAS_WINFORMS + _qbMy.SubscribeOn(new ControlScheduler(new System.Windows.Forms.Form())); +#endif + } + [TestMethod] public void SubscribeOn() { _qbMy.SubscribeOn(Scheduler.Immediate); _qbMy.SubscribeOn(new SynchronizationContext()); #if HAS_DISPATCHER - Qbservable.SubscribeOn(_qbMy, DispatcherScheduler.Instance); + Qbservable.SubscribeOn(_qbMy, DispatcherScheduler.Current); #endif #if HAS_WINFORMS _qbMy.SubscribeOn(new ControlScheduler(new System.Windows.Forms.Form())); From af836b7b280009f1892c74e20c94a012426d7ca2 Mon Sep 17 00:00:00 2001 From: Ian Griffiths Date: Tue, 13 Feb 2024 09:33:26 +0000 Subject: [PATCH 2/8] Ensure Dispatcher available in test that presume it It looks like a few tests that fetched DispatcherScheduler.Current used to rely on the Dispatcher already having been created. Up until recently, that was true by random chance. But recent changes, which presumably have affected the order of test execution, mean that's no longer true. These tests should always have ensured a dispatcher was available before starting to run, and now they do. --- Rx.NET/Source/CodeCoverage.runsettings | 4 ++++ .../Tests/Concurrency/SchedulerTest.cs | 8 ++++++++ .../Tests.System.Reactive/Tests/Linq/QbservableTest.cs | 8 ++++++++ 3 files changed, 20 insertions(+) diff --git a/Rx.NET/Source/CodeCoverage.runsettings b/Rx.NET/Source/CodeCoverage.runsettings index 92350aec5..a7e56620a 100644 --- a/Rx.NET/Source/CodeCoverage.runsettings +++ b/Rx.NET/Source/CodeCoverage.runsettings @@ -1,6 +1,10 @@ + + STA + + diff --git a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/SchedulerTest.cs b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/SchedulerTest.cs index 3dac1ffa2..e4e94efc5 100644 --- a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/SchedulerTest.cs +++ b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/SchedulerTest.cs @@ -34,6 +34,14 @@ namespace ReactiveTests.Tests [TestClass] public class SchedulerTest : ReactiveTest { +#if HAS_DISPATCHER + [TestInitialize] + public void EnsureDispatcherAvailable() + { + _ = new System.Windows.DependencyObject(); + } +#endif + #region IScheduler [TestMethod] diff --git a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/QbservableTest.cs b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/QbservableTest.cs index 655d62307..b6dfd73c5 100644 --- a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/QbservableTest.cs +++ b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/QbservableTest.cs @@ -39,6 +39,14 @@ public class QbservableTest private readonly IQbservable _qbMy = new MyQbservable(); private readonly IQbservableProvider _qbp = new MyQbservableProvider(); +#if HAS_DISPATCHER + [TestInitialize] + public void EnsureDispatcherAvailable() + { + _ = new System.Windows.DependencyObject(); + } +#endif + [TestMethod] public void LocalQueryMethodImplementationTypeAttribute() { From e27c11d7585c43e289a0c5213dca81a2c57321d0 Mon Sep 17 00:00:00 2001 From: Ian Griffiths Date: Tue, 13 Feb 2024 15:39:32 +0000 Subject: [PATCH 3/8] Update verified API * Add Obsolete attributes * Add the newly-public (was internal) member of AsyncLock --- .../Api/ApiApprovalTests.Core.verified.cs | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/Rx.NET/Source/tests/Tests.System.Reactive.ApiApprovals/Api/ApiApprovalTests.Core.verified.cs b/Rx.NET/Source/tests/Tests.System.Reactive.ApiApprovals/Api/ApiApprovalTests.Core.verified.cs index 6e3936ec8..116b69b48 100644 --- a/Rx.NET/Source/tests/Tests.System.Reactive.ApiApprovals/Api/ApiApprovalTests.Core.verified.cs +++ b/Rx.NET/Source/tests/Tests.System.Reactive.ApiApprovals/Api/ApiApprovalTests.Core.verified.cs @@ -235,7 +235,10 @@ public sealed class AsyncLock : System.IDisposable public AsyncLock() { } public void Dispose() { } public void Wait(System.Action action) { } + public void Wait(TState state, System.Action action) { } } + [System.Obsolete("Use System.Reactive.Integration.WindowsForms.ControlScheduler in the System.React" + + "ive.Integration.WindowsForms package instead", false)] public class ControlScheduler : System.Reactive.Concurrency.LocalScheduler, System.Reactive.Concurrency.ISchedulerPeriodic { public ControlScheduler(System.Windows.Forms.Control control) { } @@ -261,6 +264,8 @@ public override System.IDisposable Schedule(TState state, System.Func(TState state, System.TimeSpan dueTime, System.Func action) { } public System.IDisposable SchedulePeriodic(TState state, System.TimeSpan period, System.Func action) { } } + [System.Obsolete("Use System.Reactive.Integration.Wpf.DispatcherScheduler in the System.Reactive.In" + + "tegration.Wpf package instead", false)] public class DispatcherScheduler : System.Reactive.Concurrency.LocalScheduler, System.Reactive.Concurrency.ISchedulerPeriodic { public DispatcherScheduler(System.Windows.Threading.Dispatcher dispatcher) { } @@ -829,26 +834,69 @@ public class QueryablePlan } namespace System.Reactive.Linq { + [System.Obsolete("Use the extension methods defined by the System.Reactive.Linq.WindowsFormsControl" + + "Observable class in the System.Reactive.Integration.WindowsForms package instead" + + "", false)] public static class ControlObservable { + [System.Obsolete("Use the ObserveOnWindowsFormsControl extension method defined by System.Reactive." + + "Linq.WindowsFormsControlObservable in the System.Reactive.Integration.WindowsFor" + + "ms package instead", false)] public static System.IObservable ObserveOn(this System.IObservable source, System.Windows.Forms.Control control) { } + [System.Obsolete("Use the SubscribeOnWindowFormsControl extension method defined by System.Reactive" + + ".Linq.WindowsFormsControlObservable in the System.Reactive.Integration.WindowsFo" + + "rms package instead", false)] public static System.IObservable SubscribeOn(this System.IObservable source, System.Windows.Forms.Control control) { } } + [System.Obsolete("Use the extension methods defined by the System.Reactive.Linq.WpfDispatcherObserv" + + "able class in the System.Reactive.Integration.Wpf package instead", false)] public static class DispatcherObservable { + [System.Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.W" + + "pfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", false)] public static System.IObservable ObserveOn(this System.IObservable source, System.Reactive.Concurrency.DispatcherScheduler scheduler) { } + [System.Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.W" + + "pfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", false)] public static System.IObservable ObserveOn(this System.IObservable source, System.Windows.Threading.Dispatcher dispatcher) { } + [System.Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.W" + + "pfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", false)] public static System.IObservable ObserveOn(this System.IObservable source, System.Windows.Threading.DispatcherObject dispatcherObject) { } + [System.Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.W" + + "pfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", false)] public static System.IObservable ObserveOn(this System.IObservable source, System.Windows.Threading.Dispatcher dispatcher, System.Windows.Threading.DispatcherPriority priority) { } + [System.Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.W" + + "pfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", false)] public static System.IObservable ObserveOn(this System.IObservable source, System.Windows.Threading.DispatcherObject dispatcherObject, System.Windows.Threading.DispatcherPriority priority) { } + [System.Obsolete("Use the ObserveOnCurrentWpfDispatcher extension method defined by System.Reactive" + + ".Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package ins" + + "tead", false)] public static System.IObservable ObserveOnDispatcher(this System.IObservable source) { } + [System.Obsolete("Use the ObserveOnCurrentWpfDispatcher extension method defined by System.Reactive" + + ".Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package ins" + + "tead", false)] public static System.IObservable ObserveOnDispatcher(this System.IObservable source, System.Windows.Threading.DispatcherPriority priority) { } + [System.Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq" + + ".WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", false)] public static System.IObservable SubscribeOn(this System.IObservable source, System.Reactive.Concurrency.DispatcherScheduler scheduler) { } + [System.Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq" + + ".WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", false)] public static System.IObservable SubscribeOn(this System.IObservable source, System.Windows.Threading.Dispatcher dispatcher) { } + [System.Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq" + + ".WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", false)] public static System.IObservable SubscribeOn(this System.IObservable source, System.Windows.Threading.DispatcherObject dispatcherObject) { } + [System.Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq" + + ".WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", false)] public static System.IObservable SubscribeOn(this System.IObservable source, System.Windows.Threading.Dispatcher dispatcher, System.Windows.Threading.DispatcherPriority priority) { } + [System.Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq" + + ".WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", false)] public static System.IObservable SubscribeOn(this System.IObservable source, System.Windows.Threading.DispatcherObject dispatcherObject, System.Windows.Threading.DispatcherPriority priority) { } + [System.Obsolete("Use the SubscribeOnCurrentWpfDispatcher extension method defined by System.Reacti" + + "ve.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package i" + + "nstead", false)] public static System.IObservable SubscribeOnDispatcher(this System.IObservable source) { } + [System.Obsolete("Use the SubscribeOnCurrentWpfDispatcher extension method defined by System.Reacti" + + "ve.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package i" + + "nstead", false)] public static System.IObservable SubscribeOnDispatcher(this System.IObservable source, System.Windows.Threading.DispatcherPriority priority) { } } public interface IGroupedObservable : System.IObservable From 8708edf7a32533cf66468f2f2ccd3c1169e62396 Mon Sep 17 00:00:00 2001 From: Ian Griffiths Date: Tue, 13 Feb 2024 16:19:30 +0000 Subject: [PATCH 4/8] Add new integration package references to WindowsDesktopTests --- .../Integration/WindowsDesktopTests/WindowsDesktopTests.csproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Rx.NET/Integration/WindowsDesktopTests/WindowsDesktopTests.csproj b/Rx.NET/Integration/WindowsDesktopTests/WindowsDesktopTests.csproj index 74cc7e587..bc5efabd6 100644 --- a/Rx.NET/Integration/WindowsDesktopTests/WindowsDesktopTests.csproj +++ b/Rx.NET/Integration/WindowsDesktopTests/WindowsDesktopTests.csproj @@ -28,6 +28,8 @@ + + From 56c6da7a4223e3685ac5c17f39e3d1c4cc520aec Mon Sep 17 00:00:00 2001 From: Ian Griffiths Date: Tue, 13 Feb 2024 16:58:45 +0000 Subject: [PATCH 5/8] Add missing s in WindowsForms --- .../Integration/WindowsDesktopTests/WindowsDesktopTests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rx.NET/Integration/WindowsDesktopTests/WindowsDesktopTests.csproj b/Rx.NET/Integration/WindowsDesktopTests/WindowsDesktopTests.csproj index bc5efabd6..3d715c56e 100644 --- a/Rx.NET/Integration/WindowsDesktopTests/WindowsDesktopTests.csproj +++ b/Rx.NET/Integration/WindowsDesktopTests/WindowsDesktopTests.csproj @@ -28,7 +28,7 @@ - + From e28289bcbcd50a6b038b1b2925b92037965eb08c Mon Sep 17 00:00:00 2001 From: Ian Griffiths Date: Wed, 14 Feb 2024 07:49:37 +0000 Subject: [PATCH 6/8] Set version to 7.0 and update WindowsDesktopTests --- .../WindowsDesktopTests/WindowsDesktopTests.csproj | 10 +++++----- Rx.NET/Source/version.json | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Rx.NET/Integration/WindowsDesktopTests/WindowsDesktopTests.csproj b/Rx.NET/Integration/WindowsDesktopTests/WindowsDesktopTests.csproj index 3d715c56e..d6876fa96 100644 --- a/Rx.NET/Integration/WindowsDesktopTests/WindowsDesktopTests.csproj +++ b/Rx.NET/Integration/WindowsDesktopTests/WindowsDesktopTests.csproj @@ -27,10 +27,10 @@ - - - - - + + + + + \ No newline at end of file diff --git a/Rx.NET/Source/version.json b/Rx.NET/Source/version.json index c3ae3ab45..f08d86a8f 100644 --- a/Rx.NET/Source/version.json +++ b/Rx.NET/Source/version.json @@ -1,5 +1,5 @@ { - "version": "6.0.1-preview.{height}", + "version": "7.0.0-preview.{height}", "publicReleaseRefSpec": [ "^refs/heads/main$", // we release out of main "^refs/heads/rel/v\\d+\\.\\d+", // we also release branches starting with rel/vN.N From 23751e018c32104a4642f77a99de58a30f6f6d54 Mon Sep 17 00:00:00 2001 From: Ian Griffiths Date: Mon, 4 Mar 2024 15:00:09 +0000 Subject: [PATCH 7/8] Change .Integration package names to .For --- .../WindowsDesktopTests.csproj | 4 +- Rx.NET/Source/System.Reactive.sln | 8 +-- .../Strings_PlatformServices.Designer.cs | 4 +- .../Strings_PlatformServices.resx | 0 .../Stubs.cs | 2 +- .../System.Reactive.For.Uwp.csproj} | 4 +- .../ThreadPoolTimerExtensions.cs | 2 +- .../UwpThreadPoolScheduler.cs | 4 +- .../build/NuGet.Readme.md | 0 .../ControlScheduler.cs | 2 +- .../System.Reactive.For.WindowsForms.csproj} | 0 .../WindowsFormsControlObservable.cs | 2 +- .../build/NuGet.Readme.md | 26 ++++++++ .../AsyncInfoExtensions.cs | 2 +- .../AsyncInfoObservableExtensions.cs | 2 +- .../AsyncInfoToObservableBridge.cs | 2 +- .../CoreDispatcherScheduler.cs | 2 +- .../EventPatternSource.cs | 2 +- .../ITypedEventPatternSource.cs | 2 +- .../StableCompositeDisposable.cs | 2 +- .../Strings_WindowsThreading.Designer.cs | 4 +- .../Strings_WindowsThreading.resx | 0 ...System.Reactive.For.WindowsRuntime.csproj} | 0 .../WindowsRuntimeAsyncInfoObservable.cs | 2 +- .../WindowsRuntimeCoreDispatcherObservable.cs | 2 +- .../WindowsRuntimeObservable.Events.cs | 4 +- ...imeObservable.StandardSequenceOperators.cs | 2 +- .../build/NuGet.Readme.md | 0 .../DispatcherScheduler.cs | 2 +- .../Strings_WindowsThreading.Designer.cs | 4 +- .../Strings_WindowsThreading.resx | 0 .../System.Reactive.For.Wpf.csproj} | 0 .../WpfDispatcherObservable.cs | 2 +- .../build/NuGet.Readme.md | 0 .../ThreadPoolScheduler.Windows.cs | 10 ++-- .../Desktop/Concurrency/ControlScheduler.cs | 6 +- .../Concurrency/DispatcherScheduler.cs | 6 +- .../Desktop/Linq/ControlObservable.cs | 12 ++-- .../Desktop/Linq/DispatcherObservable.cs | 60 +++++++++---------- .../Concurrency/CoreDispatcherScheduler.cs | 6 +- .../UWP/Foundation/AsyncInfoExtensions.cs | 8 +-- .../Platforms/UWP/IEventPatternSource.cs | 10 ++-- .../Platforms/UWP/Linq/AsyncInfoObservable.cs | 32 +++++----- .../UWP/Linq/CoreDispatcherObservable.cs | 52 ++++++++-------- .../UWP/Linq/WindowsObservable.Events.cs | 10 ++-- ...owsObservable.StandardSequenceOperators.cs | 8 +-- .../Api/ApiApprovalTests.Core.verified.cs | 53 ++++++++-------- .../Tests.System.Reactive.csproj | 4 +- .../Tests/Concurrency/ControlSchedulerTest.cs | 2 +- .../Concurrency/DispatcherSchedulerTest.cs | 2 +- .../Tests/Concurrency/SchedulerTest.cs | 4 +- .../Tests/Linq/Observable/ObserveOnTest.cs | 4 +- .../Tests/Linq/Observable/SubscribeOnTest.cs | 6 +- .../Tests/Linq/QbservableTest.cs | 4 +- 54 files changed, 207 insertions(+), 186 deletions(-) rename Rx.NET/Source/src/{System.Reactive.Integration.Uwp => System.Reactive.For.Uwp}/Strings_PlatformServices.Designer.cs (95%) rename Rx.NET/Source/src/{System.Reactive.Integration.Uwp => System.Reactive.For.Uwp}/Strings_PlatformServices.resx (100%) rename Rx.NET/Source/src/{System.Reactive.Integration.Uwp => System.Reactive.For.Uwp}/Stubs.cs (88%) rename Rx.NET/Source/src/{System.Reactive.Integration.Uwp/System.Reactive.Integration.Uwp.csproj => System.Reactive.For.Uwp/System.Reactive.For.Uwp.csproj} (87%) rename Rx.NET/Source/src/{System.Reactive.Integration.Uwp => System.Reactive.For.Uwp}/ThreadPoolTimerExtensions.cs (92%) rename Rx.NET/Source/src/{System.Reactive.Integration.Uwp => System.Reactive.For.Uwp}/UwpThreadPoolScheduler.cs (98%) rename Rx.NET/Source/src/{System.Reactive.Integration.Uwp => System.Reactive.For.Uwp}/build/NuGet.Readme.md (100%) rename Rx.NET/Source/src/{System.Reactive.Integration.WindowsForms => System.Reactive.For.WindowsForms}/ControlScheduler.cs (99%) rename Rx.NET/Source/src/{System.Reactive.Integration.WindowsForms/System.Reactive.Integration.WindowsForms.csproj => System.Reactive.For.WindowsForms/System.Reactive.For.WindowsForms.csproj} (100%) rename Rx.NET/Source/src/{System.Reactive.Integration.WindowsForms => System.Reactive.For.WindowsForms}/System.Reactive.Linq/WindowsFormsControlObservable.cs (97%) create mode 100644 Rx.NET/Source/src/System.Reactive.For.WindowsForms/build/NuGet.Readme.md rename Rx.NET/Source/src/{System.Reactive.Integration.WindowsRuntime => System.Reactive.For.WindowsRuntime}/AsyncInfoExtensions.cs (90%) rename Rx.NET/Source/src/{System.Reactive.Integration.WindowsRuntime => System.Reactive.For.WindowsRuntime}/AsyncInfoObservableExtensions.cs (99%) rename Rx.NET/Source/src/{System.Reactive.Integration.WindowsRuntime => System.Reactive.For.WindowsRuntime}/AsyncInfoToObservableBridge.cs (98%) rename Rx.NET/Source/src/{System.Reactive.Integration.WindowsRuntime => System.Reactive.For.WindowsRuntime}/CoreDispatcherScheduler.cs (99%) rename Rx.NET/Source/src/{System.Reactive.Integration.WindowsRuntime => System.Reactive.For.WindowsRuntime}/EventPatternSource.cs (94%) rename Rx.NET/Source/src/{System.Reactive.Integration.WindowsRuntime => System.Reactive.For.WindowsRuntime}/ITypedEventPatternSource.cs (94%) rename Rx.NET/Source/src/{System.Reactive.Integration.WindowsRuntime => System.Reactive.For.WindowsRuntime}/StableCompositeDisposable.cs (97%) rename Rx.NET/Source/src/{System.Reactive.Integration.WindowsRuntime => System.Reactive.For.WindowsRuntime}/Strings_WindowsThreading.Designer.cs (95%) rename Rx.NET/Source/src/{System.Reactive.Integration.WindowsRuntime => System.Reactive.For.WindowsRuntime}/Strings_WindowsThreading.resx (100%) rename Rx.NET/Source/src/{System.Reactive.Integration.WindowsRuntime/System.Reactive.Integration.WindowsRuntime.csproj => System.Reactive.For.WindowsRuntime/System.Reactive.For.WindowsRuntime.csproj} (100%) rename Rx.NET/Source/src/{System.Reactive.Integration.WindowsRuntime => System.Reactive.For.WindowsRuntime}/System.Reactive.Linq/WindowsRuntimeAsyncInfoObservable.cs (99%) rename Rx.NET/Source/src/{System.Reactive.Integration.WindowsRuntime => System.Reactive.For.WindowsRuntime}/System.Reactive.Linq/WindowsRuntimeCoreDispatcherObservable.cs (99%) rename Rx.NET/Source/src/{System.Reactive.Integration.WindowsRuntime => System.Reactive.For.WindowsRuntime}/System.Reactive.Linq/WindowsRuntimeObservable.Events.cs (93%) rename Rx.NET/Source/src/{System.Reactive.Integration.WindowsRuntime => System.Reactive.For.WindowsRuntime}/System.Reactive.Linq/WindowsRuntimeObservable.StandardSequenceOperators.cs (99%) rename Rx.NET/Source/src/{System.Reactive.Integration.WindowsRuntime => System.Reactive.For.WindowsRuntime}/build/NuGet.Readme.md (100%) rename Rx.NET/Source/src/{System.Reactive.Integration.Wpf => System.Reactive.For.Wpf}/DispatcherScheduler.cs (99%) rename Rx.NET/Source/src/{System.Reactive.Integration.Wpf => System.Reactive.For.Wpf}/Strings_WindowsThreading.Designer.cs (95%) rename Rx.NET/Source/src/{System.Reactive.Integration.Wpf => System.Reactive.For.Wpf}/Strings_WindowsThreading.resx (100%) rename Rx.NET/Source/src/{System.Reactive.Integration.Wpf/System.Reactive.Integration.Wpf.csproj => System.Reactive.For.Wpf/System.Reactive.For.Wpf.csproj} (100%) rename Rx.NET/Source/src/{System.Reactive.Integration.Wpf => System.Reactive.For.Wpf}/System.Reactive.Linq/WpfDispatcherObservable.cs (99%) rename Rx.NET/Source/src/{System.Reactive.Integration.Wpf => System.Reactive.For.Wpf}/build/NuGet.Readme.md (100%) diff --git a/Rx.NET/Integration/WindowsDesktopTests/WindowsDesktopTests.csproj b/Rx.NET/Integration/WindowsDesktopTests/WindowsDesktopTests.csproj index d6876fa96..5ca0032de 100644 --- a/Rx.NET/Integration/WindowsDesktopTests/WindowsDesktopTests.csproj +++ b/Rx.NET/Integration/WindowsDesktopTests/WindowsDesktopTests.csproj @@ -28,8 +28,8 @@ - - + + diff --git a/Rx.NET/Source/System.Reactive.sln b/Rx.NET/Source/System.Reactive.sln index c03970699..7e6ab0d4d 100644 --- a/Rx.NET/Source/System.Reactive.sln +++ b/Rx.NET/Source/System.Reactive.sln @@ -68,13 +68,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Benchmarks", "Benchmarks", EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FrameworkIntegrations", "FrameworkIntegrations", "{1873A545-87AA-4C22-BA1A-8A6602F65749}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Reactive.Integration.WindowsForms", "src\System.Reactive.Integration.WindowsForms\System.Reactive.Integration.WindowsForms.csproj", "{DCD4D74D-FEED-4606-B9C6-6669A5D70B85}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Reactive.For.WindowsForms", "src\System.Reactive.For.WindowsForms\System.Reactive.For.WindowsForms.csproj", "{DCD4D74D-FEED-4606-B9C6-6669A5D70B85}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Reactive.Integration.Wpf", "src\System.Reactive.Integration.Wpf\System.Reactive.Integration.Wpf.csproj", "{D548C2CA-5C32-4FFF-B9E9-A251971ED7B4}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Reactive.For.Wpf", "src\System.Reactive.For.Wpf\System.Reactive.For.Wpf.csproj", "{D548C2CA-5C32-4FFF-B9E9-A251971ED7B4}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Reactive.Integration.Uwp", "src\System.Reactive.Integration.Uwp\System.Reactive.Integration.Uwp.csproj", "{C3FC6098-AC7F-4825-B292-4049BC6FC76E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Reactive.For.Uwp", "src\System.Reactive.For.Uwp\System.Reactive.For.Uwp.csproj", "{C3FC6098-AC7F-4825-B292-4049BC6FC76E}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Reactive.Integration.WindowsRuntime", "src\System.Reactive.Integration.WindowsRuntime\System.Reactive.Integration.WindowsRuntime.csproj", "{EB27A089-56EC-4621-BF88-E3B0DA8E6557}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Reactive.For.WindowsRuntime", "src\System.Reactive.For.WindowsRuntime\System.Reactive.For.WindowsRuntime.csproj", "{EB27A089-56EC-4621-BF88-E3B0DA8E6557}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Uwp/Strings_PlatformServices.Designer.cs b/Rx.NET/Source/src/System.Reactive.For.Uwp/Strings_PlatformServices.Designer.cs similarity index 95% rename from Rx.NET/Source/src/System.Reactive.Integration.Uwp/Strings_PlatformServices.Designer.cs rename to Rx.NET/Source/src/System.Reactive.For.Uwp/Strings_PlatformServices.Designer.cs index 21c2e42dd..63e038741 100644 --- a/Rx.NET/Source/src/System.Reactive.Integration.Uwp/Strings_PlatformServices.Designer.cs +++ b/Rx.NET/Source/src/System.Reactive.For.Uwp/Strings_PlatformServices.Designer.cs @@ -8,7 +8,7 @@ // //------------------------------------------------------------------------------ -namespace System.Reactive.Integration.Uwp { +namespace System.Reactive.Uwp { using System; using System.Reflection; @@ -40,7 +40,7 @@ internal Strings_PlatformServices() { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Reactive.Integration.Uwp.Strings_PlatformServices", typeof(Strings_PlatformServices).GetTypeInfo().Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Reactive.For.Uwp.Strings_PlatformServices", typeof(Strings_PlatformServices).GetTypeInfo().Assembly); resourceMan = temp; } return resourceMan; diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Uwp/Strings_PlatformServices.resx b/Rx.NET/Source/src/System.Reactive.For.Uwp/Strings_PlatformServices.resx similarity index 100% rename from Rx.NET/Source/src/System.Reactive.Integration.Uwp/Strings_PlatformServices.resx rename to Rx.NET/Source/src/System.Reactive.For.Uwp/Strings_PlatformServices.resx diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Uwp/Stubs.cs b/Rx.NET/Source/src/System.Reactive.For.Uwp/Stubs.cs similarity index 88% rename from Rx.NET/Source/src/System.Reactive.Integration.Uwp/Stubs.cs rename to Rx.NET/Source/src/System.Reactive.For.Uwp/Stubs.cs index 62b69c6d2..35d9cab81 100644 --- a/Rx.NET/Source/src/System.Reactive.Integration.Uwp/Stubs.cs +++ b/Rx.NET/Source/src/System.Reactive.For.Uwp/Stubs.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT License. // See the LICENSE file in the project root for more information. -namespace System.Reactive.Integration.Uwp +namespace System.Reactive.Uwp { internal static class Stubs { diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Uwp/System.Reactive.Integration.Uwp.csproj b/Rx.NET/Source/src/System.Reactive.For.Uwp/System.Reactive.For.Uwp.csproj similarity index 87% rename from Rx.NET/Source/src/System.Reactive.Integration.Uwp/System.Reactive.Integration.Uwp.csproj rename to Rx.NET/Source/src/System.Reactive.For.Uwp/System.Reactive.For.Uwp.csproj index 17b2a108d..153c6e101 100644 --- a/Rx.NET/Source/src/System.Reactive.Integration.Uwp/System.Reactive.Integration.Uwp.csproj +++ b/Rx.NET/Source/src/System.Reactive.For.Uwp/System.Reactive.For.Uwp.csproj @@ -19,14 +19,14 @@ - + - + diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Uwp/ThreadPoolTimerExtensions.cs b/Rx.NET/Source/src/System.Reactive.For.Uwp/ThreadPoolTimerExtensions.cs similarity index 92% rename from Rx.NET/Source/src/System.Reactive.Integration.Uwp/ThreadPoolTimerExtensions.cs rename to Rx.NET/Source/src/System.Reactive.For.Uwp/ThreadPoolTimerExtensions.cs index a00cbf618..60a91e462 100644 --- a/Rx.NET/Source/src/System.Reactive.Integration.Uwp/ThreadPoolTimerExtensions.cs +++ b/Rx.NET/Source/src/System.Reactive.For.Uwp/ThreadPoolTimerExtensions.cs @@ -6,7 +6,7 @@ using Windows.System.Threading; -namespace System.Reactive.Integration.Uwp +namespace System.Reactive.Uwp { internal static class ThreadPoolTimerExtensions { diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Uwp/UwpThreadPoolScheduler.cs b/Rx.NET/Source/src/System.Reactive.For.Uwp/UwpThreadPoolScheduler.cs similarity index 98% rename from Rx.NET/Source/src/System.Reactive.Integration.Uwp/UwpThreadPoolScheduler.cs rename to Rx.NET/Source/src/System.Reactive.For.Uwp/UwpThreadPoolScheduler.cs index 68d47813c..4a86a16e4 100644 --- a/Rx.NET/Source/src/System.Reactive.Integration.Uwp/UwpThreadPoolScheduler.cs +++ b/Rx.NET/Source/src/System.Reactive.For.Uwp/UwpThreadPoolScheduler.cs @@ -3,10 +3,10 @@ // See the LICENSE file in the project root for more information. using System.Reactive.Concurrency; -using System.Reactive.Integration.WindowsRuntime; +using System.Reactive.WindowsRuntime; using Windows.System.Threading; -namespace System.Reactive.Integration.Uwp +namespace System.Reactive.Uwp { /// /// Schedules units of work on the Windows Runtime thread pool. diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Uwp/build/NuGet.Readme.md b/Rx.NET/Source/src/System.Reactive.For.Uwp/build/NuGet.Readme.md similarity index 100% rename from Rx.NET/Source/src/System.Reactive.Integration.Uwp/build/NuGet.Readme.md rename to Rx.NET/Source/src/System.Reactive.For.Uwp/build/NuGet.Readme.md diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsForms/ControlScheduler.cs b/Rx.NET/Source/src/System.Reactive.For.WindowsForms/ControlScheduler.cs similarity index 99% rename from Rx.NET/Source/src/System.Reactive.Integration.WindowsForms/ControlScheduler.cs rename to Rx.NET/Source/src/System.Reactive.For.WindowsForms/ControlScheduler.cs index 9af2ac0e4..386636583 100644 --- a/Rx.NET/Source/src/System.Reactive.Integration.WindowsForms/ControlScheduler.cs +++ b/Rx.NET/Source/src/System.Reactive.For.WindowsForms/ControlScheduler.cs @@ -7,7 +7,7 @@ using System.Threading; using System.Windows.Forms; -namespace System.Reactive.Integration.WindowsForms +namespace System.Reactive.WindowsForms { /// /// Represents an object that schedules units of work on the message loop associated with a Windows Forms control. diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsForms/System.Reactive.Integration.WindowsForms.csproj b/Rx.NET/Source/src/System.Reactive.For.WindowsForms/System.Reactive.For.WindowsForms.csproj similarity index 100% rename from Rx.NET/Source/src/System.Reactive.Integration.WindowsForms/System.Reactive.Integration.WindowsForms.csproj rename to Rx.NET/Source/src/System.Reactive.For.WindowsForms/System.Reactive.For.WindowsForms.csproj diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsForms/System.Reactive.Linq/WindowsFormsControlObservable.cs b/Rx.NET/Source/src/System.Reactive.For.WindowsForms/System.Reactive.Linq/WindowsFormsControlObservable.cs similarity index 97% rename from Rx.NET/Source/src/System.Reactive.Integration.WindowsForms/System.Reactive.Linq/WindowsFormsControlObservable.cs rename to Rx.NET/Source/src/System.Reactive.For.WindowsForms/System.Reactive.Linq/WindowsFormsControlObservable.cs index 70a31752c..a62219643 100644 --- a/Rx.NET/Source/src/System.Reactive.Integration.WindowsForms/System.Reactive.Linq/WindowsFormsControlObservable.cs +++ b/Rx.NET/Source/src/System.Reactive.For.WindowsForms/System.Reactive.Linq/WindowsFormsControlObservable.cs @@ -4,7 +4,7 @@ using System.Windows.Forms; -using ControlScheduler = System.Reactive.Integration.WindowsForms.ControlScheduler; +using ControlScheduler = System.Reactive.WindowsForms.ControlScheduler; using Synchronization = System.Reactive.Concurrency.Synchronization; namespace System.Reactive.Linq diff --git a/Rx.NET/Source/src/System.Reactive.For.WindowsForms/build/NuGet.Readme.md b/Rx.NET/Source/src/System.Reactive.For.WindowsForms/build/NuGet.Readme.md new file mode 100644 index 000000000..84d58409b --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive.For.WindowsForms/build/NuGet.Readme.md @@ -0,0 +1,26 @@ +# Windows Forms Support for Rx.NET (Reactive Extensions for .NET) + +This library provides Windows Forms support for the Reactive Extensions for .NET (Rx.NET). + +See the main Rx.NET package at https://www.nuget.org/packages/System.Reactive for more information about Rx.NET. + +## Rx.NET and UI Frameworks + +Up as far as Rx.NET v6.0, UI framework support has been built directly into the main `System.Reactive` package. +Unfortunately, this has caused problems since support for WPF and Windows Forms was added in .NET Core 3.1. +Because .NET Core 3.1, and all subsequent versions of .NET have supported cross-platform use, WPF and Windows +Forms are not universally available. Rx.NET used to make WPF and Windows Forms support if you targetted a +sufficiently recent version of Windows in your application TFM. But this turns out to cause problems in +some deployment models, adding as much as 90MB to the deployable size of an application. + +Consequently, starting in Rx.NET v7.0 we are moving all UI-framework-specific types, and also platform-specific +types out into separate packages. + +## Features + +This package provides replacements for two deprecated types in `System.Reactive`: + +|Type in `System.Reactive` | Replacement | Purpose | +|---|---|---| +|`ControlScheduler` (in `System.Reactive.Concurrency`) | `ControlScheduler` (in `System.Reactive.Integration.WindowsForms`) | Provides a scheduler that schedules work on the UI thread of a Windows Forms application. | +|`ControlObservable` (in `System.Reactive.Linq`) | `WindowsFormsControlObservable` (in `System.Reactive.Linq`) | Provides a set of extension methods for scheduling work on the UI thread of a Windows Forms application. | diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/AsyncInfoExtensions.cs b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/AsyncInfoExtensions.cs similarity index 90% rename from Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/AsyncInfoExtensions.cs rename to Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/AsyncInfoExtensions.cs index dbd6d8531..f5145ca37 100644 --- a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/AsyncInfoExtensions.cs +++ b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/AsyncInfoExtensions.cs @@ -5,7 +5,7 @@ using System.Reactive.Disposables; using Windows.Foundation; -namespace System.Reactive.Integration.WindowsRuntime +namespace System.Reactive.WindowsRuntime { internal static class AsyncInfoExtensions { diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/AsyncInfoObservableExtensions.cs b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/AsyncInfoObservableExtensions.cs similarity index 99% rename from Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/AsyncInfoObservableExtensions.cs rename to Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/AsyncInfoObservableExtensions.cs index 013065c03..0d9730efc 100644 --- a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/AsyncInfoObservableExtensions.cs +++ b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/AsyncInfoObservableExtensions.cs @@ -5,7 +5,7 @@ using System.Reactive.Linq; using Windows.Foundation; -namespace System.Reactive.Integration.WindowsRuntime +namespace System.Reactive.WindowsRuntime { /// /// Provides conversions from Windows Runtime asynchronous actions and operations to observable sequences. diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/AsyncInfoToObservableBridge.cs b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/AsyncInfoToObservableBridge.cs similarity index 98% rename from Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/AsyncInfoToObservableBridge.cs rename to Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/AsyncInfoToObservableBridge.cs index e757b738e..2de450787 100644 --- a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/AsyncInfoToObservableBridge.cs +++ b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/AsyncInfoToObservableBridge.cs @@ -5,7 +5,7 @@ using System.Reactive.Subjects; using Windows.Foundation; -namespace System.Reactive.Integration.WindowsRuntime +namespace System.Reactive.WindowsRuntime { internal sealed class AsyncInfoToObservableBridge : ObservableBase { diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/CoreDispatcherScheduler.cs b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/CoreDispatcherScheduler.cs similarity index 99% rename from Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/CoreDispatcherScheduler.cs rename to Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/CoreDispatcherScheduler.cs index dcea221c9..b2e441d1c 100644 --- a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/CoreDispatcherScheduler.cs +++ b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/CoreDispatcherScheduler.cs @@ -9,7 +9,7 @@ using Windows.System; using Windows.UI.Core; -namespace System.Reactive.Integration.WindowsRuntime +namespace System.Reactive.WindowsRuntime { /// /// Schedules units of work on a . diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/EventPatternSource.cs b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/EventPatternSource.cs similarity index 94% rename from Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/EventPatternSource.cs rename to Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/EventPatternSource.cs index 72424892e..0ef4b83d6 100644 --- a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/EventPatternSource.cs +++ b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/EventPatternSource.cs @@ -4,7 +4,7 @@ using Windows.Foundation; -namespace System.Reactive.Integration.WindowsRuntime +namespace System.Reactive.WindowsRuntime { internal sealed class EventPatternSource : EventPatternSourceBase, ITypedEventPatternSource { diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/ITypedEventPatternSource.cs b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/ITypedEventPatternSource.cs similarity index 94% rename from Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/ITypedEventPatternSource.cs rename to Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/ITypedEventPatternSource.cs index 0f30732cd..eab1e1914 100644 --- a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/ITypedEventPatternSource.cs +++ b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/ITypedEventPatternSource.cs @@ -4,7 +4,7 @@ using Windows.Foundation; -namespace System.Reactive.Integration.WindowsRuntime +namespace System.Reactive.WindowsRuntime { /// /// Represents a data stream signaling its elements by means of a Windows Runtime diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/StableCompositeDisposable.cs b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/StableCompositeDisposable.cs similarity index 97% rename from Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/StableCompositeDisposable.cs rename to Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/StableCompositeDisposable.cs index d19ac4a27..bfa22ab33 100644 --- a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/StableCompositeDisposable.cs +++ b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/StableCompositeDisposable.cs @@ -4,7 +4,7 @@ using System.Threading; -namespace System.Reactive.Integration.WindowsRuntime +namespace System.Reactive.WindowsRuntime { /// /// Represents a group of disposable resources that are disposed together. diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/Strings_WindowsThreading.Designer.cs b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/Strings_WindowsThreading.Designer.cs similarity index 95% rename from Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/Strings_WindowsThreading.Designer.cs rename to Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/Strings_WindowsThreading.Designer.cs index 70038e8bb..6de4bd3ca 100644 --- a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/Strings_WindowsThreading.Designer.cs +++ b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/Strings_WindowsThreading.Designer.cs @@ -8,7 +8,7 @@ // //------------------------------------------------------------------------------ -namespace System.Reactive.Integration.WindowsRuntime { +namespace System.Reactive.WindowsRuntime { using System; @@ -39,7 +39,7 @@ internal Strings_WindowsThreading() { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Reactive.Integration.WindowsRuntime.Strings_WindowsThreading", typeof(Strings_WindowsThreading).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Reactive.For.WindowsRuntime.Strings_WindowsThreading", typeof(Strings_WindowsThreading).Assembly); resourceMan = temp; } return resourceMan; diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/Strings_WindowsThreading.resx b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/Strings_WindowsThreading.resx similarity index 100% rename from Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/Strings_WindowsThreading.resx rename to Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/Strings_WindowsThreading.resx diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Integration.WindowsRuntime.csproj b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/System.Reactive.For.WindowsRuntime.csproj similarity index 100% rename from Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Integration.WindowsRuntime.csproj rename to Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/System.Reactive.For.WindowsRuntime.csproj diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeAsyncInfoObservable.cs b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeAsyncInfoObservable.cs similarity index 99% rename from Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeAsyncInfoObservable.cs rename to Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeAsyncInfoObservable.cs index 740a89289..0e9cc0d1d 100644 --- a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeAsyncInfoObservable.cs +++ b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeAsyncInfoObservable.cs @@ -2,8 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT License. // See the LICENSE file in the project root for more information. -using System.Reactive.Integration.WindowsRuntime; using System.Reactive.Threading.Tasks; +using System.Reactive.WindowsRuntime; using System.Runtime.InteropServices.WindowsRuntime; using System.Threading.Tasks; using Windows.Foundation; diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeCoreDispatcherObservable.cs b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeCoreDispatcherObservable.cs similarity index 99% rename from Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeCoreDispatcherObservable.cs rename to Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeCoreDispatcherObservable.cs index d7474f781..c599ad098 100644 --- a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeCoreDispatcherObservable.cs +++ b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeCoreDispatcherObservable.cs @@ -8,7 +8,7 @@ using Windows.UI.Xaml; #endif -using CoreDispatcherScheduler = System.Reactive.Integration.WindowsRuntime.CoreDispatcherScheduler; +using CoreDispatcherScheduler = System.Reactive.WindowsRuntime.CoreDispatcherScheduler; using Synchronization = System.Reactive.Concurrency.Synchronization; namespace System.Reactive.Linq diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeObservable.Events.cs b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeObservable.Events.cs similarity index 93% rename from Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeObservable.Events.cs rename to Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeObservable.Events.cs index 2aa38d712..c5fe8df15 100644 --- a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeObservable.Events.cs +++ b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeObservable.Events.cs @@ -103,14 +103,14 @@ public static IObservable> FromEventPatternObservable source sequence. /// The event source object. /// is null. - public static System.Reactive.Integration.WindowsRuntime.ITypedEventPatternSource ToWindowsFoundationEventPattern(this IObservable> source) + public static System.Reactive.WindowsRuntime.ITypedEventPatternSource ToWindowsFoundationEventPattern(this IObservable> source) { if (source == null) { throw new ArgumentNullException(nameof(source)); } - return new System.Reactive.Integration.WindowsRuntime.EventPatternSource(source, static (h, evt) => h(evt.Sender!, evt.EventArgs)); + return new System.Reactive.WindowsRuntime.EventPatternSource(source, static (h, evt) => h(evt.Sender!, evt.EventArgs)); } } } diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeObservable.StandardSequenceOperators.cs b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeObservable.StandardSequenceOperators.cs similarity index 99% rename from Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeObservable.StandardSequenceOperators.cs rename to Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeObservable.StandardSequenceOperators.cs index 5f905bdbe..a8660bf97 100644 --- a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeObservable.StandardSequenceOperators.cs +++ b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/System.Reactive.Linq/WindowsRuntimeObservable.StandardSequenceOperators.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT License. // See the LICENSE file in the project root for more information. -using System.Reactive.Integration.WindowsRuntime; +using System.Reactive.WindowsRuntime; using Windows.Foundation; namespace System.Reactive.Linq diff --git a/Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/build/NuGet.Readme.md b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/build/NuGet.Readme.md similarity index 100% rename from Rx.NET/Source/src/System.Reactive.Integration.WindowsRuntime/build/NuGet.Readme.md rename to Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/build/NuGet.Readme.md diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Wpf/DispatcherScheduler.cs b/Rx.NET/Source/src/System.Reactive.For.Wpf/DispatcherScheduler.cs similarity index 99% rename from Rx.NET/Source/src/System.Reactive.Integration.Wpf/DispatcherScheduler.cs rename to Rx.NET/Source/src/System.Reactive.For.Wpf/DispatcherScheduler.cs index 6ab8bf278..5c8e8a76b 100644 --- a/Rx.NET/Source/src/System.Reactive.Integration.Wpf/DispatcherScheduler.cs +++ b/Rx.NET/Source/src/System.Reactive.For.Wpf/DispatcherScheduler.cs @@ -7,7 +7,7 @@ using System.Threading; using System.Windows.Threading; -namespace System.Reactive.Integration.Wpf +namespace System.Reactive.Wpf { /// /// Represents an object that schedules units of work on a . diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Wpf/Strings_WindowsThreading.Designer.cs b/Rx.NET/Source/src/System.Reactive.For.Wpf/Strings_WindowsThreading.Designer.cs similarity index 95% rename from Rx.NET/Source/src/System.Reactive.Integration.Wpf/Strings_WindowsThreading.Designer.cs rename to Rx.NET/Source/src/System.Reactive.For.Wpf/Strings_WindowsThreading.Designer.cs index 0cf293393..02e119223 100644 --- a/Rx.NET/Source/src/System.Reactive.Integration.Wpf/Strings_WindowsThreading.Designer.cs +++ b/Rx.NET/Source/src/System.Reactive.For.Wpf/Strings_WindowsThreading.Designer.cs @@ -8,7 +8,7 @@ // //------------------------------------------------------------------------------ -namespace System.Reactive.Integration.Wpf { +namespace System.Reactive.Wpf { using System; @@ -39,7 +39,7 @@ internal Strings_WindowsThreading() { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Reactive.Integration.Wpf.Strings_WindowsThreading", typeof(Strings_WindowsThreading).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Reactive.For.Wpf.Strings_WindowsThreading", typeof(Strings_WindowsThreading).Assembly); resourceMan = temp; } return resourceMan; diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Wpf/Strings_WindowsThreading.resx b/Rx.NET/Source/src/System.Reactive.For.Wpf/Strings_WindowsThreading.resx similarity index 100% rename from Rx.NET/Source/src/System.Reactive.Integration.Wpf/Strings_WindowsThreading.resx rename to Rx.NET/Source/src/System.Reactive.For.Wpf/Strings_WindowsThreading.resx diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Wpf/System.Reactive.Integration.Wpf.csproj b/Rx.NET/Source/src/System.Reactive.For.Wpf/System.Reactive.For.Wpf.csproj similarity index 100% rename from Rx.NET/Source/src/System.Reactive.Integration.Wpf/System.Reactive.Integration.Wpf.csproj rename to Rx.NET/Source/src/System.Reactive.For.Wpf/System.Reactive.For.Wpf.csproj diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Wpf/System.Reactive.Linq/WpfDispatcherObservable.cs b/Rx.NET/Source/src/System.Reactive.For.Wpf/System.Reactive.Linq/WpfDispatcherObservable.cs similarity index 99% rename from Rx.NET/Source/src/System.Reactive.Integration.Wpf/System.Reactive.Linq/WpfDispatcherObservable.cs rename to Rx.NET/Source/src/System.Reactive.For.Wpf/System.Reactive.Linq/WpfDispatcherObservable.cs index a748607b3..6f77e07f9 100644 --- a/Rx.NET/Source/src/System.Reactive.Integration.Wpf/System.Reactive.Linq/WpfDispatcherObservable.cs +++ b/Rx.NET/Source/src/System.Reactive.For.Wpf/System.Reactive.Linq/WpfDispatcherObservable.cs @@ -4,7 +4,7 @@ using System.Windows.Threading; -using DispatcherScheduler = System.Reactive.Integration.Wpf.DispatcherScheduler; +using DispatcherScheduler = System.Reactive.Wpf.DispatcherScheduler; using Synchronization = System.Reactive.Concurrency.Synchronization; namespace System.Reactive.Linq diff --git a/Rx.NET/Source/src/System.Reactive.Integration.Wpf/build/NuGet.Readme.md b/Rx.NET/Source/src/System.Reactive.For.Wpf/build/NuGet.Readme.md similarity index 100% rename from Rx.NET/Source/src/System.Reactive.Integration.Wpf/build/NuGet.Readme.md rename to Rx.NET/Source/src/System.Reactive.For.Wpf/build/NuGet.Readme.md diff --git a/Rx.NET/Source/src/System.Reactive/Concurrency/ThreadPoolScheduler.Windows.cs b/Rx.NET/Source/src/System.Reactive/Concurrency/ThreadPoolScheduler.Windows.cs index 8495cd0c1..fb4ba6611 100644 --- a/Rx.NET/Source/src/System.Reactive/Concurrency/ThreadPoolScheduler.Windows.cs +++ b/Rx.NET/Source/src/System.Reactive/Concurrency/ThreadPoolScheduler.Windows.cs @@ -22,7 +22,7 @@ public sealed class ThreadPoolScheduler : LocalScheduler, ISchedulerPeriodic /// /// Constructs a ThreadPoolScheduler that schedules units of work on the Windows ThreadPool. /// - [Obsolete("If you require the UWP-specific features of ThreadPoolScheduler use the UwpThreadPoolScheduler in the System.Reactive.Integration.Uwp package. Otherwise, use the Instance property, because this constructor will be removed in a future version (because UWP applications will end up with the same ThreadPoolScheduler as all other application types).")] + [Obsolete("If you require the UWP-specific features of ThreadPoolScheduler use the UwpThreadPoolScheduler in the System.Reactive.For.Uwp package. Otherwise, use the Instance property, because this constructor will be removed in a future version (because UWP applications will end up with the same ThreadPoolScheduler as all other application types).")] public ThreadPoolScheduler() { } @@ -31,7 +31,7 @@ public ThreadPoolScheduler() /// Constructs a ThreadPoolScheduler that schedules units of work on the Windows ThreadPool with the given priority. /// /// Priority for scheduled units of work. - [Obsolete("If you require the UWP-specific features of ThreadPoolScheduler use the UwpThreadPoolScheduler in the System.Reactive.Integration.Uwp package. Otherwise, use the Instance property, because this constructor will be removed in a future version (because UWP applications will end up with the same ThreadPoolScheduler as all other application types).")] + [Obsolete("If you require the UWP-specific features of ThreadPoolScheduler use the UwpThreadPoolScheduler in the System.Reactive.For.Uwp package. Otherwise, use the Instance property, because this constructor will be removed in a future version (because UWP applications will end up with the same ThreadPoolScheduler as all other application types).")] public ThreadPoolScheduler(WorkItemPriority priority) { Priority = priority; @@ -43,7 +43,7 @@ public ThreadPoolScheduler(WorkItemPriority priority) /// /// Priority for scheduled units of work. /// Options that configure how work is scheduled. - [Obsolete("If you require the UWP-specific features of ThreadPoolScheduler use the UwpThreadPoolScheduler in the System.Reactive.Integration.Uwp package. Otherwise, use the Instance property, because this constructor will be removed in a future version (because UWP applications will end up with the same ThreadPoolScheduler as all other application types).")] + [Obsolete("If you require the UWP-specific features of ThreadPoolScheduler use the UwpThreadPoolScheduler in the System.Reactive.For.Uwp package. Otherwise, use the Instance property, because this constructor will be removed in a future version (because UWP applications will end up with the same ThreadPoolScheduler as all other application types).")] public ThreadPoolScheduler(WorkItemPriority priority, WorkItemOptions options) { Priority = priority; @@ -65,13 +65,13 @@ public ThreadPoolScheduler(WorkItemPriority priority, WorkItemOptions options) /// /// Gets the priority at which work is scheduled. /// - [Obsolete("If you require the UWP-specific features of ThreadPoolScheduler use the UwpThreadPoolScheduler in the System.Reactive.Integration.Uwp package. This property will be removed in a future version (because UWP applications will end up with the same ThreadPoolScheduler as all other application types).")] + [Obsolete("If you require the UWP-specific features of ThreadPoolScheduler use the UwpThreadPoolScheduler in the System.Reactive.For.Uwp package. This property will be removed in a future version (because UWP applications will end up with the same ThreadPoolScheduler as all other application types).")] public WorkItemPriority Priority { get; } /// /// Gets the options that configure how work is scheduled. /// - [Obsolete("If you require the UWP-specific features of ThreadPoolScheduler use the UwpThreadPoolScheduler in the System.Reactive.Integration.Uwp package. This property will be removed in a future version (because UWP applications will end up with the same ThreadPoolScheduler as all other application types).")] + [Obsolete("If you require the UWP-specific features of ThreadPoolScheduler use the UwpThreadPoolScheduler in the System.Reactive.For.Uwp package. This property will be removed in a future version (because UWP applications will end up with the same ThreadPoolScheduler as all other application types).")] public WorkItemOptions Options { get; } /// diff --git a/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Concurrency/ControlScheduler.cs b/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Concurrency/ControlScheduler.cs index d8f029a04..121f69234 100644 --- a/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Concurrency/ControlScheduler.cs +++ b/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Concurrency/ControlScheduler.cs @@ -9,8 +9,8 @@ namespace System.Reactive.Concurrency { /// - /// Obsolete. The System.Reactive.Integration.WindowsForms NuGet package defines a - /// ControlScheduler class in the System.Reactive.Integration.WindowsForms + /// Obsolete. The System.Reactive.For.WindowsForms NuGet package defines a + /// ControlScheduler class in the System.Reactive.WindowsForms /// namespace that replaces this class. /// /// @@ -19,7 +19,7 @@ namespace System.Reactive.Concurrency /// System.Reactive causes applications to end up with dependencies on Windows Forms and /// WPF whether they want them or not. /// - [Obsolete("Use System.Reactive.Integration.WindowsForms.ControlScheduler in the System.Reactive.Integration.WindowsForms package instead", error: false)] + [Obsolete("Use System.Reactive.WindowsForms.ControlScheduler in the System.Reactive.For.WindowsForms package instead", error: false)] public class ControlScheduler : LocalScheduler, ISchedulerPeriodic { private readonly Control _control; diff --git a/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Concurrency/DispatcherScheduler.cs b/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Concurrency/DispatcherScheduler.cs index c06984b69..e5a922251 100644 --- a/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Concurrency/DispatcherScheduler.cs +++ b/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Concurrency/DispatcherScheduler.cs @@ -9,8 +9,8 @@ namespace System.Reactive.Concurrency { /// - /// Obsolete. The System.Reactive.Integration.Wpf NuGet package defines a - /// DispatcherScheduler class in the System.Reactive.Integration.Wpf + /// Obsolete. The System.Reactive.For.Wpf NuGet package defines a + /// DispatcherScheduler class in the System.Reactive.Wpf /// namespace that replaces this class. /// /// @@ -19,7 +19,7 @@ namespace System.Reactive.Concurrency /// System.Reactive causes applications to end up with dependencies on Windows Forms and /// WPF whether they want them or not. /// - [Obsolete("Use System.Reactive.Integration.Wpf.DispatcherScheduler in the System.Reactive.Integration.Wpf package instead", error: false)] + [Obsolete("Use System.Reactive.Wpf.DispatcherScheduler in the System.Reactive.For.Wpf package instead", error: false)] public class DispatcherScheduler : LocalScheduler, ISchedulerPeriodic { /// diff --git a/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Linq/ControlObservable.cs b/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Linq/ControlObservable.cs index 77bb9d72a..7ed814a4a 100644 --- a/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Linq/ControlObservable.cs +++ b/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Linq/ControlObservable.cs @@ -8,7 +8,7 @@ namespace System.Reactive.Linq { /// - /// Obsolete. The System.Reactive.Integration.WindowsForms NuGet package defines a + /// Obsolete. The System.Reactive.For.WindowsForms NuGet package defines a /// WindowsFormsControlObservable class that defines new extension methods to be used in /// place of these (also in the System.Reactive.Linq namespace). /// @@ -45,14 +45,14 @@ namespace System.Reactive.Linq /// visibly different names (and not the same names on a new type). /// /// - [Obsolete("Use the extension methods defined by the System.Reactive.Linq.WindowsFormsControlObservable class in the System.Reactive.Integration.WindowsForms package instead", error: false)] + [Obsolete("Use the extension methods defined by the System.Reactive.Linq.WindowsFormsControlObservable class in the System.Reactive.For.WindowsForms package instead", error: false)] public static class ControlObservable { /// /// Obsolete. Use the SubscribeOnWindowFormsControl extension method defined by /// System.Reactive.Linq.WindowsFormsControlObservable in the - /// System.Reactive.Integration.WindowsForms package instead. + /// System.Reactive.For.WindowsForms package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -63,7 +63,7 @@ public static class ControlObservable /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the specified control. /// In order to invoke observer callbacks on the specified control, e.g. to render results in a control, use . /// - [Obsolete("Use the SubscribeOnWindowFormsControl extension method defined by System.Reactive.Linq.WindowsFormsControlObservable in the System.Reactive.Integration.WindowsForms package instead", error: false)] + [Obsolete("Use the SubscribeOnWindowFormsControl extension method defined by System.Reactive.Linq.WindowsFormsControlObservable in the System.Reactive.For.WindowsForms package instead", error: false)] public static IObservable SubscribeOn(this IObservable source, Control control) { if (source == null) @@ -82,14 +82,14 @@ public static IObservable SubscribeOn(this IObservable /// Obsolete. Use the ObserveOnWindowsFormsControl extension method defined by /// System.Reactive.Linq.WindowsFormsControlObservable in the - /// System.Reactive.Integration.WindowsForms package instead. + /// System.Reactive.For.WindowsForms package instead. /// /// The type of the elements in the source sequence. /// Source sequence. /// Windows Forms control whose associated message loop is used to notify observers on. /// The source sequence whose observations happen on the Windows Forms message loop associated with the specified control. /// or is null. - [Obsolete("Use the ObserveOnWindowsFormsControl extension method defined by System.Reactive.Linq.WindowsFormsControlObservable in the System.Reactive.Integration.WindowsForms package instead", error: false)] + [Obsolete("Use the ObserveOnWindowsFormsControl extension method defined by System.Reactive.Linq.WindowsFormsControlObservable in the System.Reactive.For.WindowsForms package instead", error: false)] public static IObservable ObserveOn(this IObservable source, Control control) { if (source == null) diff --git a/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Linq/DispatcherObservable.cs b/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Linq/DispatcherObservable.cs index 2005fcd4b..40a4d1b37 100644 --- a/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Linq/DispatcherObservable.cs +++ b/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Linq/DispatcherObservable.cs @@ -9,7 +9,7 @@ namespace System.Reactive.Linq { /// - /// Obsolete. The System.Reactive.Integration.Wpf NuGet package defines a + /// Obsolete. The System.Reactive.For.Wpf NuGet package defines a /// WpfDispatcherObservable class that defines new extension methods to be used in /// place of these (also in the System.Reactive.Linq namespace). /// @@ -60,7 +60,7 @@ namespace System.Reactive.Linq /// visibly different names (and not the same names on a new type). /// /// - [Obsolete("Use the extension methods defined by the System.Reactive.Linq.WpfDispatcherObservable class in the System.Reactive.Integration.Wpf package instead", error: false)] + [Obsolete("Use the extension methods defined by the System.Reactive.Linq.WpfDispatcherObservable class in the System.Reactive.For.Wpf package instead", error: false)] public static class DispatcherObservable { #region ObserveOn[Dispatcher] @@ -68,14 +68,14 @@ public static class DispatcherObservable /// /// Obsolete. Use the ObserveOnWpfDispatcher extension method defined by /// System.Reactive.Linq.WpfDispatcherObservable in the - /// System.Reactive.Integration.Wpf package instead. + /// System.Reactive.For.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. /// Dispatcher whose associated message loop is used to notify observers on. /// The source sequence whose observations happen on the specified dispatcher. /// or is null. - [Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] + [Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)] public static IObservable ObserveOn(this IObservable source, Dispatcher dispatcher) { if (source == null) @@ -94,7 +94,7 @@ public static IObservable ObserveOn(this IObservable /// /// Obsolete. Use the ObserveOnWpfDispatcher extension method defined by /// System.Reactive.Linq.WpfDispatcherObservable in the - /// System.Reactive.Integration.Wpf package instead. + /// System.Reactive.For.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -102,7 +102,7 @@ public static IObservable ObserveOn(this IObservable /// Priority to schedule work items at. /// The source sequence whose observations happen on the specified dispatcher. /// or is null. - [Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] + [Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)] public static IObservable ObserveOn(this IObservable source, Dispatcher dispatcher, DispatcherPriority priority) { if (source == null) @@ -121,14 +121,14 @@ public static IObservable ObserveOn(this IObservable /// /// Obsolete. Use the ObserveOnWpfDispatcher extension method defined by /// System.Reactive.Linq.WpfDispatcherObservable in the - /// System.Reactive.Integration.Wpf package instead. + /// System.Reactive.For.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. /// Dispatcher scheduler to notify observers on. /// The source sequence whose observations happen on the specified dispatcher scheduler. /// or is null. - [Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] + [Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)] public static IObservable ObserveOn(this IObservable source, DispatcherScheduler scheduler) { if (source == null) @@ -147,14 +147,14 @@ public static IObservable ObserveOn(this IObservable /// /// Obsolete. Use the ObserveOnWpfDispatcher extension method defined by /// System.Reactive.Linq.WpfDispatcherObservable in the - /// System.Reactive.Integration.Wpf package instead. + /// System.Reactive.For.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. /// Object to get the dispatcher from. /// The source sequence whose observations happen on the specified object's dispatcher. /// or is null. - [Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] + [Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)] public static IObservable ObserveOn(this IObservable source, DispatcherObject dispatcherObject) { if (source == null) @@ -173,7 +173,7 @@ public static IObservable ObserveOn(this IObservable /// /// Obsolete. Use the ObserveOnWpfDispatcher extension method defined by /// System.Reactive.Linq.WpfDispatcherObservable in the - /// System.Reactive.Integration.Wpf package instead. + /// System.Reactive.For.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -181,7 +181,7 @@ public static IObservable ObserveOn(this IObservable /// Priority to schedule work items at. /// The source sequence whose observations happen on the specified object's dispatcher. /// or is null. - [Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] + [Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)] public static IObservable ObserveOn(this IObservable source, DispatcherObject dispatcherObject, DispatcherPriority priority) { if (source == null) @@ -200,13 +200,13 @@ public static IObservable ObserveOn(this IObservable /// /// Obsolete. Use the ObserveOnCurrentWpfDispatcher extension method defined by /// System.Reactive.Linq.WpfDispatcherObservable in the - /// System.Reactive.Integration.Wpf package instead. + /// System.Reactive.For.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. /// The source sequence whose observations happen on the current thread's dispatcher. /// is null. - [Obsolete("Use the ObserveOnCurrentWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] + [Obsolete("Use the ObserveOnCurrentWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)] public static IObservable ObserveOnDispatcher(this IObservable source) { if (source == null) @@ -220,14 +220,14 @@ public static IObservable ObserveOnDispatcher(this IObservable /// /// Obsolete. Use the ObserveOnCurrentWpfDispatcher extension method defined by /// System.Reactive.Linq.WpfDispatcherObservable in the - /// System.Reactive.Integration.Wpf package instead. + /// System.Reactive.For.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. /// Priority to schedule work items at. /// The source sequence whose observations happen on the current thread's dispatcher. /// is null. - [Obsolete("Use the ObserveOnCurrentWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] + [Obsolete("Use the ObserveOnCurrentWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)] public static IObservable ObserveOnDispatcher(this IObservable source, DispatcherPriority priority) { if (source == null) @@ -256,7 +256,7 @@ private static IObservable ObserveOn_(IObservable sou /// /// Obsolete. Use the SubscribeOnWpfDispatcher extension method defined by /// System.Reactive.Linq.WpfDispatcherObservable in the - /// System.Reactive.Integration.Wpf package instead. + /// System.Reactive.For.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -267,7 +267,7 @@ private static IObservable ObserveOn_(IObservable sou /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the specified dispatcher. /// In order to invoke observer callbacks on the specified dispatcher, e.g. to render results in a control, use . /// - [Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] + [Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)] public static IObservable SubscribeOn(this IObservable source, Dispatcher dispatcher) { if (source == null) @@ -286,7 +286,7 @@ public static IObservable SubscribeOn(this IObservable /// Obsolete. Use the SubscribeOnWpfDispatcher extension method defined by /// System.Reactive.Linq.WpfDispatcherObservable in the - /// System.Reactive.Integration.Wpf package instead. + /// System.Reactive.For.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -298,7 +298,7 @@ public static IObservable SubscribeOn(this IObservable. /// - [Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] + [Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)] public static IObservable SubscribeOn(this IObservable source, Dispatcher dispatcher, DispatcherPriority priority) { if (source == null) @@ -317,7 +317,7 @@ public static IObservable SubscribeOn(this IObservable /// Obsolete. Use the SubscribeOnWpfDispatcher extension method defined by /// System.Reactive.Linq.WpfDispatcherObservable in the - /// System.Reactive.Integration.Wpf package instead. + /// System.Reactive.For.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -328,7 +328,7 @@ public static IObservable SubscribeOn(this IObservable. /// - [Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] + [Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)] public static IObservable SubscribeOn(this IObservable source, DispatcherScheduler scheduler) { if (source == null) @@ -347,7 +347,7 @@ public static IObservable SubscribeOn(this IObservable /// Obsolete. Use the SubscribeOnWpfDispatcher extension method defined by /// System.Reactive.Linq.WpfDispatcherObservable in the - /// System.Reactive.Integration.Wpf package instead. + /// System.Reactive.For.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -358,7 +358,7 @@ public static IObservable SubscribeOn(this IObservable. /// - [Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] + [Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)] public static IObservable SubscribeOn(this IObservable source, DispatcherObject dispatcherObject) { if (source == null) @@ -377,7 +377,7 @@ public static IObservable SubscribeOn(this IObservable /// Obsolete. Use the SubscribeOnWpfDispatcher extension method defined by /// System.Reactive.Linq.WpfDispatcherObservable in the - /// System.Reactive.Integration.Wpf package instead. + /// System.Reactive.For.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -389,7 +389,7 @@ public static IObservable SubscribeOn(this IObservable. /// - [Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] + [Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)] public static IObservable SubscribeOn(this IObservable source, DispatcherObject dispatcherObject, DispatcherPriority priority) { if (source == null) @@ -408,7 +408,7 @@ public static IObservable SubscribeOn(this IObservable /// Obsolete. Use the SubscribeOnCurrentWpfDispatcher extension method defined by /// System.Reactive.Linq.WpfDispatcherObservable in the - /// System.Reactive.Integration.Wpf package instead. + /// System.Reactive.For.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -418,7 +418,7 @@ public static IObservable SubscribeOn(this IObservable. /// - [Obsolete("Use the SubscribeOnCurrentWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] + [Obsolete("Use the SubscribeOnCurrentWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)] public static IObservable SubscribeOnDispatcher(this IObservable source) { if (source == null) @@ -432,7 +432,7 @@ public static IObservable SubscribeOnDispatcher(this IObservab /// /// Obsolete. Use the SubscribeOnCurrentWpfDispatcher extension method defined by /// System.Reactive.Linq.WpfDispatcherObservable in the - /// System.Reactive.Integration.Wpf package instead. + /// System.Reactive.For.Wpf package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -443,7 +443,7 @@ public static IObservable SubscribeOnDispatcher(this IObservab /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the dispatcher associated with the current thread. /// In order to invoke observer callbacks on the dispatcher associated with the current thread, e.g. to render results in a control, use . /// - [Obsolete("Use the SubscribeOnCurrentWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", error: false)] + [Obsolete("Use the SubscribeOnCurrentWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)] public static IObservable SubscribeOnDispatcher(this IObservable source, DispatcherPriority priority) { if (source == null) diff --git a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Concurrency/CoreDispatcherScheduler.cs b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Concurrency/CoreDispatcherScheduler.cs index 439db5996..c64b17874 100644 --- a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Concurrency/CoreDispatcherScheduler.cs +++ b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Concurrency/CoreDispatcherScheduler.cs @@ -12,8 +12,8 @@ namespace System.Reactive.Concurrency { /// - /// Obsolete. The System.Reactive.Integration.WindowsForms NuGet package defines a - /// ControlScheduler class in the System.Reactive.Integration.WindowsForms + /// Obsolete. The System.Reactive.For.WindowsRuntime NuGet package defines a + /// CoreDispatcherScheduler class in the System.Reactive.WindowsForms /// namespace that replaces this class. /// /// @@ -22,7 +22,7 @@ namespace System.Reactive.Concurrency /// System.Reactive causes applications to end up with dependencies on Windows Forms and /// WPF whether they want them or not. /// - [Obsolete("Use System.Reactive.Integration.WindowsRuntime.CoreDispatcherScheduler in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use System.Reactive.WindowsRuntime.CoreDispatcherScheduler in the System.Reactive.For.WindowsRuntime package instead", error: false)] [CLSCompliant(false)] public sealed class CoreDispatcherScheduler : LocalScheduler, ISchedulerPeriodic { diff --git a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Foundation/AsyncInfoExtensions.cs b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Foundation/AsyncInfoExtensions.cs index 33817469e..d3f60fb0a 100644 --- a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Foundation/AsyncInfoExtensions.cs +++ b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Foundation/AsyncInfoExtensions.cs @@ -10,19 +10,19 @@ namespace System.Reactive.Windows.Foundation { /// /// Obsolete. Use the AsyncInfoObservableExtensions class in the - /// System.Reactive.Integration.WindowsRuntime namespace in the - /// System.Reactive.Integration.WindowsRuntime package instead. + /// System.Reactive.WindowsRuntime namespace in the + /// System.Reactive.For.WindowsRuntime package instead. /// /// /// /// Since this obsolete class is the only public type in the System.Reactive.Windows.Foundation /// namespace, existing code will normally need only to replace a using directive of /// using System.Reactive.Windows.Foundation; with - /// using System.Reactive.Integration.WindowsRuntime;. + /// using System.Reactive.WindowsRuntime;. /// /// [CLSCompliant(false)] - [Obsolete("Use the System.Reactive.Integration.WindowsRuntime.AsyncInfoObservableExtensions class in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the System.Reactive.WindowsRuntime.AsyncInfoObservableExtensions class in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static class AsyncInfoObservableExtensions { #region IAsyncAction and IAsyncActionWithProgress diff --git a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/IEventPatternSource.cs b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/IEventPatternSource.cs index e4e2742fe..214aa2b5c 100644 --- a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/IEventPatternSource.cs +++ b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/IEventPatternSource.cs @@ -8,8 +8,8 @@ namespace System.Reactive { /// - /// Obsolete. The System.Reactive.Integration.WindowsRuntime NuGet package defines an - /// ITypedEventPatternSource class that should be used instead. + /// Obsolete. The System.Reactive.For.WindowsRuntime NuGet package defines an + /// ITypedEventPatternSource interface that should be used instead. /// /// Sender type. /// Event arguments type. @@ -22,7 +22,7 @@ namespace System.Reactive /// /// /// The replacement type is not just in a different package and namespace. Its name has been - /// changed. There are two reasons. + /// changed to ITypedEventPatternSource. There are two reasons. /// /// /// First, the choice of name and namespace implied, wrongly, that this was a general purpose @@ -42,7 +42,7 @@ namespace System.Reactive /// other reasons. This could make it difficult for code to move cleanly onto the new /// definition for as long as the old one remains present in Obsolete form, because it /// might not always be possible to replace using System.Reactive; with, say, - /// using System.Reactive.Integration.WindowsRuntime; + /// using System.Reactive.WindowsRuntime; /// /// /// The main reason for pushing such code out into separate packages is to avoid a problem in @@ -66,7 +66,7 @@ namespace System.Reactive /// /// [CLSCompliant(false)] - [Obsolete("Use the System.Reactive.Integration.WindowsRuntime.IEventPatternSource interface in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the System.Reactive.WindowsRuntime.ITypedEventPatternSource interface in the System.Reactive.For.WindowsRuntime package instead", error: false)] public interface IEventPatternSource { /// diff --git a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/AsyncInfoObservable.cs b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/AsyncInfoObservable.cs index ed67e7605..a9ae10992 100644 --- a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/AsyncInfoObservable.cs +++ b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/AsyncInfoObservable.cs @@ -12,7 +12,7 @@ namespace System.Reactive.Linq { /// - /// Obsolete. The System.Reactive.Integration.WindowsRuntime NuGet package defines a + /// Obsolete. The System.Reactive.For.WindowsRuntime NuGet package defines a /// WindowsRuntimeAsyncInfoObservable class that defines new extension methods to be used in /// place of these (also in the System.Reactive.Linq namespace). /// @@ -79,7 +79,7 @@ namespace System.Reactive.Linq /// former even when running on Windows. /// /// - [Obsolete("Use the extension methods defined by the System.Reactive.Linq.WindowsRuntimeAsyncInfoObservable class in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the extension methods defined by the System.Reactive.Linq.WindowsRuntimeAsyncInfoObservable class in the System.Reactive.For.WindowsRuntime package instead", error: false)] [CLSCompliant(false)] public static class AsyncInfoObservable { @@ -87,13 +87,13 @@ public static class AsyncInfoObservable /// /// Obsolete. Use the WindowsRuntimeAsyncInfoObservable.ToIAsyncAction method in the - /// System.Reactive.Integration.WindowsRuntime package instead. + /// System.Reactive.For.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence to expose as an asynchronous action. /// Windows Runtime asynchronous action object representing the completion of the observable sequence. /// is null. - [Obsolete("Use the ToIAsyncAction extension method defined by System.Reactive.Linq.WindowsRuntimeAsyncInfoObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the ToIAsyncAction extension method defined by System.Reactive.Linq.WindowsRuntimeAsyncInfoObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IAsyncAction ToAsyncAction(this IObservable source) { if (source == null) @@ -108,13 +108,13 @@ public static IAsyncAction ToAsyncAction(this IObservable sour /// /// Obsolete. Use the WindowsRuntimeAsyncInfoObservable.ToIAsyncActionWithProgress - /// method in the System.Reactive.Integration.WindowsRuntime package instead. + /// method in the System.Reactive.For.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence to expose as an asynchronous action. /// Windows Runtime asynchronous action object representing the completion of the observable sequence, reporting incremental progress for each source sequence element. /// is null. - [Obsolete("Use the ToIAsyncActionWithProgress extension method defined by System.Reactive.Linq.WindowsRuntimeAsyncInfoObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the ToIAsyncActionWithProgress extension method defined by System.Reactive.Linq.WindowsRuntimeAsyncInfoObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IAsyncActionWithProgress ToAsyncActionWithProgress(this IObservable source) { if (source == null) @@ -131,7 +131,7 @@ public static IAsyncActionWithProgress ToAsyncActionWithProgress(t /// /// Obsolete. Use the WindowsRuntimeAsyncInfoObservable.ToIAsyncActionWithProgress - /// method in the System.Reactive.Integration.WindowsRuntime package instead. + /// method in the System.Reactive.For.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// The type of the elements in the progress sequence. @@ -139,7 +139,7 @@ public static IAsyncActionWithProgress ToAsyncActionWithProgress(t /// Selector function to map the source sequence on a progress reporting sequence. /// Windows Runtime asynchronous action object representing the completion of the result sequence, reporting progress computed through the progress sequence. /// or is null. - [Obsolete("Use the ToIAsyncActionWithProgress extension method defined by System.Reactive.Linq.WindowsRuntimeAsyncInfoObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the ToIAsyncActionWithProgress extension method defined by System.Reactive.Linq.WindowsRuntimeAsyncInfoObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IAsyncActionWithProgress ToAsyncActionWithProgress(this IObservable source, Func, IObservable> progressSelector) { if (source == null) @@ -177,13 +177,13 @@ public static IAsyncActionWithProgress ToAsyncActionWithProgress /// Obsolete. Use the WindowsRuntimeAsyncInfoObservable.ToAsyncOperation method in - /// the System.Reactive.Integration.WindowsRuntime package instead. + /// the System.Reactive.For.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence to expose as an asynchronous operation. /// Windows Runtime asynchronous operation object that returns the last element of the observable sequence. /// is null. - [Obsolete("Use the ToIAsyncOperation extension method defined by System.Reactive.Linq.WindowsRuntimeAsyncInfoObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the ToIAsyncOperation extension method defined by System.Reactive.Linq.WindowsRuntimeAsyncInfoObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IAsyncOperation ToAsyncOperation(this IObservable source) { if (source == null) @@ -196,13 +196,13 @@ public static IAsyncOperation ToAsyncOperation(this IObservabl /// /// Obsolete. Use the WindowsRuntimeAsyncInfoObservable.ToIAsyncOperationWithProgress - /// method in the System.Reactive.Integration.WindowsRuntime package instead. + /// method in the System.Reactive.For.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence to expose as an asynchronous operation. /// Windows Runtime asynchronous operation object that returns the last element of the observable sequence, reporting incremental progress for each source sequence element. /// is null. - [Obsolete("Use the ToIAsyncOperationWithProgress extension method defined by System.Reactive.Linq.WindowsRuntimeAsyncInfoObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the ToIAsyncOperationWithProgress extension method defined by System.Reactive.Linq.WindowsRuntimeAsyncInfoObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IAsyncOperationWithProgress ToAsyncOperationWithProgress(this IObservable source) { if (source == null) @@ -221,7 +221,7 @@ public static IAsyncOperationWithProgress ToAsyncOperationWithProg /// /// Obsolete. Use the WindowsRuntimeAsyncInfoObservable.ToIAsyncOperationWithProgress - /// method in the System.Reactive.Integration.WindowsRuntime package instead. + /// method in the System.Reactive.For.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// The type of the elements in the result sequence. @@ -229,7 +229,7 @@ public static IAsyncOperationWithProgress ToAsyncOperationWithProg /// Selector function to map the source sequence on a result sequence. /// Windows Runtime asynchronous operation object that returns the last element of the result sequence, reporting incremental progress for each source sequence element. /// or is null. - [Obsolete("Use the ToIAsyncOperationWithProgress extension method defined by System.Reactive.Linq.WindowsRuntimeAsyncInfoObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the ToIAsyncOperationWithProgress extension method defined by System.Reactive.Linq.WindowsRuntimeAsyncInfoObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IAsyncOperationWithProgress ToAsyncOperationWithProgress(this IObservable source, Func, IObservable> resultSelector) { if (source == null) @@ -251,7 +251,7 @@ public static IAsyncOperationWithProgress ToAsyncOperationWithProg /// /// Obsolete. Use the WindowsRuntimeAsyncInfoObservable.ToIAsyncOperationWithProgress - /// method in the System.Reactive.Integration.WindowsRuntime package instead. + /// method in the System.Reactive.For.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// The type of the elements in the result sequence. @@ -261,7 +261,7 @@ public static IAsyncOperationWithProgress ToAsyncOperationWithProg /// Selector function to map the source sequence on a progress reporting sequence. /// Windows Runtime asynchronous operation object that returns the last element of the result sequence, reporting progress computed through the progress sequence. /// or or is null. - [Obsolete("Use the ToIAsyncOperationWithProgress extension method defined by System.Reactive.Linq.WindowsRuntimeAsyncInfoObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the ToIAsyncOperationWithProgress extension method defined by System.Reactive.Linq.WindowsRuntimeAsyncInfoObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IAsyncOperationWithProgress ToAsyncOperationWithProgress(this IObservable source, Func, IObservable> resultSelector, Func, IObservable> progressSelector) { if (source == null) diff --git a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/CoreDispatcherObservable.cs b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/CoreDispatcherObservable.cs index 4a799a3f7..d823621b5 100644 --- a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/CoreDispatcherObservable.cs +++ b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/CoreDispatcherObservable.cs @@ -13,7 +13,7 @@ namespace System.Reactive.Linq { /// - /// Obsolete. The System.Reactive.Integration.WindowsRuntime NuGet package defines a + /// Obsolete. The System.Reactive.For.WindowsRuntime NuGet package defines a /// WindowsRuntimeCoreDispatcherObservable class that defines new extension methods to /// be used in place of these (also in the System.Reactive.Linq namespace). /// @@ -70,7 +70,7 @@ namespace System.Reactive.Linq /// /// [CLSCompliant(false)] - [Obsolete("Use the extension methods defined by the System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable class in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the extension methods defined by the System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable class in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static class CoreDispatcherObservable { #region ObserveOn[CoreDispatcher] @@ -78,14 +78,14 @@ public static class CoreDispatcherObservable /// /// Obsolete. Use the ObserveOnWindowsRuntimeCoreDispatcher extension method defined by /// System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the - /// System.Reactive.Integration.WindowsRuntime package instead. + /// System.Reactive.For.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence. /// Dispatcher whose associated message loop is used to notify observers on. /// The source sequence whose observations happen on the specified dispatcher. /// or is null. - [Obsolete("Use the ObserveOnWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the ObserveOnWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IObservable ObserveOn(this IObservable source, CoreDispatcher dispatcher) { if (source == null) @@ -104,7 +104,7 @@ public static IObservable ObserveOn(this IObservable /// /// Obsolete. Use the ObserveOnWindowsRuntimeCoreDispatcher extension method defined by /// System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the - /// System.Reactive.Integration.WindowsRuntime package instead. + /// System.Reactive.For.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -112,7 +112,7 @@ public static IObservable ObserveOn(this IObservable /// Priority to schedule work items at. /// The source sequence whose observations happen on the specified dispatcher. /// or is null. - [Obsolete("Use the ObserveOnWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the ObserveOnWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IObservable ObserveOn(this IObservable source, CoreDispatcher dispatcher, CoreDispatcherPriority priority) { if (source == null) @@ -132,14 +132,14 @@ public static IObservable ObserveOn(this IObservable /// /// Obsolete. Use the ObserveOnWindowsRuntimeCoreDispatcher extension method defined by /// System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the - /// System.Reactive.Integration.WindowsRuntime package instead. + /// System.Reactive.For.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence. /// Object to get the dispatcher from. /// The source sequence whose observations happen on the specified object's dispatcher. /// or is null. - [Obsolete("Use the ObserveOnWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the ObserveOnWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IObservable ObserveOn(this IObservable source, DependencyObject dependencyObject) { if (source == null) @@ -158,7 +158,7 @@ public static IObservable ObserveOn(this IObservable /// /// Obsolete. Use the ObserveOnWindowsRuntimeCoreDispatcher extension method defined by /// System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the - /// System.Reactive.Integration.WindowsRuntime package instead. + /// System.Reactive.For.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -166,7 +166,7 @@ public static IObservable ObserveOn(this IObservable /// Priority to schedule work items at. /// The source sequence whose observations happen on the specified object's dispatcher. /// or is null. - [Obsolete("Use the ObserveOnWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the ObserveOnWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IObservable ObserveOn(this IObservable source, DependencyObject dependencyObject, CoreDispatcherPriority priority) { if (source == null) @@ -185,13 +185,13 @@ public static IObservable ObserveOn(this IObservable /// /// Obsolete. Use the ObserveOnCurrentWindowsRuntimeCoreDispatcher extension method defined by /// System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the - /// System.Reactive.Integration.WindowsRuntime package instead. + /// System.Reactive.For.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence. /// The source sequence whose observations happen on the current window's dispatcher. /// is null. - [Obsolete("Use the ObserveOnCurrentWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the ObserveOnCurrentWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IObservable ObserveOnCoreDispatcher(this IObservable source) { if (source == null) @@ -205,14 +205,14 @@ public static IObservable ObserveOnCoreDispatcher(this IObserv /// /// Obsolete. Use the ObserveOnCurrentWindowsRuntimeCoreDispatcher extension method defined by /// System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the - /// System.Reactive.Integration.WindowsRuntime package instead. + /// System.Reactive.For.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence. /// Priority to schedule work items at. /// The source sequence whose observations happen on the current window's dispatcher. /// is null. - [Obsolete("Use the ObserveOnCurrentWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the ObserveOnCurrentWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IObservable ObserveOnDispatcher(this IObservable source, CoreDispatcherPriority priority) { if (source == null) @@ -230,7 +230,7 @@ public static IObservable ObserveOnDispatcher(this IObservable /// /// Obsolete. Use the SubscribeOnWindowsRuntimeCoreDispatcher extension method defined by /// System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the - /// System.Reactive.Integration.WindowsRuntime package instead. + /// System.Reactive.For.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -241,7 +241,7 @@ public static IObservable ObserveOnDispatcher(this IObservable /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the specified dispatcher. /// In order to invoke observer callbacks on the specified dispatcher, e.g. to render results in a control, use . /// - [Obsolete("Use the SubscribeOnWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the SubscribeOnWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IObservable SubscribeOn(this IObservable source, CoreDispatcher dispatcher) { if (source == null) @@ -260,7 +260,7 @@ public static IObservable SubscribeOn(this IObservable /// Obsolete. Use the SubscribeOnWindowsRuntimeCoreDispatcher extension method defined by /// System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the - /// System.Reactive.Integration.WindowsRuntime package instead. + /// System.Reactive.For.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -272,7 +272,7 @@ public static IObservable SubscribeOn(this IObservable. /// - [Obsolete("Use the SubscribeOnWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the SubscribeOnWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IObservable SubscribeOn(this IObservable source, CoreDispatcher dispatcher, CoreDispatcherPriority priority) { if (source == null) @@ -292,7 +292,7 @@ public static IObservable SubscribeOn(this IObservable /// Obsolete. Use the SubscribeOnWindowsRuntimeCoreDispatcher extension method defined by /// System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the - /// System.Reactive.Integration.WindowsRuntime package instead. + /// System.Reactive.For.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -303,7 +303,7 @@ public static IObservable SubscribeOn(this IObservable. /// - [Obsolete("Use the SubscribeOnWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the SubscribeOnWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IObservable SubscribeOn(this IObservable source, DependencyObject dependencyObject) { if (source == null) @@ -322,7 +322,7 @@ public static IObservable SubscribeOn(this IObservable /// Obsolete. Use the SubscribeOnWindowsRuntimeCoreDispatcher extension method defined by /// System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the - /// System.Reactive.Integration.WindowsRuntime package instead. + /// System.Reactive.For.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -334,7 +334,7 @@ public static IObservable SubscribeOn(this IObservable. /// - [Obsolete("Use the SubscribeOnWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the SubscribeOnWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IObservable SubscribeOn(this IObservable source, DependencyObject dependencyObject, CoreDispatcherPriority priority) { if (source == null) @@ -354,7 +354,7 @@ public static IObservable SubscribeOn(this IObservable /// Obsolete. Use the SubscribeOnCurrentWindowsRuntimeCoreDispatcher extension method defined by /// System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the - /// System.Reactive.Integration.WindowsRuntime package instead. + /// System.Reactive.For.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -364,7 +364,7 @@ public static IObservable SubscribeOn(this IObservable. /// - [Obsolete("Use the SubscribeOnCurrentWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the SubscribeOnCurrentWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IObservable SubscribeOnCoreDispatcher(this IObservable source) { if (source == null) @@ -378,7 +378,7 @@ public static IObservable SubscribeOnCoreDispatcher(this IObse /// /// Obsolete. Use the SubscribeOnCurrentWindowsRuntimeCoreDispatcher extension method defined by /// System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the - /// System.Reactive.Integration.WindowsRuntime package instead. + /// System.Reactive.For.WindowsRuntime package instead. /// /// The type of the elements in the source sequence. /// Source sequence. @@ -389,7 +389,7 @@ public static IObservable SubscribeOnCoreDispatcher(this IObse /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the dispatcher associated with the current window. /// In order to invoke observer callbacks on the dispatcher associated with the current window, e.g. to render results in a control, use . /// - [Obsolete("Use the SubscribeOnCurrentWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the SubscribeOnCurrentWindowsRuntimeCoreDispatcher extension method defined by System.Reactive.Linq.WindowsRuntimeCoreDispatcherObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IObservable SubscribeOnDispatcher(this IObservable source, CoreDispatcherPriority priority) { if (source == null) diff --git a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/WindowsObservable.Events.cs b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/WindowsObservable.Events.cs index 70a12be1c..958297fc4 100644 --- a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/WindowsObservable.Events.cs +++ b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/WindowsObservable.Events.cs @@ -8,7 +8,7 @@ namespace System.Reactive.Linq { /// - /// Obsolete. The System.Reactive.Integration.WindowsRuntime NuGet package defines a + /// Obsolete. The System.Reactive.For.WindowsRuntime NuGet package defines a /// WindowsRuntimeObservable class (also in the System.Reactive.Linq namespace) /// to use instead. /// @@ -75,7 +75,7 @@ namespace System.Reactive.Linq /// former even when running on Windows. /// /// - [Obsolete("Use the System.Reactive.Linq.WindowsRuntimeObservable class in the System.Reactive.Integration.WindowsRuntime instead", error: false)] + [Obsolete("Use the System.Reactive.Linq.WindowsRuntimeObservable class in the System.Reactive.For.WindowsRuntime instead", error: false)] [CLSCompliant(false)] public static partial class WindowsObservable { @@ -89,7 +89,7 @@ public static partial class WindowsObservable /// The observable sequence that contains data representations of invocations of the underlying typed event. /// or is null. /// - [Obsolete("Use the FromEventPattern method defined by System.Reactive.Linq.WindowsRuntimeObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the FromEventPattern method defined by System.Reactive.Linq.WindowsRuntimeObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IObservable> FromEventPattern(Action> addHandler, Action> removeHandler) { if (addHandler == null) @@ -130,7 +130,7 @@ public static IObservable> FromEventPatternThe observable sequence that contains data representations of invocations of the underlying typed event. /// or or is null. /// - [Obsolete("Use the FromEventPattern method defined by System.Reactive.Linq.WindowsRuntimeObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the FromEventPattern method defined by System.Reactive.Linq.WindowsRuntimeObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IObservable> FromEventPattern(Func, TDelegate> conversion, Action addHandler, Action removeHandler) { if (conversion == null) @@ -172,7 +172,7 @@ public static IObservable> FromEventPatternObservable source sequence. /// The event source object. /// is null. - [Obsolete("Use the ToWindowsFoundationEventPattern extension method defined by System.Reactive.Linq.WindowsRuntimeObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the ToWindowsFoundationEventPattern extension method defined by System.Reactive.Linq.WindowsRuntimeObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IEventPatternSource ToEventPattern(this IObservable> source) { if (source == null) diff --git a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/WindowsObservable.StandardSequenceOperators.cs b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/WindowsObservable.StandardSequenceOperators.cs index 3c7429d93..6bfcc59b1 100644 --- a/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/WindowsObservable.StandardSequenceOperators.cs +++ b/Rx.NET/Source/src/System.Reactive/Platforms/UWP/Linq/WindowsObservable.StandardSequenceOperators.cs @@ -20,7 +20,7 @@ public static partial class WindowsObservable /// An observable sequence whose elements are the result of the asynchronous operations executed for each element of the input sequence. /// or is null. /// This overload supports composition of observable sequences and Windows Runtime asynchronous operations, without requiring manual conversion of the asynchronous operations to observable sequences using . - [Obsolete("Use the SelectManyIAsyncOperation extension method defined by System.Reactive.Linq.WindowsRuntimeObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the SelectManyIAsyncOperation extension method defined by System.Reactive.Linq.WindowsRuntimeObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IObservable SelectMany(this IObservable source, Func> selector) { if (source == null) @@ -47,7 +47,7 @@ public static IObservable SelectMany(this IObservable /// An observable sequence whose elements are the result of the asynchronous operations executed for each element of the input sequence. /// or is null. /// This overload supports composition of observable sequences and Windows Runtime asynchronous operations, without requiring manual conversion of the asynchronous operations to observable sequences using . - [Obsolete("Use the SelectManyIAsyncOperationWithProgress extension method defined by System.Reactive.Linq.WindowsRuntimeObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the SelectManyIAsyncOperationWithProgress extension method defined by System.Reactive.Linq.WindowsRuntimeObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IObservable SelectMany(this IObservable source, Func> selector) { if (source == null) @@ -75,7 +75,7 @@ public static IObservable SelectMany(this /// An observable sequence whose elements are the result of obtaining an asynchronous operation for each element of the input sequence and then mapping the asynchronous operation's result and its corresponding source element to a result element. /// or or is null. /// This overload supports using LINQ query comprehension syntax in C# and Visual Basic to compose observable sequences and Windows Runtime asynchronous operations, without requiring manual conversion of the asynchronous operations to observable sequences using . - [Obsolete("Use the SelectManyIAsyncOperation extension method defined by System.Reactive.Linq.WindowsRuntimeObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the SelectManyIAsyncOperation extension method defined by System.Reactive.Linq.WindowsRuntimeObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IObservable SelectMany(this IObservable source, Func> asyncOperationSelector, Func resultSelector) { if (source == null) @@ -109,7 +109,7 @@ public static IObservable SelectManyAn observable sequence whose elements are the result of obtaining an asynchronous operation for each element of the input sequence and then mapping the asynchronous operation's result and its corresponding source element to a result element. /// or or is null. /// This overload supports using LINQ query comprehension syntax in C# and Visual Basic to compose observable sequences and Windows Runtime asynchronous operations, without requiring manual conversion of the asynchronous operations to observable sequences using . - [Obsolete("Use the SelectManyIAsyncOperationWithProgress extension method defined by System.Reactive.Linq.WindowsRuntimeObservable in the System.Reactive.Integration.WindowsRuntime package instead", error: false)] + [Obsolete("Use the SelectManyIAsyncOperationWithProgress extension method defined by System.Reactive.Linq.WindowsRuntimeObservable in the System.Reactive.For.WindowsRuntime package instead", error: false)] public static IObservable SelectMany(this IObservable source, Func> asyncOperationSelector, Func resultSelector) { if (source == null) diff --git a/Rx.NET/Source/tests/Tests.System.Reactive.ApiApprovals/Api/ApiApprovalTests.Core.verified.cs b/Rx.NET/Source/tests/Tests.System.Reactive.ApiApprovals/Api/ApiApprovalTests.Core.verified.cs index 116b69b48..e9f4243d7 100644 --- a/Rx.NET/Source/tests/Tests.System.Reactive.ApiApprovals/Api/ApiApprovalTests.Core.verified.cs +++ b/Rx.NET/Source/tests/Tests.System.Reactive.ApiApprovals/Api/ApiApprovalTests.Core.verified.cs @@ -237,8 +237,8 @@ public void Dispose() { } public void Wait(System.Action action) { } public void Wait(TState state, System.Action action) { } } - [System.Obsolete("Use System.Reactive.Integration.WindowsForms.ControlScheduler in the System.React" + - "ive.Integration.WindowsForms package instead", false)] + [System.Obsolete("Use System.Reactive.WindowsForms.ControlScheduler in the System.Reactive.For.Wind" + + "owsForms package instead", false)] public class ControlScheduler : System.Reactive.Concurrency.LocalScheduler, System.Reactive.Concurrency.ISchedulerPeriodic { public ControlScheduler(System.Windows.Forms.Control control) { } @@ -264,8 +264,8 @@ public override System.IDisposable Schedule(TState state, System.Func(TState state, System.TimeSpan dueTime, System.Func action) { } public System.IDisposable SchedulePeriodic(TState state, System.TimeSpan period, System.Func action) { } } - [System.Obsolete("Use System.Reactive.Integration.Wpf.DispatcherScheduler in the System.Reactive.In" + - "tegration.Wpf package instead", false)] + [System.Obsolete("Use System.Reactive.Wpf.DispatcherScheduler in the System.Reactive.For.Wpf packag" + + "e instead", false)] public class DispatcherScheduler : System.Reactive.Concurrency.LocalScheduler, System.Reactive.Concurrency.ISchedulerPeriodic { public DispatcherScheduler(System.Windows.Threading.Dispatcher dispatcher) { } @@ -835,68 +835,63 @@ public class QueryablePlan namespace System.Reactive.Linq { [System.Obsolete("Use the extension methods defined by the System.Reactive.Linq.WindowsFormsControl" + - "Observable class in the System.Reactive.Integration.WindowsForms package instead" + - "", false)] + "Observable class in the System.Reactive.For.WindowsForms package instead", false)] public static class ControlObservable { [System.Obsolete("Use the ObserveOnWindowsFormsControl extension method defined by System.Reactive." + - "Linq.WindowsFormsControlObservable in the System.Reactive.Integration.WindowsFor" + - "ms package instead", false)] + "Linq.WindowsFormsControlObservable in the System.Reactive.For.WindowsForms packa" + + "ge instead", false)] public static System.IObservable ObserveOn(this System.IObservable source, System.Windows.Forms.Control control) { } [System.Obsolete("Use the SubscribeOnWindowFormsControl extension method defined by System.Reactive" + - ".Linq.WindowsFormsControlObservable in the System.Reactive.Integration.WindowsFo" + - "rms package instead", false)] + ".Linq.WindowsFormsControlObservable in the System.Reactive.For.WindowsForms pack" + + "age instead", false)] public static System.IObservable SubscribeOn(this System.IObservable source, System.Windows.Forms.Control control) { } } [System.Obsolete("Use the extension methods defined by the System.Reactive.Linq.WpfDispatcherObserv" + - "able class in the System.Reactive.Integration.Wpf package instead", false)] + "able class in the System.Reactive.For.Wpf package instead", false)] public static class DispatcherObservable { [System.Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.W" + - "pfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", false)] + "pfDispatcherObservable in the System.Reactive.For.Wpf package instead", false)] public static System.IObservable ObserveOn(this System.IObservable source, System.Reactive.Concurrency.DispatcherScheduler scheduler) { } [System.Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.W" + - "pfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", false)] + "pfDispatcherObservable in the System.Reactive.For.Wpf package instead", false)] public static System.IObservable ObserveOn(this System.IObservable source, System.Windows.Threading.Dispatcher dispatcher) { } [System.Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.W" + - "pfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", false)] + "pfDispatcherObservable in the System.Reactive.For.Wpf package instead", false)] public static System.IObservable ObserveOn(this System.IObservable source, System.Windows.Threading.DispatcherObject dispatcherObject) { } [System.Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.W" + - "pfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", false)] + "pfDispatcherObservable in the System.Reactive.For.Wpf package instead", false)] public static System.IObservable ObserveOn(this System.IObservable source, System.Windows.Threading.Dispatcher dispatcher, System.Windows.Threading.DispatcherPriority priority) { } [System.Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.W" + - "pfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", false)] + "pfDispatcherObservable in the System.Reactive.For.Wpf package instead", false)] public static System.IObservable ObserveOn(this System.IObservable source, System.Windows.Threading.DispatcherObject dispatcherObject, System.Windows.Threading.DispatcherPriority priority) { } [System.Obsolete("Use the ObserveOnCurrentWpfDispatcher extension method defined by System.Reactive" + - ".Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package ins" + - "tead", false)] + ".Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", false)] public static System.IObservable ObserveOnDispatcher(this System.IObservable source) { } [System.Obsolete("Use the ObserveOnCurrentWpfDispatcher extension method defined by System.Reactive" + - ".Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package ins" + - "tead", false)] + ".Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", false)] public static System.IObservable ObserveOnDispatcher(this System.IObservable source, System.Windows.Threading.DispatcherPriority priority) { } [System.Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq" + - ".WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", false)] + ".WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", false)] public static System.IObservable SubscribeOn(this System.IObservable source, System.Reactive.Concurrency.DispatcherScheduler scheduler) { } [System.Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq" + - ".WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", false)] + ".WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", false)] public static System.IObservable SubscribeOn(this System.IObservable source, System.Windows.Threading.Dispatcher dispatcher) { } [System.Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq" + - ".WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", false)] + ".WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", false)] public static System.IObservable SubscribeOn(this System.IObservable source, System.Windows.Threading.DispatcherObject dispatcherObject) { } [System.Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq" + - ".WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", false)] + ".WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", false)] public static System.IObservable SubscribeOn(this System.IObservable source, System.Windows.Threading.Dispatcher dispatcher, System.Windows.Threading.DispatcherPriority priority) { } [System.Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq" + - ".WpfDispatcherObservable in the System.Reactive.Integration.Wpf package instead", false)] + ".WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", false)] public static System.IObservable SubscribeOn(this System.IObservable source, System.Windows.Threading.DispatcherObject dispatcherObject, System.Windows.Threading.DispatcherPriority priority) { } [System.Obsolete("Use the SubscribeOnCurrentWpfDispatcher extension method defined by System.Reacti" + - "ve.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package i" + - "nstead", false)] + "ve.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", false)] public static System.IObservable SubscribeOnDispatcher(this System.IObservable source) { } [System.Obsolete("Use the SubscribeOnCurrentWpfDispatcher extension method defined by System.Reacti" + - "ve.Linq.WpfDispatcherObservable in the System.Reactive.Integration.Wpf package i" + - "nstead", false)] + "ve.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", false)] public static System.IObservable SubscribeOnDispatcher(this System.IObservable source, System.Windows.Threading.DispatcherPriority priority) { } } public interface IGroupedObservable : System.IObservable diff --git a/Rx.NET/Source/tests/Tests.System.Reactive/Tests.System.Reactive.csproj b/Rx.NET/Source/tests/Tests.System.Reactive/Tests.System.Reactive.csproj index dbe142c20..77839382d 100644 --- a/Rx.NET/Source/tests/Tests.System.Reactive/Tests.System.Reactive.csproj +++ b/Rx.NET/Source/tests/Tests.System.Reactive/Tests.System.Reactive.csproj @@ -38,7 +38,7 @@ - - + + \ No newline at end of file diff --git a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/ControlSchedulerTest.cs b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/ControlSchedulerTest.cs index 6da3d65b7..db9fac706 100644 --- a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/ControlSchedulerTest.cs +++ b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/ControlSchedulerTest.cs @@ -15,7 +15,7 @@ using Assert = Xunit.Assert; using LegacyControlScheduler = System.Reactive.Concurrency.ControlScheduler; -using ControlScheduler = System.Reactive.Integration.WindowsForms.ControlScheduler; +using ControlScheduler = System.Reactive.WindowsForms.ControlScheduler; namespace ReactiveTests.Tests { diff --git a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/DispatcherSchedulerTest.cs b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/DispatcherSchedulerTest.cs index a2318f3a3..f0f782893 100644 --- a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/DispatcherSchedulerTest.cs +++ b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/DispatcherSchedulerTest.cs @@ -14,7 +14,7 @@ using Assert = Xunit.Assert; using LegacyDispatcherScheduler = System.Reactive.Concurrency.DispatcherScheduler; -using DispatcherScheduler = System.Reactive.Integration.Wpf.DispatcherScheduler; +using DispatcherScheduler = System.Reactive.Wpf.DispatcherScheduler; namespace ReactiveTests.Tests { diff --git a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/SchedulerTest.cs b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/SchedulerTest.cs index e4e94efc5..99cd82e48 100644 --- a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/SchedulerTest.cs +++ b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/SchedulerTest.cs @@ -17,12 +17,12 @@ #if HAS_WINFORMS using System.Windows.Forms; using LegacyControlScheduler = System.Reactive.Concurrency.ControlScheduler; -using ControlScheduler = System.Reactive.Integration.WindowsForms.ControlScheduler; +using ControlScheduler = System.Reactive.WindowsForms.ControlScheduler; #endif #if HAS_WPF using LegacyDispatcherScheduler = System.Reactive.Concurrency.DispatcherScheduler; -using DispatcherScheduler = System.Reactive.Integration.Wpf.DispatcherScheduler; +using DispatcherScheduler = System.Reactive.Wpf.DispatcherScheduler; #endif using System.Threading.Tasks; diff --git a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/Observable/ObserveOnTest.cs b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/Observable/ObserveOnTest.cs index faab29df2..2efb46004 100644 --- a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/Observable/ObserveOnTest.cs +++ b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/Observable/ObserveOnTest.cs @@ -18,13 +18,13 @@ using System.Windows.Threading; using LegacyDispatcherScheduler = System.Reactive.Concurrency.DispatcherScheduler; -using DispatcherScheduler = System.Reactive.Integration.Wpf.DispatcherScheduler; +using DispatcherScheduler = System.Reactive.Wpf.DispatcherScheduler; #endif #if HAS_WINFORMS using System.Windows.Forms; using LegacyControlScheduler = System.Reactive.Concurrency.ControlScheduler; -using ControlScheduler = System.Reactive.Integration.WindowsForms.ControlScheduler; +using ControlScheduler = System.Reactive.WindowsForms.ControlScheduler; #endif using Assert = Xunit.Assert; diff --git a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/Observable/SubscribeOnTest.cs b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/Observable/SubscribeOnTest.cs index 2192a6543..31c4b9631 100644 --- a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/Observable/SubscribeOnTest.cs +++ b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/Observable/SubscribeOnTest.cs @@ -16,13 +16,13 @@ using System.Reactive.Subjects; using LegacyDispatcherScheduler = System.Reactive.Concurrency.DispatcherScheduler; -using DispatcherScheduler = System.Reactive.Integration.Wpf.DispatcherScheduler; +using DispatcherScheduler = System.Reactive.Wpf.DispatcherScheduler; #endif #if HAS_WINFORMS using System.Windows.Forms; using LegacyControlScheduler = System.Reactive.Concurrency.ControlScheduler; -using ControlScheduler = System.Reactive.Integration.WindowsForms.ControlScheduler; +using ControlScheduler = System.Reactive.WindowsForms.ControlScheduler; #endif using Assert = Xunit.Assert; @@ -199,7 +199,7 @@ public void SubscribeOn_ControlScheduler() evt.Set(); }; }) - .SubscribeOn(new System.Reactive.Integration.WindowsForms.ControlScheduler(lbl)) + .SubscribeOn(new System.Reactive.WindowsForms.ControlScheduler(lbl)) .Subscribe(_ => { }); evt2.WaitOne(); diff --git a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/QbservableTest.cs b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/QbservableTest.cs index b6dfd73c5..e2c3c4edc 100644 --- a/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/QbservableTest.cs +++ b/Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/QbservableTest.cs @@ -22,12 +22,12 @@ using Assert = Xunit.Assert; #if HAS_WINFORMS using LegacyControlScheduler = System.Reactive.Concurrency.ControlScheduler; -using ControlScheduler = System.Reactive.Integration.WindowsForms.ControlScheduler; +using ControlScheduler = System.Reactive.WindowsForms.ControlScheduler; #endif #if HAS_WPF using LegacyDispatcherScheduler = System.Reactive.Concurrency.DispatcherScheduler; -using DispatcherScheduler = System.Reactive.Integration.Wpf.DispatcherScheduler; +using DispatcherScheduler = System.Reactive.Wpf.DispatcherScheduler; #endif namespace ReactiveTests.Tests From 35c735da49a7ad7efa85aba24a9cdb2509e88844 Mon Sep 17 00:00:00 2001 From: Ian Griffiths Date: Thu, 12 Jun 2025 14:38:22 +0100 Subject: [PATCH 8/8] Fixes required now MSBuild.Extras.SDK has gone --- .../Strings_PlatformServices.Designer.cs | 2 +- .../System.Reactive.For.Uwp.csproj | 9 ++++++++- .../System.Reactive.For.WindowsRuntime.csproj | 4 ++++ .../Tests.System.Reactive/Tests.System.Reactive.csproj | 2 +- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Rx.NET/Source/src/System.Reactive.For.Uwp/Strings_PlatformServices.Designer.cs b/Rx.NET/Source/src/System.Reactive.For.Uwp/Strings_PlatformServices.Designer.cs index 63e038741..6acaa5044 100644 --- a/Rx.NET/Source/src/System.Reactive.For.Uwp/Strings_PlatformServices.Designer.cs +++ b/Rx.NET/Source/src/System.Reactive.For.Uwp/Strings_PlatformServices.Designer.cs @@ -40,7 +40,7 @@ internal Strings_PlatformServices() { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Reactive.For.Uwp.Strings_PlatformServices", typeof(Strings_PlatformServices).GetTypeInfo().Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Reactive.Uwp.Strings_PlatformServices", typeof(Strings_PlatformServices).GetTypeInfo().Assembly); resourceMan = temp; } return resourceMan; diff --git a/Rx.NET/Source/src/System.Reactive.For.Uwp/System.Reactive.For.Uwp.csproj b/Rx.NET/Source/src/System.Reactive.For.Uwp/System.Reactive.For.Uwp.csproj index 0bfdf3490..d626d7b3e 100644 --- a/Rx.NET/Source/src/System.Reactive.For.Uwp/System.Reactive.For.Uwp.csproj +++ b/Rx.NET/Source/src/System.Reactive.For.Uwp/System.Reactive.For.Uwp.csproj @@ -1,7 +1,10 @@  - uap10.0.18362 + + uap10.0.18362 + System.Reactive.Uwp Rx;Reactive;Extensions;Observable;LINQ;Events;Windows Forms Reactive Extensions (Rx) for .NET @@ -13,6 +16,10 @@ enable + + + + diff --git a/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/System.Reactive.For.WindowsRuntime.csproj b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/System.Reactive.For.WindowsRuntime.csproj index c27fe104e..3302cb099 100644 --- a/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/System.Reactive.For.WindowsRuntime.csproj +++ b/Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/System.Reactive.For.WindowsRuntime.csproj @@ -29,6 +29,10 @@ enable + + + + diff --git a/Rx.NET/Source/tests/Tests.System.Reactive/Tests.System.Reactive.csproj b/Rx.NET/Source/tests/Tests.System.Reactive/Tests.System.Reactive.csproj index d0ab92a01..03bd609e0 100644 --- a/Rx.NET/Source/tests/Tests.System.Reactive/Tests.System.Reactive.csproj +++ b/Rx.NET/Source/tests/Tests.System.Reactive/Tests.System.Reactive.csproj @@ -37,7 +37,7 @@ - +