Reactive Extensions, assemblies, installers, and NuGet - The full story RRS feed

  • General discussion

  • Hi everyone,

    Over the past few months, you've seen quite a bit of churn to Rx in preparation of the final release which we published today. We know it's been a rough ride, with regards to some of the API changes, assembly refactoring, and installation changes. The API level changes have been discussed on the forum quite a bit, so I wanted to focus on assemblies and installation aspects in this post.

    Before I go on, I should point out we're incredibly thankful for all the feedback and we appreciate you've followed us on the rough ride with regards to any of the aspects mentioned above. Thanks a lot!


    Rx Assemblies

    As part of the stabilization of the API, we focused on straightening out the assembly dependencies of Rx.

    In the past, Rx used to depend on UI library assemblies such as WindowsBase, System.Windows, and System.Windows.Forms in order to provide scheduling facilities. Although those references are not necessarily exercised during the execution of a program depending on Rx, it didn't make much sense in a layer map to have those dependencies for something as generic as an event processing library. As a result, we refactored out the UI dependencies in System.Reactive.Windows.Forms.dll (for Windows Forms) and System.Reactive.Windows.Threading.dll (for WPF and Silverlight).

    Expression trees leveraged by the IQbservable<T> interface and its associated operators pose another problem because they're not fully supported on all Rx platforms. For example, on Windows Phone 7, there's no support for expression tree compilation, required by the AsQbservable/AsObservable operator pair. Other platforms we historically supported in Rx didn't have expression trees at all. Moreover, the use of IQbservable<T> is less common today (though you'll most likely see observable query providers popping up), so it made sense to split off this functionality as well, resulting in System.Reactive.Providers.dll.

    You may also wonder about support for the Task Parallel Library (TPL). Because the TPL is included with core framework assemblies, there's no dependency-driven refactoring involved with this: it either is there, or it isn't. Going forward, with the Async CTP features relying on Task<T>, the TPL will be the norm rather than an outlier. In the past, we shipped a backport of the TPL for .NET Framework 3.5. We no longer do because of supportability reasons, but you're totally free to archive the System.Threading.dll binary from previous versions and use it as-is, with no support provided. And of course, if you can, moving to .NET 4 is a good thing.

    Dependencies for the core Rx interfaces, IObservable<T> and IObserver<T>, are imported in slightly different ways depending on the platform. For .NET 4, the interfaces are part of the core .NET Framework assemblies. For .NET 3.5 and Silverlight 4, we include them in System.Reactive.dll. For Windows Phone 7, a reference to the System.Observable.dll is used in order to provide compatibility with the version of Rx that ships in the ROM.

    Refactoring those assemblies led to a few API-level changes as well:

    • For UI scheduling, reference the appropriate Rx UI assembly matching your UI technology of choice, and you'll see ObserveOn overloads and/or the ObserveOnDispatcher operator appear as extension methods. Use the ControlScheduler and DispatcherScheduler types if you need use schedulers directly.
    • Notice Scheduler.Dispatcher no longer exists because there's no way to span classes across multiple assemblies (runtime partial classes if you will), nor do we have "static extension properties". Instead, use the DispatcherScheduler.Instance property or construct an instance yourself.
    • To refer to the local query provider for use with IQbservable<T> - formerly defined as Observable.Provider - include the System.Reactive.Providers assembly in your project and use the Qbservable.Provider property instead.

    All of those changes should minimize the assembly-level differences across different platforms, both in terms of required references and what's inside the assemblies (e.g. System.Reactive is fairly similar on all platform, modulo extra Func<> and Action<> overloads or TPL dependencies).


    Rx Version Numbers

    Before the splits between Experimental and Stable releases of Rx, our version scheme was a straightforward 1.0.xxxx pattern, where xxxx was a daily build increment number. Many of you will have worked with versions such as 1.0.2838 in the past.

    Part of the work on splitting the releases was to give them distinct numbering schemes. With the Experimental release always looking at the latest and greatest, we chose to put it one minor version number unit ahead, leading to Experimental 1.1 version numbers for and Stable 1.0 version numbers. The new build number scheme is ymmdd, where y is the year of the Rx release (currently we're in our "first year", 1), mm the month (06 for the RTW build), and dd the day (21 for the RTW build), pretty similar to the .NET Framework's build number scheme.

    So, the final builds of Rx were produced on 6/21/2011 (start of the spring on this hemisphere).


    Rx Installers

    The installation of Rx has changed to become an SDK rather than a redistributable package. Basically this boils down to an installer that drops a reference assemblies folder on your development machine (containing assemblies and XML doc comment files), also registering Add Reference... dialog entries for the platforms included. Installations of different versions of Rx (including Experimental versus Stable) can co-exist side-by-side.

    After the installation, you can find the Rx reference assemblies under your Program Files (x86) folder, following the Microsoft Reactive Extensions SDK\v1.0.10621\Binaries path. There you can find a license and redist file, as well as the folder layout containing the binaries. Normally, you don't have to poke at this folder directly; instead, you can use the Add Reference... dialog in Visual Studio for all practical uses.

    In particular, the installer doesn't drop assemblies in the GAC as it did before. Rx assemblies get copied into your build output (unless you tweak the Copy Local setting for the reference in your project), and you control how you want to package up assemblies and install them on end-user machines. Notice the assemblies are strong name signed, so you can put them in the GAC if you really want, but an xcopy deployment typically suffices.


    Rx on NuGet

    Rx adopted NuGet early on, being an early adopter. During the last year, NuGet has evolved rapidly and become a popular way to include packages into Visual Studio projects. We're extremely pleased to have Rx available through NuGet as well. The history on package names is quite involved, and we want to apologize for the friction some of the changes have caused (as noted by some people on social networking sites). This said, we're now using a final naming scheme that will take us beyond. Here's the story.

    Initially, we had a number of Rx packages on NuGet with the Rx- naming prefix, e.g. Rx-Core and Rx-Main 1.0.2838. In general, the naming reflects mappings onto the underlying assembly contained within the package. As we moved on to refactor the API, some assemblies went away, while others were welcomed to the happy Rx family. This made some names no longer relevant, for example Rx-Core was obsoleted due to the elimination of System.CoreEx.dll which got embedded into the main System.Reactive assembly.

    As part of the initial wave of changes, we defined the following packages:

    • Rx-Main - System.Reactive.dll (for all platforms)
    • Rx-Providers - System.Reactive.Providers.dll (for .NET 3.5, .NET 4, and Silverlight 4)
    • Rx-WPF - System.Reactive.Windows.Threading.dll (for .NET 3.5 and .NET 4)
    • Rx-Silverlight - System.Reactive.Windows.Threading.dll (for Silverlight 4 and Windows Phone 7)
    • Rx-WinForms - System.Reactive.Windows.Forms.dll (for .NET 3.5 and .NET 4)
    • Rx-Testing - Microsoft.Reactive.Testing.dll (for all platforms)

    You may notice the artificial difference between the WPF and Silverlight packages, really containing an assembly with the same name. We think it's easier for users to choose the bridges they want to build in terms of the UI technology's name, rather than some cryptic all-encompassing name. Also, we started to use NuGet features to declare dependencies with framework assemblies, which differ in both packages, referring to WindowsBase in one, and System.Windows.Threading in the other.

    Rx-All has been removed. It no longer makes sense to define what "all" means for the "typical" customer of Rx. Do you really use all UI frameworks, as well as provider capabilities? Or did you just want Rx-Main? Most likely you don't want to include testing in your project all the time. Rx-All is nothing but a historical thing that arose from Rx-Core and Rx-Main splits.

    As we moved to a Stable versus Experimental release split, we had to do something to provide both flavors online. Because NuGet doesn't have a good way to structure stable/unstable versions of the same package yet, we had to make a call whether to upload Experimental or Stable packages for the 1.x.10425 build. We chose the former option, reflecting our history of always and rapidly evolving releases, hoping to see the NuGet feature for stable/unstable versioning by the time we released. As a result, we jumped from version 1.0.2856 to version 1.1.10425 in the NuGet repository.

    By the time we got around to shipping the RC release of Rx (build 10605), we didn't have the stable/unstable NuGet versioning feature yet, and we learned from customers they like to use NuGet also to get stable packages, so only shipping experimental was no longer an option. To keep true to the old naming scheme - in particular Rx-Main which a lot of people were used to searching for - we wanted to use the well-known Rx- prefixes for the stable release (1.0.10605). We came up with the Rx_Experimental- prefix for the experimental release (1.1.10605), because we couldn't clash with the stable releases which have a lower version number and wouldn't show up in dialogs due to the missing stable/unstable feature in NuGet. The unfortunate implication of this was a drop in the version numbers of Rx- packages from 1.1.10425 to 1.0.10605. We decided to bite the bullet to land with a final naming scheme, realizing it'd cause a bit of friction. Sorry.

    So, this is where we're at. In short, search for Rx- to find stable releases, and Rx_Experimental- to find experimental releases. Oh, and we use the Ix_Experimental- prefix for Interactive Extensions (Ix), reflecting the same naming scheme.


    -Rx team

    using (Microsoft.Sql.Cloud.DataProgrammability.Rx) { Signature.Emit("Bart De Smet"); }
    Wednesday, June 29, 2011 11:21 PM

All replies