void TestNpcReturnLine(NpcReturnLine expectedReturnLine, String returnLineString) { Console.WriteLine("Testing '{0}'", returnLineString); NpcReturnLine actualReturnLine = new NpcReturnLine(returnLineString); Assert.AreEqual(expectedReturnLine.exceptionMessage, actualReturnLine.exceptionMessage); Assert.AreEqual(expectedReturnLine.sosTypeName, actualReturnLine.sosTypeName); Assert.AreEqual(expectedReturnLine.sosSerializationString, actualReturnLine.sosSerializationString); }
void ThrowExceptionFromCall(String methodName, NpcReturnLine returnLine) { Type exceptionType; try { exceptionType = staticClientTypeFinder.FindType(returnLine.sosTypeName); } catch (InvalidOperationException) { //Console.WriteLine("Could not find type '{0}'", returnLine.sosTypeName); goto INVALID_EXCEPTION; } Object exceptionObject; try { Int32 offset = Sos.Deserialize(out exceptionObject, exceptionType, returnLine.sosSerializationString, 0, returnLine.sosSerializationString.Length); if (offset != returnLine.sosSerializationString.Length) { goto INVALID_EXCEPTION; } } catch (Exception) { //Console.WriteLine("Faild to deserialize exception '{0}'", returnLine.sosTypeName); goto INVALID_EXCEPTION; } try { Exception e = (Exception)exceptionObject; throw e; } catch (InvalidCastException) { //Console.WriteLine("Could not cast '{0}' to Exception", exceptionObject.GetType().Name); goto INVALID_EXCEPTION; } INVALID_EXCEPTION: throw new Exception(String.Format("Method '{0}' threw exception {1}: '{2}'", methodName, returnLine.sosTypeName, returnLine.exceptionMessage)); }
// expectedReturnType can be null, but providing the expected return type makes it unnecessary to search // each assembly for the type Object PerformCall(Type expectedReturnType, String methodName, String rawNpcLine) { if (threadSafe) { Monitor.Enter(serverEndPoint); } try { // // The reason for the retry logic is because if the underlying socket is disconnected, it may not // fail until after a send and a receive...so the socket should be reconnected and the request should // be repeated only once. // for (UInt32 attempt = 0; ; attempt++) { try { Connect(); socketLineReader.socket.Send(Encoding.UTF8.GetBytes(rawNpcLine.ToString())); String returnLineString = socketLineReader.ReadLine(); if (returnLineString == null) { if (attempt == 0) { Dispose(); continue; // Retry } throw UnexpectedClose(); } NpcReturnLine returnLine = new NpcReturnLine(returnLineString); if (returnLine.exceptionMessage != null) { ThrowExceptionFromCall(methodName, returnLine); } if (expectedReturnType == null) { if (returnLine.sosTypeName.Equals("Void")) { return(null); } expectedReturnType = GetTypeFromSosTypeName(returnLine.sosTypeName); } else { if (!returnLine.sosTypeName.Equals(expectedReturnType.SosTypeName())) { throw new InvalidOperationException(String.Format("Expected return type to be {0} but was {1}", expectedReturnType.SosTypeName(), returnLine.sosTypeName)); } } if (expectedReturnType == typeof(void)) { return(null); } Object returnObject; Int32 valueStringOffset = Sos.Deserialize(out returnObject, expectedReturnType, returnLine.sosSerializationString, 0, returnLine.sosSerializationString.Length); if (valueStringOffset != returnLine.sosSerializationString.Length) { throw new InvalidOperationException(String.Format( "Used {0} characters to deserialize object of type '{1}' but the serialization string had {2} characters", valueStringOffset, expectedReturnType.SosTypeName(), returnLine.sosSerializationString.Length)); } return(returnObject); } catch (SocketException) { if (socketLineReader != null) { socketLineReader.Dispose(); socketLineReader = null; } if (attempt == 0) { continue; // Retry } throw; } } } finally { if (threadSafe) { Monitor.Exit(serverEndPoint); } } }