Skip to content

Instantly share code, notes, and snippets.

@Rene-Sackers
Created February 3, 2018 14:46
Show Gist options
  • Save Rene-Sackers/3df309916ab2ed55d8ffe879cbc3aea6 to your computer and use it in GitHub Desktop.
Save Rene-Sackers/3df309916ab2ed55d8ffe879cbc3aea6 to your computer and use it in GitHub Desktop.
[Serializable]
public class TypedHubClientInterceptor : IInterceptor
{
public delegate void MethodCalledHandler(MethodInfo methodInfo, params object[] args);
public void Intercept(IInvocation invocation) =>
MethodCalled?.Invoke(invocation.Method, invocation.Arguments);
public event MethodCalledHandler MethodCalled;
}
public class TypedHubClient<TClient> where TClient : class
{
private readonly HubConnection _hubConnection;
private readonly TClient _onHandlerClient;
private readonly Dictionary<string, Tuple<MethodInfo, object>> _onHandlers = new Dictionary<string, Tuple<MethodInfo, object>>();
private TaskCompletionSource<string> _getOnHookMethodName;
public TClient Client { get; }
public TypedHubClient(HubConnection hubConnection)
{
_hubConnection = hubConnection;
var proxyGenerator = new ProxyGenerator();
var proxyInterceptor = new TypedHubClientInterceptor();
var onHookProxyInterceptor = new TypedHubClientInterceptor();
proxyInterceptor.MethodCalled += ProxyInterceptorOnMethodCalled;
onHookProxyInterceptor.MethodCalled += OnHookProxyInterceptorOnMethodCalled;
Client = proxyGenerator.CreateInterfaceProxyWithoutTarget<TClient>(proxyInterceptor);
_onHandlerClient = proxyGenerator.CreateInterfaceProxyWithoutTarget<TClient>(onHookProxyInterceptor);
}
private void ProxyInterceptorOnMethodCalled(MethodInfo methodInfo, params object[] args) =>
_hubConnection.InvokeAsync(methodInfo.Name, args);
private void OnHookProxyInterceptorOnMethodCalled(MethodInfo methodInfo, params object[] args)
{
_getOnHookMethodName?.TrySetResult(methodInfo.Name);
_hubConnection.On(
methodInfo.Name,
methodInfo.GetParameters().Select(p => p.ParameterType).ToArray(),
objects => HandleHubConnectionClientOnEvent(methodInfo.Name, objects)
);
}
private Task HandleHubConnectionClientOnEvent(string methodName, object[] args)
{
if (!_onHandlers.ContainsKey(methodName))
return Task.CompletedTask;
var methodHandling = _onHandlers[methodName];
return (Task)methodHandling.Item1.Invoke(methodHandling.Item2, args);
}
public async Task On(Action<TClient> clientAction, Func<object[], Task> handler, object handlerInstance)
{
_getOnHookMethodName = new TaskCompletionSource<string>();
clientAction(_onHandlerClient);
var methodName = await _getOnHookMethodName.Task;
_onHandlers.Add(methodName, new Tuple<MethodInfo, object>(handler.Method, handlerInstance));
}
public async Task On<T1>(Action<TClient> clientAction, Func<T1, Task> handler, object handlerInstance)
{
_getOnHookMethodName = new TaskCompletionSource<string>();
clientAction(_onHandlerClient);
var methodName = await _getOnHookMethodName.Task;
_onHandlers.Add(methodName, new Tuple<MethodInfo, object>(handler.Method, handlerInstance));
}
public async Task On<T1, T2>(Action<TClient> clientAction, Func<T1, T2, Task> handler)
{
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment