-
Notifications
You must be signed in to change notification settings - Fork 105
/
Copy pathHandlerCollection.cs
110 lines (89 loc) · 5.08 KB
/
HandlerCollection.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reactive.Disposables;
using System.Reflection;
using MediatR;
using Microsoft.Extensions.DependencyInjection;
namespace OmniSharp.Extensions.JsonRpc
{
internal class HandlerCollection : IHandlersManager, IEnumerable<IHandlerDescriptor>
{
private readonly IServiceProvider _serviceProvider;
private readonly IHandlerTypeDescriptorProvider<IHandlerTypeDescriptor> _handlerTypeDescriptorProvider;
private ImmutableArray<IHandlerDescriptor> _descriptors = ImmutableArray<IHandlerDescriptor>.Empty;
public IEnumerable<IHandlerDescriptor> Descriptors => _descriptors;
public HandlerCollection(IServiceProvider serviceProvider, IHandlerTypeDescriptorProvider<IHandlerTypeDescriptor> handlerTypeDescriptorProvider)
{
_serviceProvider = serviceProvider;
_handlerTypeDescriptorProvider = handlerTypeDescriptorProvider;
}
private void Remove(IJsonRpcHandler handler)
{
var descriptors = _descriptors.ToBuilder();
foreach (var item in _descriptors.Where(instance => instance.Handler == handler))
{
descriptors.Remove(item);
}
ImmutableInterlocked.InterlockedExchange(ref _descriptors, descriptors.ToImmutableArray());
}
public IDisposable Add(params IJsonRpcHandler[] handlers)
{
var cd = new CompositeDisposable();
foreach (var handler in handlers)
{
if (_descriptors.Any(z => z.Handler == handler)) continue;
cd.Add(Add(_handlerTypeDescriptorProvider.GetMethodName(handler.GetType()), handler, null));
}
return cd;
}
public IDisposable Add(IJsonRpcHandler handler, JsonRpcHandlerOptions options) => Add(_handlerTypeDescriptorProvider.GetMethodName(handler.GetType()), handler, options);
public IDisposable Add(string method, IJsonRpcHandler handler, JsonRpcHandlerOptions options)
{
var type = handler.GetType();
var @interface = HandlerTypeDescriptorHelper.GetHandlerInterface(type);
Type @params = null;
Type response = null;
if (@interface.GetTypeInfo().IsGenericType)
{
@params = @interface.GetTypeInfo().GetGenericArguments()[0];
var requestInterface = @params.GetInterfaces()
.FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IRequest<>));
if (requestInterface != null)
{
response = requestInterface.GetGenericArguments()[0];
}
}
var requestProcessType =
options?.RequestProcessType ??
_handlerTypeDescriptorProvider.GetHandlerTypeDescriptor(type)?.RequestProcessType ??
type.GetCustomAttributes(true)
.Concat(@interface.GetCustomAttributes(true))
.OfType<ProcessAttribute>()
.FirstOrDefault()?.Type;
var descriptor = new HandlerInstance(method, handler, @interface, @params, response, requestProcessType, () => Remove(handler));
ImmutableInterlocked.InterlockedExchange(ref _descriptors, _descriptors.Add(descriptor));
return descriptor;
}
public IDisposable Add(JsonRpcHandlerFactory factory, JsonRpcHandlerOptions options) => Add(factory(_serviceProvider), options);
public IDisposable Add(string method, JsonRpcHandlerFactory factory, JsonRpcHandlerOptions options) => Add(method, factory(_serviceProvider), options);
public IDisposable Add(Type handlerType, JsonRpcHandlerOptions options) =>
Add(ActivatorUtilities.CreateInstance(_serviceProvider, handlerType) as IJsonRpcHandler, options);
public IDisposable Add(string method, Type handlerType, JsonRpcHandlerOptions options) => Add(
method, ActivatorUtilities.CreateInstance(_serviceProvider, handlerType) as IJsonRpcHandler, options
);
public IDisposable AddLink(string sourceMethod, string destinationMethod)
{
var source = _descriptors.FirstOrDefault(z => z.Method == sourceMethod);
var descriptor = new LinkedHandler(destinationMethod, source, () => _descriptors.RemoveAll(z => z.Method == destinationMethod));
ImmutableInterlocked.InterlockedExchange(ref _descriptors, _descriptors.Add(descriptor));
return descriptor;
}
public bool ContainsHandler(Type type) => _descriptors.Any(z => type.IsAssignableFrom(z.HandlerType));
public bool ContainsHandler(TypeInfo type) => _descriptors.Any(z => type.IsAssignableFrom(z.HandlerType));
public IEnumerator<IHandlerDescriptor> GetEnumerator() => ( (IEnumerable<IHandlerDescriptor>) _descriptors ).GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => ( (IEnumerable) _descriptors ).GetEnumerator();
}
}