private Type UnknownTypeResolver(SerializationContext context) { if (context.InterfaceType != null) { return(containerHost.GetInterfaceImplementationType(context.InterfaceType.FullName)); } else if (context.ParentObject is GenericMessage && context.Key == GenericMessagePayloadPropertyName) { GenericMessage message = (GenericMessage)context.ParentObject; // check out of order json keys -> load manually if (message.Type == MessageType.Undefined) { message.Type = (MessageType)short.Parse(GetJsonSimpleStringValue(context.JsonString, "Type")); } if (message.Type == MessageType.Exception) { if (context.IsDeserialize) { // check if payload contains complex type (ExceptionWrapper) // this check must be done because of backwards compatibility int nextObjectOrValueIndex = context.ValueStartIndex + context.Key.Length + 3; if (nextObjectOrValueIndex < context.JsonString.Length && context.JsonString[nextObjectOrValueIndex] == Structure.CharLeftBrace) { return(typeof(ExceptionWrapper)); } else { return(typeof(string)); } } else { // always serialize wrapper object return(typeof(ExceptionWrapper)); } } if (context.ExternalContext is IInvokeMethodInfo) { // serialize context IInvokeMethodInfo invokeInfo = (IInvokeMethodInfo)context.ExternalContext; switch (message.Type) { case MessageType.MethodInvokeRequest: case MessageType.AsyncMethodInvokeRequest: if (context.ArrayIndex.HasValue) { var paramInfo = invokeInfo.ParameterInfos[context.ArrayIndex.Value]; if (paramInfo.IsOut) { // determine out parameter type return(paramInfo.ParameterType.GetElementType()); } else { return(paramInfo.ParameterType); } } else { return(objectArrayType); } case MessageType.MethodInvokeResponse: if (context.ArrayIndex.HasValue == false || context.ArrayIndex == 0) { return(TypeService.GetAsyncAwaitResultType(invokeInfo.InterfaceMethod.ReturnType)); } else { // determine out parameter type return(invokeInfo.OutParameters[context.ArrayIndex.Value - 1].ParameterType.GetElementType()); } } } else if (context.ExternalContext is ISession) { // deserialize context ISession session = (ISession)context.ExternalContext; switch (message.Type) { case MessageType.AsyncMethodInvokeRequest: case MessageType.MethodInvokeRequest: if (context.ArrayIndex.HasValue) { // check out of order json keys -> load manually if (message.Name == null) { message.Name = GetJsonSimpleStringValue(context.JsonString, "Name"); } if (message.Target == null) { message.Target = GetJsonSimpleStringValue(context.JsonString, "Target"); } int cacheKey = message.Target.GetHashCode(); cacheKey = cacheKey * 23 + message.Name.GetHashCode(); ParameterInfo[] parameters; if (!methodParameterCache.TryGetValue(cacheKey, out parameters)) { Type interfaceServiceType; if (TypeService.TryGetTypeByName(message.Target, out interfaceServiceType)) { MethodInfo mi = TypeService.GetMethodByName(interfaceServiceType, message.Name); if (mi == null) { throw new InvalidOperationException(string.Format("The method: \"{0}\" is not specified in the interface: \"{1}\"", message.Name, interfaceServiceType.AssemblyQualifiedName)); } parameters = mi.GetParameters(); methodParameterCache[cacheKey] = parameters; } else { throw new TypeLoadException(string.Format("The interface \"{0}\" could not be found!", message.Target)); } } if (parameters.Length > context.ArrayIndex.Value) { return(parameters[context.ArrayIndex.Value].ParameterType); } else { // method does not support requested parameter index // BL 02.05.2020: happened because of wrong escape json chars throw new IndexOutOfRangeException($"Requested method parameter index {context.ArrayIndex.Value} not available in method {message.Target}; {message.Name}"); } } else { return(objectArrayType); } case MessageType.MethodInvokeResponse: IInvokeState invokeState; if (session.PendingRequests.TryGetValue(message.RequestId, out invokeState)) { if (invokeState.OutParameterValues != null) { if (context.ArrayIndex.HasValue) { if (context.ArrayIndex == 0) { return(invokeState.Method.ReturnType); } else { Type type = invokeState.MethodSource.OutParameters[context.ArrayIndex.Value - 1].ParameterType; type = type.GetElementType(); return(type); } } else { return(objectArrayType); } } else if (context.ArrayIndex == 0 || !context.ArrayIndex.HasValue) { // first arrar item contains method return type // or payload only inlcudes return object return(TypeService.GetAsyncAwaitResultType(invokeState.Method.ReturnType)); } } else { throw new InvalidOperationException("Pending request ID: " + message.RequestId + " message not found!"); } break; } } else if ((message.Type == MessageType.MethodInvokeRequest || message.Type == MessageType.AsyncMethodInvokeRequest) && !context.ArrayIndex.HasValue) { return(objectArrayType); } } return(null); }