Cleanup and shuffling things

- Moved the InvocationAdapterRegistry registration to SignalROptions
- Moved the JsonNetInvocationAdapter to Microsoft.AspNetCore.SignalR
- Remove dead JavaScript code
This commit is contained in:
David Fowler 2016-11-02 20:54:58 -07:00
parent 8dd61250f4
commit b6f15338eb
12 changed files with 73 additions and 218 deletions

View File

@ -1,32 +0,0 @@
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.DependencyInjection;
namespace ChatSample
{
public static class RpcExtensions
{
public static IApplicationBuilder UseRpc(this IApplicationBuilder app, Action<RpcBuilder> registerAdapters)
{
var adapters = app.ApplicationServices.GetRequiredService<InvocationAdapterRegistry>();
registerAdapters(new RpcBuilder(adapters));
return app;
}
}
public class RpcBuilder
{
private InvocationAdapterRegistry _invocationAdapters;
public RpcBuilder(InvocationAdapterRegistry invocationAdapters)
{
_invocationAdapters = invocationAdapters;
}
public void AddInvocationAdapter(string format, IInvocationAdapter adapter)
{
_invocationAdapters.RegisterInvocationAdapter(format, adapter);
}
}
}

View File

@ -1,7 +1,7 @@
using System; using ChatSample.Data;
using System.Collections.Generic; using ChatSample.Hubs;
using System.Linq; using ChatSample.Models;
using System.Threading.Tasks; using ChatSample.Services;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
@ -9,11 +9,6 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using ChatSample.Data;
using ChatSample.Models;
using ChatSample.Services;
using ChatSample.Hubs;
using ChatSample;
namespace ChatSample namespace ChatSample
{ {
@ -56,6 +51,7 @@ namespace ChatSample
services.AddTransient<ISmsSender, AuthMessageSender>(); services.AddTransient<ISmsSender, AuthMessageSender>();
services.AddSignalR(); services.AddSignalR();
services.AddAuthentication(); services.AddAuthentication();
} }
@ -84,12 +80,7 @@ namespace ChatSample
app.UseSignalR(routes => app.UseSignalR(routes =>
{ {
routes.MapHub<Chat>("/hubs"); routes.MapHub<Chat>("/chat");
});
app.UseRpc(invocationAdapters =>
{
invocationAdapters.AddInvocationAdapter("json", new JsonNetInvocationAdapter());
}); });
app.UseMvc(routes => app.UseMvc(routes =>

View File

@ -2,87 +2,10 @@
ViewData["Title"] = "Chat"; ViewData["Title"] = "Chat";
} }
@*<link rel="stylesheet" href="~/css/chat.css" />*@
<script src="~/js/signalr-client.js"></script> <script src="~/js/signalr-client.js"></script>
<script> <script>
function hubConnection(url) {
var ws = new WebSocket(url);
var id = 0;
var calls = {};
var methods = {};
ws.onopen = function () {
console.log('Opened!');
};
ws.onmessage = function (event) {
let response = {};
//if (document.getElementById('formatType').value == 'line') {
// let parts = event.data.split(',');
// if (event.data[0] == 'R') {
// response.Id = parts[0].slice(2);
// response.Result = parts[1].slice(1);
// }
// else if (event.data[0] == 'C') {
// response.Method = parts[1].slice(1);
// response.Arguments = parts.slice(2).join();
// }
// else {
// response.error = parts[0].slice(1);
// }
//}
//else {
response = JSON.parse(event.data);
//}
// Response
if (response.Id) {
var cb = calls[response.Id];
delete calls[response.Id];
if (response.Error) {
cb.error(response.Error);
}
else {
cb.success(response.Result);
}
}
else {
// Reverse JSON RPC
methods[response.Method](response.Arguments);
}
};
ws.onclose = function (event) {
console.log('Closed!');
};
this.invoke = function (method, args, formatType) {
return new Promise((resolve, reject) => {
calls[id] = { success: resolve, error: reject };
if (formatType == 'line') {
ws.send(`CI${id},M${method},${args.join()}\n`);
}
else {
ws.send(JSON.stringify({ method: method, arguments: args, id: id }));
}
id++;
});
};
this.on = function (method, fn) {
methods[method] = fn;
};
}
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
let connection = new RpcConnection(`http://${document.location.host}/hubs`, 'formatType=json&format=text'); let connection = new RpcConnection(`http://${document.location.host}/chat`, 'formatType=json&format=text');
connection.on('Send', function (message) { connection.on('Send', function (message) {
var child = document.createElement('li'); var child = document.createElement('li');

View File

@ -1,32 +0,0 @@
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.DependencyInjection;
namespace SocketsSample
{
public static class RpcExtensions
{
public static IApplicationBuilder UseRpc(this IApplicationBuilder app, Action<RpcBuilder> registerAdapters)
{
var adapters = app.ApplicationServices.GetRequiredService<InvocationAdapterRegistry>();
registerAdapters(new RpcBuilder(adapters));
return app;
}
}
public class RpcBuilder
{
private InvocationAdapterRegistry _invocationAdapters;
public RpcBuilder(InvocationAdapterRegistry invocationAdapters)
{
_invocationAdapters = invocationAdapters;
}
public void AddInvocationAdapter(string format, IInvocationAdapter adapter)
{
_invocationAdapters.RegisterInvocationAdapter(format, adapter);
}
}
}

View File

@ -1,42 +0,0 @@
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
using Newtonsoft.Json;
namespace SocketsSample
{
public class JsonNetInvocationAdapter : IInvocationAdapter
{
private JsonSerializer _serializer = new JsonSerializer();
public JsonNetInvocationAdapter()
{
}
public async Task<InvocationDescriptor> ReadInvocationDescriptor(Stream stream, Func<string, Type[]> getParams)
{
var reader = new JsonTextReader(new StreamReader(stream));
return await Task.Run(() => _serializer.Deserialize<InvocationDescriptor>(reader));
}
public Task WriteInvocationResult(InvocationResultDescriptor resultDescriptor, Stream stream)
{
Write(resultDescriptor, stream);
return Task.FromResult(0);
}
public Task WriteInvocationDescriptor(InvocationDescriptor invocationDescriptor, Stream stream)
{
Write(invocationDescriptor, stream);
return Task.FromResult(0);
}
private void Write(object value, Stream stream)
{
var writer = new JsonTextWriter(new StreamWriter(stream));
_serializer.Serialize(writer, value);
writer.Flush();
}
}
}

View File

@ -16,8 +16,16 @@ namespace SocketsSample
{ {
services.AddRouting(); services.AddRouting();
services.AddSignalR(); services.AddSingleton<ProtobufInvocationAdapter>();
// .AddRedis(); services.AddSingleton<LineInvocationAdapter>();
services.AddSignalR()
.AddSignalROptions(options =>
{
options.RegisterInvocationAdapter<ProtobufInvocationAdapter>("protobuf");
options.RegisterInvocationAdapter<LineInvocationAdapter>("line");
});
// .AddRedis();
services.AddSingleton<ChatEndPoint>(); services.AddSingleton<ChatEndPoint>();
services.AddSingleton<ProtobufSerializer>(); services.AddSingleton<ProtobufSerializer>();
@ -45,13 +53,6 @@ namespace SocketsSample
routes.MapSocketEndpoint<ChatEndPoint>("/chat"); routes.MapSocketEndpoint<ChatEndPoint>("/chat");
routes.MapSocketEndpoint<RpcEndpoint<Echo>>("/jsonrpc"); routes.MapSocketEndpoint<RpcEndpoint<Echo>>("/jsonrpc");
}); });
app.UseRpc(invocationAdapters =>
{
invocationAdapters.AddInvocationAdapter("protobuf", new ProtobufInvocationAdapter(app.ApplicationServices));
invocationAdapters.AddInvocationAdapter("json", new JsonNetInvocationAdapter());
invocationAdapters.AddInvocationAdapter("line", new LineInvocationAdapter());
});
} }
} }
} }

