Dynamic Hub Work Part 1 (#636)

Getting rid of TClient
This commit is contained in:
Mikael Mengistu 2017-07-05 22:55:16 -07:00 committed by GitHub
parent ed6badbabe
commit cfaa4b69d7
15 changed files with 41 additions and 75 deletions

View File

@ -7,18 +7,11 @@ using Microsoft.AspNetCore.SignalR;
namespace ChatSample namespace ChatSample
{ {
public class HubWithPresence : HubWithPresence<IClientProxy> public class HubWithPresence : Hub
{ {
private IUserTracker<HubWithPresence> _userTracker;
public HubWithPresence(IUserTracker<HubWithPresence> userTracker) public HubWithPresence(IUserTracker<HubWithPresence> userTracker)
: base(userTracker)
{ }
}
public class HubWithPresence<TClient> : Hub<TClient>
{
private IUserTracker<HubWithPresence<TClient>> _userTracker;
public HubWithPresence(IUserTracker<HubWithPresence<TClient>> userTracker)
{ {
_userTracker = userTracker; _userTracker = userTracker;
} }

View File

@ -102,7 +102,7 @@ namespace ChatSample
{ {
using (var scope = _serviceScopeFactory.CreateScope()) using (var scope = _serviceScopeFactory.CreateScope())
{ {
var hubActivator = scope.ServiceProvider.GetRequiredService<IHubActivator<THub, IClientProxy>>(); var hubActivator = scope.ServiceProvider.GetRequiredService<IHubActivator<THub>>();
var hub = hubActivator.Create(); var hub = hubActivator.Create();
if (_hubContext == null) if (_hubContext == null)

View File

@ -17,12 +17,12 @@ namespace Microsoft.AspNetCore.SignalR
_routes = routes; _routes = routes;
} }
public void MapHub<THub>(string path) where THub : Hub<IClientProxy> public void MapHub<THub>(string path) where THub : Hub
{ {
MapHub<THub>(path, socketOptions: null); MapHub<THub>(path, socketOptions: null);
} }
public void MapHub<THub>(string path, Action<HttpSocketOptions> socketOptions) where THub : Hub<IClientProxy> public void MapHub<THub>(string path, Action<HttpSocketOptions> socketOptions) where THub : Hub
{ {
// find auth attributes // find auth attributes
var authorizeAttributes = typeof(THub).GetCustomAttributes<AuthorizeAttribute>(inherit: true); var authorizeAttributes = typeof(THub).GetCustomAttributes<AuthorizeAttribute>(inherit: true);

View File

@ -7,8 +7,7 @@ using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.SignalR namespace Microsoft.AspNetCore.SignalR
{ {
public class DefaultHubActivator<THub, TClient> : IHubActivator<THub, TClient> public class DefaultHubActivator<THub> : IHubActivator<THub> where THub: Hub
where THub: Hub<TClient>
{ {
private readonly IServiceProvider _serviceProvider; private readonly IServiceProvider _serviceProvider;
private bool? _created; private bool? _created;

View File

@ -6,18 +6,14 @@ using System.Threading.Tasks;
namespace Microsoft.AspNetCore.SignalR namespace Microsoft.AspNetCore.SignalR
{ {
public class Hub : Hub<IClientProxy> public class Hub : IDisposable
{
}
public class Hub<TClient> : IDisposable
{ {
private bool _disposed; private bool _disposed;
private IHubConnectionContext<TClient> _clients; private IHubClients _clients;
private HubCallerContext _context; private HubCallerContext _context;
private IGroupManager _groups; private IGroupManager _groups;
public IHubConnectionContext<TClient> Clients public IHubClients Clients
{ {
get get
{ {

View File

@ -1,14 +1,9 @@
// Copyright (c) .NET Foundation. All rights reserved. // Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.AspNetCore.SignalR namespace Microsoft.AspNetCore.SignalR
{ {
public class HubContext<THub> : IHubContext<THub>, IHubConnectionContext<IClientProxy> public class HubContext<THub> : IHubContext<THub>, IHubClients where THub : Hub
{ {
private readonly HubLifetimeManager<THub> _lifetimeManager; private readonly HubLifetimeManager<THub> _lifetimeManager;
private readonly AllClientProxy<THub> _all; private readonly AllClientProxy<THub> _all;
@ -19,7 +14,7 @@ namespace Microsoft.AspNetCore.SignalR
_all = new AllClientProxy<THub>(_lifetimeManager); _all = new AllClientProxy<THub>(_lifetimeManager);
} }
public IHubConnectionContext<IClientProxy> Clients => this; public IHubClients Clients => this;
public virtual IClientProxy All => _all; public virtual IClientProxy All => _all;

View File

@ -20,32 +20,20 @@ using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.SignalR namespace Microsoft.AspNetCore.SignalR
{ {
public class HubEndPoint<THub> : HubEndPoint<THub, IClientProxy> where THub : Hub<IClientProxy> public class HubEndPoint<THub> : IInvocationBinder where THub : Hub
{
public HubEndPoint(HubLifetimeManager<THub> lifetimeManager,
IHubProtocolResolver protocolResolver,
IHubContext<THub> hubContext,
ILogger<HubEndPoint<THub>> logger,
IServiceScopeFactory serviceScopeFactory)
: base(lifetimeManager, protocolResolver, hubContext, logger, serviceScopeFactory)
{
}
}
public class HubEndPoint<THub, TClient> : IInvocationBinder where THub : Hub<TClient>
{ {
private readonly Dictionary<string, HubMethodDescriptor> _methods = new Dictionary<string, HubMethodDescriptor>(StringComparer.OrdinalIgnoreCase); private readonly Dictionary<string, HubMethodDescriptor> _methods = new Dictionary<string, HubMethodDescriptor>(StringComparer.OrdinalIgnoreCase);
private readonly HubLifetimeManager<THub> _lifetimeManager; private readonly HubLifetimeManager<THub> _lifetimeManager;
private readonly IHubContext<THub, TClient> _hubContext; private readonly IHubContext<THub> _hubContext;
private readonly ILogger<HubEndPoint<THub, TClient>> _logger; private readonly ILogger<HubEndPoint<THub>> _logger;
private readonly IServiceScopeFactory _serviceScopeFactory; private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly IHubProtocolResolver _protocolResolver; private readonly IHubProtocolResolver _protocolResolver;
public HubEndPoint(HubLifetimeManager<THub> lifetimeManager, public HubEndPoint(HubLifetimeManager<THub> lifetimeManager,
IHubProtocolResolver protocolResolver, IHubProtocolResolver protocolResolver,
IHubContext<THub, TClient> hubContext, IHubContext<THub> hubContext,
ILogger<HubEndPoint<THub, TClient>> logger, ILogger<HubEndPoint<THub>> logger,
IServiceScopeFactory serviceScopeFactory) IServiceScopeFactory serviceScopeFactory)
{ {
_protocolResolver = protocolResolver; _protocolResolver = protocolResolver;
@ -146,7 +134,7 @@ namespace Microsoft.AspNetCore.SignalR
{ {
using (var scope = _serviceScopeFactory.CreateScope()) using (var scope = _serviceScopeFactory.CreateScope())
{ {
var hubActivator = scope.ServiceProvider.GetRequiredService<IHubActivator<THub, TClient>>(); var hubActivator = scope.ServiceProvider.GetRequiredService<IHubActivator<THub>>();
var hub = hubActivator.Create(); var hub = hubActivator.Create();
try try
{ {
@ -172,7 +160,7 @@ namespace Microsoft.AspNetCore.SignalR
{ {
using (var scope = _serviceScopeFactory.CreateScope()) using (var scope = _serviceScopeFactory.CreateScope())
{ {
var hubActivator = scope.ServiceProvider.GetRequiredService<IHubActivator<THub, TClient>>(); var hubActivator = scope.ServiceProvider.GetRequiredService<IHubActivator<THub>>();
var hub = hubActivator.Create(); var hub = hubActivator.Create();
try try
{ {
@ -311,7 +299,7 @@ namespace Microsoft.AspNetCore.SignalR
return; return;
} }
var hubActivator = scope.ServiceProvider.GetRequiredService<IHubActivator<THub, TClient>>(); var hubActivator = scope.ServiceProvider.GetRequiredService<IHubActivator<THub>>();
var hub = hubActivator.Create(); var hub = hubActivator.Create();
try try

View File

@ -5,7 +5,7 @@ using System;
namespace Microsoft.AspNetCore.SignalR namespace Microsoft.AspNetCore.SignalR
{ {
public interface IHubActivator<THub, TClient> where THub : Hub<TClient> public interface IHubActivator<THub> where THub : Hub
{ {
THub Create(); THub Create();
void Release(THub hub); void Release(THub hub);

View File

@ -3,14 +3,14 @@
namespace Microsoft.AspNetCore.SignalR namespace Microsoft.AspNetCore.SignalR
{ {
public interface IHubConnectionContext<TClient> public interface IHubClients
{ {
TClient All { get; } IClientProxy All { get; }
TClient Client(string connectionId); IClientProxy Client(string connectionId);
TClient Group(string groupName); IClientProxy Group(string groupName);
TClient User(string userId); IClientProxy User(string userId);
} }
} }

View File

@ -8,12 +8,8 @@ using System.Threading.Tasks;
namespace Microsoft.AspNetCore.SignalR namespace Microsoft.AspNetCore.SignalR
{ {
public interface IHubContext<THub, TClient> public interface IHubContext<THub> where THub: Hub
{
IHubConnectionContext<TClient> Clients { get; }
}
public interface IHubContext<THub> : IHubContext<THub, IClientProxy>
{ {
IHubClients Clients { get; }
} }
} }

View File

@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.SignalR.Internal
{ {
public static class HubReflectionHelper public static class HubReflectionHelper
{ {
private static readonly Type[] _excludeInterfaces = new[] { typeof(Hub<>), typeof(IDisposable) }; private static readonly Type[] _excludeInterfaces = new[] { typeof(IDisposable) };
public static IEnumerable<MethodInfo> GetHubMethods(Type hubType) public static IEnumerable<MethodInfo> GetHubMethods(Type hubType)
{ {
@ -38,9 +38,8 @@ namespace Microsoft.AspNetCore.SignalR.Internal
return false; return false;
} }
// removes methods such as Hub<TClient>.OnConnectedAsync
var baseType = baseDefinition.GetTypeInfo().IsGenericType ? baseDefinition.GetGenericTypeDefinition() : baseDefinition; var baseType = baseDefinition.GetTypeInfo().IsGenericType ? baseDefinition.GetGenericTypeDefinition() : baseDefinition;
return typeof(Hub<>) != baseType; return typeof(Hub) != baseType;
} }
} }
} }

View File

@ -14,7 +14,7 @@ namespace Microsoft.Extensions.DependencyInjection
services.AddSingleton(typeof(IHubProtocolResolver), typeof(DefaultHubProtocolResolver)); services.AddSingleton(typeof(IHubProtocolResolver), typeof(DefaultHubProtocolResolver));
services.AddSingleton(typeof(IHubContext<>), typeof(HubContext<>)); services.AddSingleton(typeof(IHubContext<>), typeof(HubContext<>));
services.AddSingleton(typeof(HubEndPoint<>), typeof(HubEndPoint<>)); services.AddSingleton(typeof(HubEndPoint<>), typeof(HubEndPoint<>));
services.AddScoped(typeof(IHubActivator<,>), typeof(DefaultHubActivator<,>)); services.AddScoped(typeof(IHubActivator<>), typeof(DefaultHubActivator<>));
services.AddAuthorization(); services.AddAuthorization();

View File

@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.SignalR
{ {
public static class SignalRSocketBuilderExtensions public static class SignalRSocketBuilderExtensions
{ {
public static ISocketBuilder UseHub<THub>(this ISocketBuilder socketBuilder) where THub : Hub<IClientProxy> public static ISocketBuilder UseHub<THub>(this ISocketBuilder socketBuilder) where THub : Hub
{ {
var endpoint = socketBuilder.ApplicationServices.GetRequiredService<HubEndPoint<THub>>(); var endpoint = socketBuilder.ApplicationServices.GetRequiredService<HubEndPoint<THub>>();
return socketBuilder.Run(connection => endpoint.OnConnectedAsync(connection)); return socketBuilder.Run(connection => endpoint.OnConnectedAsync(connection));

View File

@ -14,20 +14,20 @@ namespace Microsoft.AspNetCore.SignalR.Tests
public void HubCreatedIfNotResolvedFromServiceProvider() public void HubCreatedIfNotResolvedFromServiceProvider()
{ {
Assert.NotNull( Assert.NotNull(
new DefaultHubActivator<Hub<object>, object>(Mock.Of<IServiceProvider>()).Create()); new DefaultHubActivator<Hub>(Mock.Of<IServiceProvider>()).Create());
} }
[Fact] [Fact]
public void HubCanBeResolvedFromServiceProvider() public void HubCanBeResolvedFromServiceProvider()
{ {
var hub = Mock.Of<Hub<object>>(); var hub = Mock.Of<Hub>();
var mockServiceProvider = new Mock<IServiceProvider>(); var mockServiceProvider = new Mock<IServiceProvider>();
mockServiceProvider mockServiceProvider
.Setup(sp => sp.GetService(typeof(Hub<object>))) .Setup(sp => sp.GetService(typeof(Hub)))
.Returns(hub); .Returns(hub);
Assert.Same(hub, Assert.Same(hub,
new DefaultHubActivator<Hub<object>, object>(mockServiceProvider.Object).Create()); new DefaultHubActivator<Hub>(mockServiceProvider.Object).Create());
} }
@ -36,15 +36,15 @@ namespace Microsoft.AspNetCore.SignalR.Tests
{ {
var mockServiceProvider = new Mock<IServiceProvider>(); var mockServiceProvider = new Mock<IServiceProvider>();
mockServiceProvider mockServiceProvider
.Setup(sp => sp.GetService(typeof(Hub<object>))) .Setup(sp => sp.GetService(typeof(Hub)))
.Returns(() => .Returns(() =>
{ {
var m = new Mock<Hub<object>>(); var m = new Mock<Hub>();
m.Protected().Setup("Dispose", ItExpr.IsAny<bool>()); m.Protected().Setup("Dispose", ItExpr.IsAny<bool>());
return m.Object; return m.Object;
}); });
var hubActivator = new DefaultHubActivator<Hub<object>, object>(mockServiceProvider.Object); var hubActivator = new DefaultHubActivator<Hub>(mockServiceProvider.Object);
var hub = hubActivator.Create(); var hub = hubActivator.Create();
hubActivator.Release(hub); hubActivator.Release(hub);
Mock.Get(hub).Protected().Verify("Dispose", Times.Never(), ItExpr.IsAny<bool>()); Mock.Get(hub).Protected().Verify("Dispose", Times.Never(), ItExpr.IsAny<bool>());
@ -55,7 +55,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests
{ {
Assert.Equal("hub", Assert.Equal("hub",
Assert.Throws<ArgumentNullException>( Assert.Throws<ArgumentNullException>(
() => new DefaultHubActivator<Hub<object>, object>(Mock.Of<IServiceProvider>()).Release(null)).ParamName); () => new DefaultHubActivator<Hub>(Mock.Of<IServiceProvider>()).Release(null)).ParamName);
} }
} }
} }

View File

@ -45,7 +45,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests
mockLifetimeManager mockLifetimeManager
.Setup(m => m.OnConnectedAsync(It.IsAny<HubConnectionContext>())) .Setup(m => m.OnConnectedAsync(It.IsAny<HubConnectionContext>()))
.Throws(new InvalidOperationException("Lifetime manager OnConnectedAsync failed.")); .Throws(new InvalidOperationException("Lifetime manager OnConnectedAsync failed."));
var mockHubActivator = new Mock<IHubActivator<Hub, IClientProxy>>(); var mockHubActivator = new Mock<IHubActivator<Hub>>();
var serviceProvider = CreateServiceProvider(services => var serviceProvider = CreateServiceProvider(services =>
{ {