-
Notifications
You must be signed in to change notification settings - Fork 10.4k
Target netstandard2.1 for SignalR client #10540
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't change a couple libraries like Http.Connections.Common
because the reason we cross-targeted that one was to not pull in the System.Text.Json
package on netcoreapp3.0
#else | ||
var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); | ||
if (!isWindows) | ||
try |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we can do a compile time check here, for example, someone running on netcoreapp3.0 but targeting the netstandard2.0 library on windows 7 will have access to the managed websockets impl, but if we just hardcoded netstandard2.0 as not having websockets then a scenario that should work will not work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This kinda sucks....
@@ -49,7 +49,7 @@ public partial class HubConnection | |||
}; | |||
|
|||
private static readonly MethodInfo _sendStreamItemsMethod = typeof(HubConnection).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).Single(m => m.Name.Equals(nameof(SendStreamItems))); | |||
#if NETCOREAPP3_0 | |||
#if NETSTANDARD2_1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe all the #if NETSTANDARD2_1
checks should be #if !NETSTANDARD2_0
, that way we might never have to update them in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doubt it matters. We can't be sure at this point when we'll drop .NET Standard 2.0 support, update 2.1 to something newer, add a new TFM, …
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What you can do is have ifdefs based on the available feature.
For example, this test could be #if HAVE_ASYNCENUMERABLE
. Then in the csproj against NETSTANDARD2_1
you would define HAVE_ASYNCENUMERABLE
.
Now when a new target is added in the future, e.g. netcoreapp50, you just add it to the csproj and set the required flags. No need to update individual source code files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We know that all targets after netstandard2.0 will have these new APIs so I don't see why we'd add extra upkeep when a simple !NETSTANDARD2_0
check will do. And in the future if we remove netstandard2.0 compatibility then we just remove the #if
entirely.
If for some crazy reason we do have future targets that remove features like IAsyncEnumerable
then we can revisit and add feature flags.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Future targets will never remove IAsyncEnumerable but future targets will add new features that you will likely want to use. With multiple targets things start getting complicated quickly...
A new feature in 3.0: #if !(NETSTANDARD2_0 || NETSTANDARD2_1)
A new feature in 4.0: #if !(NETSTANDARD2_0 || NETSTANDARD2_1 || NETSTANDARD3_0)
etc
Meanwhile using feature flags are a single test that and easy to read and all visible in the csproj to see what each target supports.
@@ -24,13 +24,26 @@ public static IAsyncEnumerable<T> MakeCancelableTypedAsyncEnumerable<T>(IAsyncEn | |||
return new CancelableTypedAsyncEnumerable<T>(asyncEnumerable, cts); | |||
} | |||
|
|||
#if NETCOREAPP3_0 | |||
public static async IAsyncEnumerable<object> MakeAsyncEnumerableFromChannel<T>(ChannelReader<T> channel, [EnumeratorCancellation] CancellationToken cancellationToken = default) | |||
{ | |||
await foreach (var item in channel.ReadAllAsync(cancellationToken)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
channel.ReadAllAsync
isn't available on netstandard2.1
, is this something we should ask CoreFX to provide or...?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might get this for free with https://github.com/dotnet/corefx/issues/34963
Directory.Build.targets
Outdated
<!-- Only update the default runtime version for preview builds. --> | ||
<DefaultRuntimeFrameworkVersion Condition="'%(TargetFramework)' == '$(DefaultNetCoreTargetFramework)' and '$(IsServicingBuild)' != 'true'">$(MicrosoftNETCoreAppPackageVersion)</DefaultRuntimeFrameworkVersion> | ||
<!-- Only update the targeting pack version for preview builds. --> | ||
<TargetingPackVersion Condition="'%(TargetFramework)' == '$(DefaultNetCoreTargetFramework)' and '$(IsServicingBuild)' != 'true'">$(MicrosoftNETCoreAppPackageVersion)</TargetingPackVersion> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest moving the consistent Condition="'%(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'"
to the <KnownFrameworkReference>
element as is done below.
@@ -49,7 +49,7 @@ public partial class HubConnection | |||
}; | |||
|
|||
private static readonly MethodInfo _sendStreamItemsMethod = typeof(HubConnection).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).Single(m => m.Name.Equals(nameof(SendStreamItems))); | |||
#if NETCOREAPP3_0 | |||
#if NETSTANDARD2_1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doubt it matters. We can't be sure at this point when we'll drop .NET Standard 2.0 support, update 2.1 to something newer, add a new TFM, …
src/SignalR/clients/csharp/Client.Core/ref/Microsoft.AspNetCore.SignalR.Client.Core.csproj
Show resolved
Hide resolved
We might be delaying this until preview7. I'll probably spin up a PR with just the infrastructure changes. |
At this point unless we're super clear on what we're doing, deferring to preview 7 seems safest :). |
🆙 📅 This should be good now |
public string TransportType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } | ||
} | ||
} | ||
namespace Microsoft.AspNetCore.Http.Connections.Client.Internal |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to make these internal 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#10169 !
Reviewers? My main concern with this is that we only test the netcoreapp3.0 versions of the binaries. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I only see one place where we are conditional on netcoreapp3.0
without also supporting netstandard2.1
, what's the value of keeping that TFM in place? Is there actually different code we want to write?
@@ -24,13 +24,26 @@ public static IAsyncEnumerable<T> MakeCancelableTypedAsyncEnumerable<T>(IAsyncEn | |||
return new CancelableTypedAsyncEnumerable<T>(asyncEnumerable, cts); | |||
} | |||
|
|||
#if NETCOREAPP3_0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this not possible in NETSTANDARD2_1
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
channel.ReadAllAsync
isn't in netstandard2.1 currently. And they seem to not be interested in moving corefx to netstandard2.1 currently. https://github.com/dotnet/corefx/issues/34963
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want an API added to netstandard2.1 you should request it on dotnet/standard, e.g. dotnet/standard#1144
(as far as I know. Worst case they can only say no 😋)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Channels isn't in netstandard
at all, it's a library that targets netstandard2.0
(and doesn't cross-target 2.1).
My understanding of that issue though is that corefx isn't going to bulk-update to target 2.1. I think it doesn't preclude targeting 2.1 in a particular assembly.
If we really think netstandard2.1
is worth it here then I guess this is why we need to triple-target. It just seems counter-productive to keep doing this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is what the world of developing libraries that run everywhere is like.
btw I still think you should use feature flags. If makes this stuff easier #10540 (comment)
#VoiceOfExperience
@davidfowl is wanting to put the client in the shared framework. |
Does that require the |
I want no unnecessary deps when running on netcoreapp3.0 as well. |
What unnecessary deps are there? |
I was also assuming we'd use the Microsoft.Bcl.AsyncInterfaces on ns2.0 |
Right but why would embedding this package in the shared framework be a problem if all it's deps are in the shared fx? I don't understand how a separate build actually solves what seems to be a deployment problem. When this is embedded in the shared framework, it's dependencies will already be there so it should only add this single assembly. Even if we use the The comment above about |
@@ -32,9 +32,11 @@ await foreach (var item in channel.ReadAllAsync(cancellationToken)) | |||
} | |||
} | |||
#else | |||
// System.Threading.Channels.ReadAllAsync() is not available on netstandard2.0 and netstandard2.1 | |||
// But this is the exact same code that it uses |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was just going to ask for this after our convo 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment was made automatically. If there is a problem contact [email protected]. I've triaged the above build. I've created/commented on the following issue(s) |
return true; | ||
} | ||
else | ||
catch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we know what get thrown in practice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NotSupportedException
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I figured. This is gross, but catching only the NotSupportedException
is probably even worse.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we cache this now?
@aspnet/build Can someone merge please. Seems some kind of AzDo and GitHub integration is broken, everything is passing if you manually check. |
Fixes #9525
Fixes #10607