View File

@ -1,8 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Options;
namespace Microsoft.Extensions.DependencyInjection namespace Microsoft.Extensions.DependencyInjection
{ {
@ -14,9 +13,17 @@ namespace Microsoft.Extensions.DependencyInjection
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.AddSingleton(typeof(RpcEndpoint<>), typeof(RpcEndpoint<>)); services.AddSingleton(typeof(RpcEndpoint<>), typeof(RpcEndpoint<>));
services.AddSingleton<IConfigureOptions<SignalROptions>, SignalROptionsSetup>();
services.AddSingleton<JsonNetInvocationAdapter>();
services.AddSingleton<InvocationAdapterRegistry>(); services.AddSingleton<InvocationAdapterRegistry>();
return new SignalRBuilder(services); return new SignalRBuilder(services);
} }
public static ISignalRBuilder AddSignalROptions(this ISignalRBuilder builder, Action<SignalROptions> configure)
{
builder.Services.Configure(configure);
return builder;
}
} }
} }

View File

@ -1,22 +1,29 @@
using System; using System;
using System.Collections.Generic; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.SignalR namespace Microsoft.AspNetCore.SignalR
{ {
public class InvocationAdapterRegistry public class InvocationAdapterRegistry
{ {
private Dictionary<string, IInvocationAdapter> _invocationAdapters = new Dictionary<string, IInvocationAdapter>(); private readonly IServiceProvider _serviceProvider;
private readonly SignalROptions _options;
public void RegisterInvocationAdapter(string format, IInvocationAdapter adapter) public InvocationAdapterRegistry(IOptions<SignalROptions> options, IServiceProvider serviceProvider)
{ {
_invocationAdapters[format] = adapter; _options = options.Value;
_serviceProvider = serviceProvider;
} }
public IInvocationAdapter GetInvocationAdapter(string format) public IInvocationAdapter GetInvocationAdapter(string format)
{ {
IInvocationAdapter value; Type type;
if (_options._invocationMappings.TryGetValue(format, out type))
{
return _serviceProvider.GetRequiredService(type) as IInvocationAdapter;
}
return _invocationAdapters.TryGetValue(format, out value) ? value : null; return null;
} }
} }
} }

