public T GetRpcInterface <T>() where T : class { ClientData clientData; if (_clientsData.TryGetValue(typeof(T), out clientData)) { return((T)clientData.Proxy); } var type = typeof(T); if (type.HasAttribute <RpcInterface>()) { var newClientData = new ClientData() { InterfaceOrdinal = type.GetAttribute <RpcInterface>().Ordinal, InterfaceMethods = RpcInterface.GetOrderedMethods(type), }; newClientData.Proxy = RpcInterface.CreateDynamicProxy <T>(this, newClientData); _clientsData[typeof(T)] = newClientData; return((T)newClientData.Proxy); } throw new NotSupportedException(type.Name + " does not have the RPCInterface attribute"); }
public void RegisterRpcHandler(object handler) { Type handlerType = handler.GetType(); bool handlerRegistered = false; foreach (var intType in handlerType.GetInterfaces()) { if (intType.HasAttribute <RpcInterface>()) { var iface = intType.GetAttribute <RpcInterface>(); HandlerData existingHandler; if (_handlersData.TryGetValue(iface.Ordinal, out existingHandler)) { RemoveRpcHandler(handler); throw new ArgumentException("Handler with type " + handler.GetType() + " implements " + iface.GetType() + " which is already handled by " + existingHandler.Handler.GetType()); } _handlersData[iface.Ordinal] = new HandlerData { RpcInterfaceType = intType, Handler = handler, InterfaceMethods = RpcInterface.GetOrderedMethods(intType), }; handlerRegistered = true; } } if (!handlerRegistered) { throw new ArgumentException("Handler with type " + handler.GetType() + " does not implement any RPC interface."); } }
private void ProcessHandlerCall(BinaryReader reader, byte ifaceOrdinal, object context) { HandlerData handlerData; if (!_handlersData.TryGetValue(ifaceOrdinal, out handlerData)) { Type ifaceType = RpcInterface.GetRpcInterface(ifaceOrdinal); if (ifaceType == null) { throw new ProtocolViolationException("Unknown RPC interface ordinal received: " + ifaceOrdinal); } MethodInfo mi = RpcInterface.GetOrderedMethods(ifaceType)[reader.ReadByte()].MethodInfo; throw new ProtocolViolationException("RPC call received for " + ifaceType.FullName + "." + mi.Name + " which does not have a handler registered."); } byte methodOrdinal = reader.ReadByte(); RpcMethodInfo rpcMethodInfo = handlerData.InterfaceMethods[methodOrdinal]; MethodInfo methodInfo = rpcMethodInfo.MethodInfo; byte callId = 0; if (rpcMethodInfo.HasReturnType) { callId = reader.ReadByte(); } var paramsInfo = methodInfo.GetParameters(); var paramValues = new object[paramsInfo.Length]; for (int i = 0, n = paramValues.Length; i < n; ++i) { paramValues[i] = BinarySerializer.DeserializeParameter(reader, paramsInfo[i]); } var callContext = new HandlerCallContext { HandlerType = handlerData.RpcInterfaceType, Handler = handlerData.Handler, Method = methodInfo, CallId = callId, Context = context, }; if (OnBeforeHandlerCall != null) { OnBeforeHandlerCall(callContext); } callContext.Result = methodInfo.Invoke(handlerData.Handler, paramValues); if (callContext.Result != null && OnDataOut != null) { Type resultFutureType = callContext.Result.GetType(); var stream = new MemoryStream(64); var writer = new BinaryWriter(stream); var header = (byte)(ResponseTypeFlag | callId); writer.Write((byte)header); resultFutureType.GetMethod("Serialize", BindingFlags.NonPublic | BindingFlags.Instance) .Invoke(callContext.Result, new object[] { writer }); OnDataOut(stream.ToArray(), 0, (int)stream.Length); } if (OnAfterHandlerCall != null) { OnAfterHandlerCall(callContext); } }