/// <summary> /// Initializes a new instance of the <see cref="GenericMessage"/> class. /// </summary> /// <param name="requestId">The request id.</param> /// <param name="invokeMethodInfo">The invoke method info.</param> /// <param name="parameters">The parameters.</param> /// <param name="responseExptected">if set to <c>true</c> [response exptected].</param> public GenericMessage(long requestId, IInvokeMethodInfo invokeMethodInfo, object[] parameters, bool responseExptected) { this.Type = responseExptected ? MessageType.MethodInvokeRequest : MessageType.AsyncMethodInvokeRequest; this.RequestId = requestId; this.Target = TypeService.GetSourceCodeTypeName(invokeMethodInfo.InterfaceMethod.DeclaringType); this.Name = invokeMethodInfo.QualifiedMethodName; this.Payload = parameters; }
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); }
public IValueItem DetermineSpecialInterfaceType(Type sourceType, Type defaultInterfaceType, ISerializeContext context) { // reverse lookup interfaces Type resultType = null; IValueItem specialTarget; if (serializer.TryGetDifferentTargetType(sourceType, out specialTarget) && specialTarget != null) { return(specialTarget); } // check contextual target type { if (sourceType.Equals(typeof(Communication.Common.GenericMessage))) { resultType = typeof(IGenericMessage); } else if (context.ParentObject is IGenericMessage) { IGenericMessage message = (IGenericMessage)context.ParentObject; 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 resultType = paramInfo.ParameterType.GetElementType(); } else { resultType = paramInfo.ParameterType; } } break; //else //{ // return objectArrayType; //} case MessageType.MethodInvokeResponse: if (context.ArrayIndex == 0 || !context.ArrayIndex.HasValue) { resultType = invokeInfo.InterfaceMethod.ReturnType; } else { // determine out parameter type resultType = invokeInfo.OutParameters[context.ArrayIndex.Value - 1].ParameterType.GetElementType(); } break; } } 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) { 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)); } } resultType = parameters[context.ArrayIndex.Value].ParameterType; } else { resultType = objectArrayType; } break; 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) { resultType = invokeState.Method.ReturnType; } else { Type type = invokeState.MethodSource.OutParameters[context.ArrayIndex.Value - 1].ParameterType; type = type.GetElementType(); resultType = type; } } else { resultType = objectArrayType; } } else if (context.ArrayIndex == 0 || !context.ArrayIndex.HasValue) { // first arrar item contains method return type // or payload only inlcudes return object resultType = 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) { resultType = objectArrayType; } } } if (resultType != null) { return(serializer.RegisterDifferentTargetType(sourceType, defaultInterfaceType, resultType, context)); } else { return(serializer.DetermineSpecialInterfaceType(sourceType, defaultInterfaceType, context));; } }