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."); } }
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 MessageInfo AnalyzeMessage(byte[] data, int offset, int length) { var reader = new BinaryReader(new MemoryStream(data, offset, length)); byte header = reader.ReadByte(); if ((header & ResponseTypeFlag) == 0) { byte ifaceOrdinal = header; byte methodOrdinal = reader.ReadByte(); HandlerData handlerData = _handlersData[ifaceOrdinal]; RpcMethodInfo rpcMethodInfo = handlerData.InterfaceMethods[methodOrdinal]; return(new MessageInfo { Type = MessageType.HandlerCall, InterfaceType = RpcInterface.GetRpcInterface(ifaceOrdinal), InterfaceMethodInfo = rpcMethodInfo.MethodInfo, Handler = handlerData.Handler, }); } return(new MessageInfo { Type = MessageType.CallResult, }); }
public static void Serialize <T>(BinaryWriter writer, Type type, bool nullable, T value) { if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(System.Nullable <>)) { Type underlyingType = type.GetGenericArguments()[0]; Serialize(writer, underlyingType, true, value); return; } if (nullable) { if (value == null) { writer.Write((byte)0); return; } writer.Write((byte)1); } else if (value == null) { throw new SerializationException("Trying to serialize a non Nullable null value"); } Action <BinaryWriter, object, bool> serializerFunc; if (WriteFunctions.TryGetValue(type, out serializerFunc)) { serializerFunc(writer, value, nullable); return; } if (type.IsEnum) { Type underlyingType = Enum.GetUnderlyingType(type); if (WriteFunctions.TryGetValue(underlyingType, out serializerFunc)) { serializerFunc(writer, Convert.ChangeType(value, underlyingType), nullable); } else { throw new SerializationException("Enum " + type.Name + " underlying type is not serializable."); } return; } SerializableTypeInfo serTypeInfo = SerializableTypeCache[type]; if (serTypeInfo != null) { if (serTypeInfo.SerializeMethod.IsStatic) { serTypeInfo.SerializeMethod.Invoke(null, new object[] { value, writer }); } else { serTypeInfo.SerializeMethod.Invoke(value, new object[] { writer }); } return; } Type elementType = GetListElementType(type); if (elementType != null) { Action <BinaryWriter, object, bool> writeFunc = (wrtr, vlue, nlble) => { wrtr.Write(checked ((ushort)((ICollection)vlue).Count)); foreach (var el in (IEnumerable)vlue) { Serialize(wrtr, elementType, nlble, el); } }; WriteFunctions[type] = writeFunc; writeFunc(writer, value, nullable); return; } foreach (var info in RpcInterface.GetOrederedFields(type)) { if (!info.IsStatic) { Serialize(writer, info.FieldType, NullableParamCache.Contains(info), info.GetValue(value)); } } foreach (var info in RpcInterface.GetOrderedProperties(type)) { if (info.CanRead && info.CanWrite) { Serialize(writer, info.PropertyType, NullableParamCache.Contains(info), info.GetValue(value, null)); } } }
public static object Deserialize(BinaryReader reader, Type type, bool nullable) { if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(System.Nullable <>)) { Type underlyingType = type.GetGenericArguments()[0]; return(Deserialize(reader, underlyingType, true)); } if (nullable && reader.ReadByte() == 0) { return(null); } Func <BinaryReader, bool, object> deserializerFunc; if (ReadFunctions.TryGetValue(type, out deserializerFunc)) { return(deserializerFunc(reader, nullable)); } if (type.IsEnum) { Type underlyingType = Enum.GetUnderlyingType(type); if (ReadFunctions.TryGetValue(underlyingType, out deserializerFunc)) { object value = deserializerFunc(reader, nullable); return(Enum.ToObject(type, value)); } throw new SerializationException("Enum " + type.Name + " underlying type is not serializable."); } SerializableTypeInfo serTypeInfo = SerializableTypeCache[type]; if (serTypeInfo != null) { if (serTypeInfo.DeserializeMethod != null) { return(serTypeInfo.DeserializeMethod.Invoke(null, new object[] { reader })); } if (serTypeInfo.Constructor != null) { return(Activator.CreateInstance(type, reader)); } } Type elementType = GetListElementType(type); if (elementType != null) { Func <BinaryReader, bool, object> readFunc; if (type.IsArray) { readFunc = (rdr, nlble) => { int length = rdr.ReadUInt16(); var array = (Array)Activator.CreateInstance(type, length); for (int i = 0; i < length; ++i) { array.SetValue(Deserialize(rdr, elementType, nlble), i); } return(array); }; } else { Type listType = typeof(List <>).MakeGenericType(elementType); readFunc = (rdr, nlble) => { int length = rdr.ReadUInt16(); var list = (IList)Activator.CreateInstance(listType); for (int i = 0; i < length; ++i) { list.Add(Deserialize(rdr, elementType, nlble)); } return(list); }; } ReadFunctions[type] = readFunc; return(readFunc(reader, nullable)); } var obj = Activator.CreateInstance(type); foreach (var info in RpcInterface.GetOrederedFields(type)) { if (!info.IsStatic) { var fieldValue = Deserialize(reader, info.FieldType, NullableParamCache.Contains(info)); info.SetValue(obj, fieldValue); } } foreach (var info in RpcInterface.GetOrderedProperties(type)) { if (info.CanRead && info.CanWrite) { var propValue = Deserialize(reader, info.PropertyType, NullableParamCache.Contains(info)); info.SetValue(obj, propValue, null); } } return(obj); }
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); } }