/// <summary> /// This dispatches messages synchronously in the client, as we want to ensure that each message is processed in order, and without collision. /// </summary> /// <param name="message"> </param> /// <returns> </returns> public bool DispatchSynchronous(UrlEncodedMessage message) { return(_methodTargets[message.Command].With(method => { try { method.MethodInfo.Invoke(_targetObject, method.Parameters.Keys.Select(each => message.GetValue(each, method.Parameters[each].Type)).ToArray()); } catch (TargetInvocationException exception) { if (exception.InnerException != null) { if (exception.InnerException is RestartingException) { #if TODO Logger.Message("Client recieved restarting message"); #endif return false; } throw exception.InnerException; } } catch (AggregateException exception) { var c = exception.Unwrap(); #if TODO Logger.Error(c); #endif throw c; } catch (Exception exception) { #if TODO Logger.Error(exception); #endif throw exception; } return !(message.Command.Equals("TaskComplete") || message.Command.Equals("OperationCanceled")); }, () => { throw new MissingMethodException("Method '{0}' does not exist in this interface", message.Command); })); }
/// <summary> /// On the server side, we process messages asynchronously, as we want to make them as parallel as possible. /// </summary> /// <param name="message"> </param> /// <returns> </returns> public Task Dispatch(UrlEncodedMessage message) { return(_methodTargets[message.Command].With(method => Task.Factory.StartNew(() => { try { method.MethodInfo.Invoke(_targetObject, method.Parameters.Keys.Select(each => message.GetValue(each, method.Parameters[each].Type)).ToArray()); } catch (Exception e) { #if TODO Logger.Error(e); #endif } }, TaskCreationOptions.AttachedToParent), () => { throw new MissingMethodException("Method '{0}' does not exist in this interface", message.Command); })); }
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) { var msg = new UrlEncodedMessage(binder.Name); var method = _methodTargets[binder.Name]; for (int i = 0; i < binder.CallInfo.ArgumentCount; i++) { if (args[i] != null) { // var targetType = method.Parameters[binder.CallInfo.ArgumentNames[i]].Type; // var sourceType = args[i].GetType(); msg.Add(binder.CallInfo.ArgumentNames[i], args[i], args[i].GetType()); } } _writeAsync(msg); // our incoming calls appear as return type 'Task' in the interface // but that's just so that the client app can treat the interface as async easily. // on the servicing side, we just return null, and don't actually expect that the // call has a significant return value. result = null; return(true); }
internal abstract object DeserializeObject(UrlEncodedMessage msg, string key);
internal abstract void SerializeObject(UrlEncodedMessage msg, string key, object obj);
public Object CreateObject(UrlEncodedMessage message, string key, Type targetType) { var instantiator = _instantiators[targetType]; return(instantiator != null?instantiator(message, key, targetType) : CreateInstance(targetType)); }