View File

@ -1,10 +1,9 @@
using System; using System;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace ChatSample namespace Microsoft.AspNetCore.SignalR
{ {
public class JsonNetInvocationAdapter : IInvocationAdapter public class JsonNetInvocationAdapter : IInvocationAdapter
{ {
@ -17,6 +16,7 @@ namespace ChatSample
public async Task<InvocationDescriptor> ReadInvocationDescriptor(Stream stream, Func<string, Type[]> getParams) public async Task<InvocationDescriptor> ReadInvocationDescriptor(Stream stream, Func<string, Type[]> getParams)
{ {
var reader = new JsonTextReader(new StreamReader(stream)); var reader = new JsonTextReader(new StreamReader(stream));
// REVIEW: Task.Run()
return await Task.Run(() => _serializer.Deserialize<InvocationDescriptor>(reader)); return await Task.Run(() => _serializer.Deserialize<InvocationDescriptor>(reader));
} }

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.AspNetCore.SignalR
{
public class SignalROptions
{
internal readonly Dictionary<string, Type> _invocationMappings = new Dictionary<string, Type>();
public void RegisterInvocationAdapter<TInvocationAdapter>(string format) where TInvocationAdapter : IInvocationAdapter
{
_invocationMappings[format] = typeof(TInvocationAdapter);
}
}
}

View File

@ -0,0 +1,14 @@
using System;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Options;
namespace Microsoft.Extensions.DependencyInjection
{
public class SignalROptionsSetup : IConfigureOptions<SignalROptions>
{
public void Configure(SignalROptions options)
{
options.RegisterInvocationAdapter<JsonNetInvocationAdapter>("json");
}
}
}

View File

@ -2,6 +2,7 @@
"version": "1.0.0-*", "version": "1.0.0-*",
"dependencies": { "dependencies": {
"Newtonsoft.Json": "9.0.1",
"Microsoft.AspNetCore.Sockets": { "Microsoft.AspNetCore.Sockets": {
"target": "project" "target": "project"
} }