示例#1
0
        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);
        }