We ran into an interesting bug (?) recently, while updating our services to .NET Core we suddenly started receiving strange build errors, like:
The type 'IAsyncAction' is defined in an assembly that is not referenced. You must add a reference to assembly 'Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime'.
The type 'IAsyncActionWithProgress<>' is defined in an assembly that is not referenced. You must add a reference to assembly 'Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime'.
The type 'IAsyncOperation<>' is defined in an assembly that is not referenced. You must add a reference to assembly 'Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime'.
The type 'IAsyncOperationWithProgress<,>' is defined in an assembly that is not referenced. You must add a reference to assembly 'Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime'.
These errors were pointing to lines where we directly await
ed IObservable
s, like
await Observable.Return("Hello World");The clue
As I've been rigorously scanning through our dependencies and project file definitions, one thing stood out, that the System.Reactive
NuGet package has a reference to System.Runtime.InteropServices.WindowsRuntime
for netstandard2.0
target. ( link ).
This on its own though is not causing any immediate trouble...
The realizationI created a clean project with reference to Rx and tried to await
an IObservable
... and it worked just fine, so I figured, the issue will be somewhere else... So I started stripping down the dependencies from our original project, until it finally built successfully.
And then I found that because we migrated to .NET Core, we no longer had implicit access to certain Windows specific APIs, so we referenced Microsoft.Windows.Compatibility
and by doing that we must have activated a special scenario for Rx's platform services, or something where it started to try to be WinRT compatible and give us those errors when trying to await
on an IObservable
.
The solution was to either reference the more specific compatibility packages, like System.Configuration.ConfigurationManager
and System.ServiceProcess.ServiceController
and/or to explicitly use the ToTask()
extension method before attempting to await
an IObservable
.
With all this, I'm still a little confused about why Rx has reference to WinRT Interop package for its .NET Standard (cross platform) target? I'd guess this weird issue would never have came up in the first place if it wouldn't have that reference.
Reprocsproj file
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp3.0</TargetFramework> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.Windows.Compatibility" Version="3.0.0" /> <PackageReference Include="System.Reactive" Version="4.1.6" /> </ItemGroup> </Project>
Program.cs
using System; using System.Reactive.Linq; using System.Threading.Tasks; namespace Repro { class Program { static async Task Main(string[] args) { await Observable.Return("Hello World"); } } }
SuperJMN, theodorzoulias and glopesdev
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4