Skip to content

Commit e7b84b7

Browse files
authored
Refactor HubConnectionBuilder (#1830)
1 parent 99ae47b commit e7b84b7

File tree

44 files changed

+428
-569
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+428
-569
lines changed

SignalR.sln

-14
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Signal
8181
EndProject
8282
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Protocols.MsgPack", "src\Microsoft.AspNetCore.SignalR.Protocols.MsgPack\Microsoft.AspNetCore.SignalR.Protocols.MsgPack.csproj", "{55DB4B6F-12E5-4A27-97F4-E97E135470FF}"
8383
EndProject
84-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.MsgPack", "src\Microsoft.AspNetCore.SignalR.MsgPack\Microsoft.AspNetCore.SignalR.MsgPack.csproj", "{FDDB4E1F-2FD2-49E8-B0FF-874B0931369A}"
85-
EndProject
86-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Client.MsgPack", "src\Microsoft.AspNetCore.SignalR.Client.MsgPack\Microsoft.AspNetCore.SignalR.Client.MsgPack.csproj", "{4DBF918E-BD37-4309-B448-BA68C935944D}"
87-
EndProject
8884
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FunctionalTests", "clients\ts\FunctionalTests\FunctionalTests.csproj", "{D0C7B22E-B0B6-4D62-BF7D-79EE4AAF1981}"
8985
EndProject
9086
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BenchmarkServer", "benchmarks\BenchmarkServer\BenchmarkServer.csproj", "{B5286020-C218-443C-91A9-B65751FB9B29}"
@@ -195,14 +191,6 @@ Global
195191
{55DB4B6F-12E5-4A27-97F4-E97E135470FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
196192
{55DB4B6F-12E5-4A27-97F4-E97E135470FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
197193
{55DB4B6F-12E5-4A27-97F4-E97E135470FF}.Release|Any CPU.Build.0 = Release|Any CPU
198-
{FDDB4E1F-2FD2-49E8-B0FF-874B0931369A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
199-
{FDDB4E1F-2FD2-49E8-B0FF-874B0931369A}.Debug|Any CPU.Build.0 = Debug|Any CPU
200-
{FDDB4E1F-2FD2-49E8-B0FF-874B0931369A}.Release|Any CPU.ActiveCfg = Release|Any CPU
201-
{FDDB4E1F-2FD2-49E8-B0FF-874B0931369A}.Release|Any CPU.Build.0 = Release|Any CPU
202-
{4DBF918E-BD37-4309-B448-BA68C935944D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
203-
{4DBF918E-BD37-4309-B448-BA68C935944D}.Debug|Any CPU.Build.0 = Debug|Any CPU
204-
{4DBF918E-BD37-4309-B448-BA68C935944D}.Release|Any CPU.ActiveCfg = Release|Any CPU
205-
{4DBF918E-BD37-4309-B448-BA68C935944D}.Release|Any CPU.Build.0 = Release|Any CPU
206194
{D0C7B22E-B0B6-4D62-BF7D-79EE4AAF1981}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
207195
{D0C7B22E-B0B6-4D62-BF7D-79EE4AAF1981}.Debug|Any CPU.Build.0 = Debug|Any CPU
208196
{D0C7B22E-B0B6-4D62-BF7D-79EE4AAF1981}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -241,8 +229,6 @@ Global
241229
{1A953296-E869-4DE2-A693-FD5FCDE27057} = {C4BC9889-B49F-41B6-806B-F84941B2549B}
242230
{0A0A6135-EA24-4307-95C2-CE1B7E164A5E} = {6A35B453-52EC-48AF-89CA-D4A69800F131}
243231
{55DB4B6F-12E5-4A27-97F4-E97E135470FF} = {DA69F624-5398-4884-87E4-B816698CDE65}
244-
{FDDB4E1F-2FD2-49E8-B0FF-874B0931369A} = {DA69F624-5398-4884-87E4-B816698CDE65}
245-
{4DBF918E-BD37-4309-B448-BA68C935944D} = {DA69F624-5398-4884-87E4-B816698CDE65}
246232
{D0C7B22E-B0B6-4D62-BF7D-79EE4AAF1981} = {3A76C5A2-79ED-49BC-8BDC-6A3A766FFA1B}
247233
{B5286020-C218-443C-91A9-B65751FB9B29} = {8A4582C8-DC59-4B61-BCE7-119FBAA99EFB}
248234
EndGlobalSection

benchmarks/BenchmarkServer/BenchmarkServer.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
</ItemGroup>
1010

1111
<ItemGroup>
12-
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.MsgPack\Microsoft.AspNetCore.SignalR.MsgPack.csproj" />
12+
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Protocols.MsgPack\Microsoft.AspNetCore.SignalR.Protocols.MsgPack.csproj" />
1313
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR\Microsoft.AspNetCore.SignalR.csproj" />
1414

1515
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />

benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/HubConnectionSendBenchmark.cs

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4+
using System;
45
using System.Buffers;
56
using System.IO.Pipelines;
67
using System.Threading.Tasks;
78
using BenchmarkDotNet.Attributes;
9+
using Microsoft.AspNetCore.Connections;
810
using Microsoft.AspNetCore.Connections.Features;
911
using Microsoft.AspNetCore.SignalR.Client;
1012
using Microsoft.AspNetCore.SignalR.Internal;
1113
using Microsoft.AspNetCore.SignalR.Internal.Protocol;
1214
using Microsoft.AspNetCore.SignalR.Microbenchmarks.Shared;
15+
using Microsoft.Extensions.DependencyInjection;
1316
using Microsoft.Extensions.Logging.Abstractions;
1417

1518
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
@@ -47,7 +50,12 @@ public void GlobalSetup()
4750
connection.Transport = _pipe;
4851

4952
var protocol = Protocol == "json" ? (IHubProtocol)new JsonHubProtocol() : new MessagePackHubProtocol();
50-
_hubConnection = new HubConnection(() => connection, protocol, new NullLoggerFactory());
53+
54+
var hubConnectionBuilder = new HubConnectionBuilder();
55+
hubConnectionBuilder.WithHubProtocol(protocol);
56+
hubConnectionBuilder.WithConnectionFactory(() => connection);
57+
58+
_hubConnection = hubConnectionBuilder.Build();
5159
_hubConnection.StartAsync().GetAwaiter().GetResult();
5260

5361
_arguments = new object[ArgumentCount];

benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/HubConnectionStartBenchmark.cs

+6-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
using Microsoft.AspNetCore.SignalR.Internal;
1414
using Microsoft.AspNetCore.SignalR.Internal.Protocol;
1515
using Microsoft.AspNetCore.SignalR.Microbenchmarks.Shared;
16+
using Microsoft.Extensions.DependencyInjection;
1617
using Microsoft.Extensions.Logging.Abstractions;
1718

1819
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
@@ -44,7 +45,11 @@ public void GlobalSetup()
4445
connection.Features.Set<IConnectionInherentKeepAliveFeature>(new TestConnectionInherentKeepAliveFeature());
4546
connection.Transport = _pipe;
4647

47-
_hubConnection = new HubConnection(() => connection, new JsonHubProtocol(), new NullLoggerFactory());
48+
var hubConnectionBuilder = new HubConnectionBuilder();
49+
hubConnectionBuilder.WithHubProtocol(new JsonHubProtocol());
50+
hubConnectionBuilder.WithConnectionFactory(() => connection);
51+
52+
_hubConnection = hubConnectionBuilder.Build();
4853
}
4954

5055
private void AddHandshakeResponse()

clients/ts/FunctionalTests/FunctionalTests.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
</ItemGroup>
2020

2121
<ItemGroup>
22-
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.SignalR.MsgPack\Microsoft.AspNetCore.SignalR.MsgPack.csproj" />
22+
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.SignalR.Protocols.MsgPack\Microsoft.AspNetCore.SignalR.Protocols.MsgPack.csproj" />
2323
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.SignalR\Microsoft.AspNetCore.SignalR.csproj" />
2424
</ItemGroup>
2525

samples/ClientSample/Tcp/TcpHubConnectionBuilderExtensions.cs

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1-
using System.Net;
1+
using System;
2+
using System.Net;
23
using ClientSample;
4+
using Microsoft.AspNetCore.Connections;
5+
using Microsoft.Extensions.DependencyInjection;
6+
using Microsoft.Extensions.DependencyInjection.Extensions;
37

48
namespace Microsoft.AspNetCore.SignalR.Client
59
{
610
public static class TcpHubConnectionBuilderExtensions
711
{
812
public static IHubConnectionBuilder WithEndPoint(this IHubConnectionBuilder builder, IPEndPoint endPoint)
913
{
10-
builder.ConfigureConnectionFactory(() => new TcpConnection(endPoint));
14+
builder.WithConnectionFactory(() => new TcpConnection(endPoint));
1115

1216
return builder;
1317
}

samples/JwtClientSample/Program.cs

+6-4
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,15 @@ await Task.WhenAll(
2828

2929
private async Task RunConnection(HttpTransportType transportType)
3030
{
31-
var userId = "C#" + transportType.ToString();
31+
var userId = "C#" + transportType;
3232
_tokens[userId] = await GetJwtToken(userId);
3333

3434
var hubConnection = new HubConnectionBuilder()
35-
.WithUrl(ServerUrl + "/broadcast")
36-
.WithTransport(transportType)
37-
.WithAccessToken(() => _tokens[userId])
35+
.WithUrl(ServerUrl + "/broadcast", options =>
36+
{
37+
options.Transport = transportType;
38+
options.AccessTokenFactory = () => _tokens[userId];
39+
})
3840
.Build();
3941

4042
var closedTcs = new TaskCompletionSource<object>();

samples/SignalRSamples/SignalRSamples.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10-
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.MsgPack\Microsoft.AspNetCore.SignalR.MsgPack.csproj" />
10+
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Protocols.MsgPack\Microsoft.AspNetCore.SignalR.Protocols.MsgPack.csproj" />
1111
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR\Microsoft.AspNetCore.SignalR.csproj" />
1212
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Http.Connections\Microsoft.AspNetCore.Http.Connections.csproj" />
1313
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Redis\Microsoft.AspNetCore.SignalR.Redis.csproj" />

src/Microsoft.AspNetCore.Http.Connections.Client/HttpConnection.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -391,12 +391,12 @@ private HttpClient CreateHttpClient()
391391
}
392392

393393
httpMessageHandler = httpClientHandler;
394-
if (_httpOptions.HttpMessageHandler != null)
394+
if (_httpOptions.HttpMessageHandlerFactory != null)
395395
{
396-
httpMessageHandler = _httpOptions.HttpMessageHandler(httpClientHandler);
396+
httpMessageHandler = _httpOptions.HttpMessageHandlerFactory(httpClientHandler);
397397
if (httpMessageHandler == null)
398398
{
399-
throw new InvalidOperationException("Configured HttpMessageHandler did not return a value.");
399+
throw new InvalidOperationException("Configured HttpMessageHandlerFactory did not return a value.");
400400
}
401401
}
402402
}

src/Microsoft.AspNetCore.Http.Connections.Client/HttpOptions.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ namespace Microsoft.AspNetCore.Http.Connections.Client
1313
public class HttpOptions
1414
{
1515
/// <summary>
16-
/// Gets or sets a delegate for wrapping or replacing the <see cref="HttpMessageHandler"/>
16+
/// Gets or sets a delegate for wrapping or replacing the <see cref="HttpMessageHandlerFactory"/>
1717
/// that will make HTTP requests the server.
1818
/// </summary>
19-
public Func<HttpMessageHandler, HttpMessageHandler> HttpMessageHandler { get; set; }
19+
public Func<HttpMessageHandler, HttpMessageHandler> HttpMessageHandlerFactory { get; set; }
2020

2121
public IReadOnlyCollection<KeyValuePair<string, string>> Headers { get; set; }
2222
public Func<string> AccessTokenFactory { get; set; }

src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnection.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
using Microsoft.AspNetCore.Connections.Features;
1515
using Microsoft.AspNetCore.SignalR.Internal;
1616
using Microsoft.AspNetCore.SignalR.Internal.Protocol;
17+
using Microsoft.Extensions.DependencyInjection;
1718
using Microsoft.Extensions.Logging;
1819
using Microsoft.Extensions.Logging.Abstractions;
1920

@@ -30,6 +31,7 @@ public partial class HubConnection
3031
private readonly ILoggerFactory _loggerFactory;
3132
private readonly ILogger _logger;
3233
private readonly IHubProtocol _protocol;
34+
private readonly IServiceProvider _serviceProvider;
3335
private readonly Func<IConnection> _connectionFactory;
3436
private readonly ConcurrentDictionary<string, List<InvocationHandler>> _handlers = new ConcurrentDictionary<string, List<InvocationHandler>>();
3537
private bool _disposed;
@@ -45,14 +47,11 @@ public partial class HubConnection
4547
/// </summary>
4648
public TimeSpan ServerTimeout { get; set; } = DefaultServerTimeout;
4749

48-
public HubConnection(Func<IConnection> connectionFactory, IHubProtocol protocol) : this(connectionFactory, protocol, NullLoggerFactory.Instance)
49-
{
50-
}
51-
52-
public HubConnection(Func<IConnection> connectionFactory, IHubProtocol protocol, ILoggerFactory loggerFactory)
50+
public HubConnection(Func<IConnection> connectionFactory, IHubProtocol protocol, IServiceProvider serviceProvider, ILoggerFactory loggerFactory)
5351
{
5452
_connectionFactory = connectionFactory ?? throw new ArgumentNullException(nameof(connectionFactory));
5553
_protocol = protocol ?? throw new ArgumentNullException(nameof(protocol));
54+
_serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
5655

5756
_loggerFactory = loggerFactory ?? NullLoggerFactory.Instance;
5857
_logger = _loggerFactory.CreateLogger<HubConnection>();
@@ -185,6 +184,7 @@ private async Task StopAsyncCore(bool disposing)
185184

186185
if (disposing)
187186
{
187+
(_serviceProvider as IDisposable)?.Dispose();
188188
_disposed = true;
189189
}
190190
}

src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnectionBuilder.cs

+28-25
Original file line numberDiff line numberDiff line change
@@ -2,72 +2,75 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
5-
using System.Collections.Generic;
65
using System.ComponentModel;
6+
using System.Linq;
77
using Microsoft.AspNetCore.Connections;
88
using Microsoft.AspNetCore.SignalR.Internal.Protocol;
9-
using Newtonsoft.Json;
9+
using Microsoft.Extensions.DependencyInjection;
10+
using Microsoft.Extensions.DependencyInjection.Extensions;
11+
using Microsoft.Extensions.Logging;
12+
using Microsoft.Extensions.Logging.Abstractions;
1013

1114
namespace Microsoft.AspNetCore.SignalR.Client
1215
{
1316
public class HubConnectionBuilder : IHubConnectionBuilder
1417
{
15-
private readonly Dictionary<KeyValuePair<string, Type>, object> _settings = new Dictionary<KeyValuePair<string, Type>, object>();
16-
private Func<IConnection> _connectionFactoryDelegate;
18+
private bool _hubConnectionBuilt;
1719

18-
public void ConfigureConnectionFactory(Func<IConnection> connectionFactoryDelegate) =>
19-
_connectionFactoryDelegate = connectionFactoryDelegate;
20+
public IServiceCollection Services { get; }
2021

21-
public void AddSetting<T>(string name, T value)
22+
public HubConnectionBuilder()
2223
{
23-
_settings[new KeyValuePair<string, Type>(name, typeof(T))] = value;
24+
Services = new ServiceCollection();
25+
Services.AddSingleton<ILoggerFactory>(NullLoggerFactory.Instance);
26+
Services.AddSingleton<IHubProtocol, JsonHubProtocol>();
27+
Services.AddSingleton<HubConnection>();
2428
}
2529

26-
public bool TryGetSetting<T>(string name, out T value)
30+
public HubConnection Build()
2731
{
28-
value = default;
29-
if (!_settings.TryGetValue(new KeyValuePair<string, Type>(name, typeof(T)), out var setting))
32+
// Build can only be used once
33+
if (_hubConnectionBuilt)
3034
{
31-
return false;
35+
throw new InvalidOperationException("HubConnectionBuilder allows creation only of a single instance of HubConnection.");
3236
}
3337

34-
value = (T)setting;
35-
return true;
36-
}
38+
_hubConnectionBuilt = true;
3739

38-
public HubConnection Build()
39-
{
40-
if (_connectionFactoryDelegate == null)
40+
// The service provider is disposed by the HubConnection
41+
var serviceProvider = Services.BuildServiceProvider();
42+
43+
var connectionFactory = serviceProvider.GetService<Func<IConnection>>();
44+
if (connectionFactory == null)
4145
{
42-
throw new InvalidOperationException("Cannot create IConnection instance. The connection factory was not configured.");
46+
throw new InvalidOperationException("Cannot create HubConnection instance. A connection was not configured.");
4347
}
4448

45-
IHubConnectionBuilder builder = this;
46-
47-
var loggerFactory = builder.GetLoggerFactory();
48-
var hubProtocol = builder.GetHubProtocol();
49-
50-
return new HubConnection(_connectionFactoryDelegate, hubProtocol ?? new JsonHubProtocol(), loggerFactory);
49+
return serviceProvider.GetService<HubConnection>();
5150
}
5251

52+
// Prevents from being displayed in intellisense
5353
[EditorBrowsable(EditorBrowsableState.Never)]
5454
public override int GetHashCode()
5555
{
5656
return base.GetHashCode();
5757
}
5858

59+
// Prevents from being displayed in intellisense
5960
[EditorBrowsable(EditorBrowsableState.Never)]
6061
public override bool Equals(object obj)
6162
{
6263
return base.Equals(obj);
6364
}
6465

66+
// Prevents from being displayed in intellisense
6567
[EditorBrowsable(EditorBrowsableState.Never)]
6668
public override string ToString()
6769
{
6870
return base.ToString();
6971
}
7072

73+
// Prevents from being displayed in intellisense
7174
[EditorBrowsable(EditorBrowsableState.Never)]
7275
public new Type GetType()
7376
{

src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnectionBuilderDefaults.cs

-11
This file was deleted.

0 commit comments

Comments
 (0)