Inheritance: ISoapMessage
		public void TestObjects() {
			object objReturn;
			objReturn = Serialize("");
			objReturn = Serialize("hello world!");
			Assertion.AssertEquals("#string", "hello world!", objReturn);
			SoapMessage soapMsg = new SoapMessage();
			soapMsg.Headers = new Header[0];
			soapMsg.MethodName = "Equals";
			soapMsg.ParamNames = new String[0];
			soapMsg.ParamTypes = new Type[0];
			soapMsg.ParamValues = new object[0];
			soapMsg.XmlNameSpace = SoapServices.CodeXmlNamespaceForClrTypeNamespace("String", "System");
			_soapFormatterDeserializer.TopObject = new SoapMessage();
			objReturn = Serialize(soapMsg);
			_soapFormatterDeserializer.TopObject = null;
			SimpleObject obj = new SimpleObject("simple object", 1);
			objReturn = Serialize(obj);
			Assertion.AssertEquals("#SimpleObject", obj, objReturn);
			objReturn = Serialize(typeof(SimpleObject));
			Assertion.AssertEquals("#Type", typeof(SimpleObject), (Type)objReturn);
			objReturn = Serialize(obj.GetType().Assembly);
			Assertion.AssertEquals("#Assembly", obj.GetType().Assembly, objReturn);
		}
		public void TestMethodSignatureSerialization ()
		{
			Header h = new Header ("__MethodSignature", new Type [] { typeof(string),typeof(SignatureTest[]) }, false, "http://schemas.microsoft.com/clr/soap/messageProperties");

			SoapMessage msg = new SoapMessage ();
			msg.MethodName = "Run";
			msg.ParamNames = new string [] { "nom" };
			msg.ParamTypes = new Type [] { typeof(SignatureTest) };
			msg.ParamValues = new object[] { new SignatureTest () };
			msg.Headers = new Header[] { h};

			MemoryStream ms = new MemoryStream ();
			SoapFormatter sf = new SoapFormatter ();
			sf.Serialize (ms, msg);

			ms.Position = 0;

			SoapMessage t = new SoapMessage ();
			sf.TopObject = t;
			t = (SoapMessage) sf.Deserialize (ms);
			
			Assertion.AssertNotNull ("#1", t.Headers[0].Value);
			Assertion.AssertEquals ("#2", t.Headers[0].Value.GetType (), typeof(Type[]));
			
			Type[] ts = (Type[]) t.Headers[0].Value;
			
			Assertion.AssertEquals ("#3", 2, ts.Length);
			Assertion.AssertNotNull ("#4", ts[0]);
			Assertion.AssertNotNull ("#5", ts[1]);
			Console.WriteLine ("PPP:" + ts[0].GetType());
			Assertion.AssertEquals ("#6", typeof(string), ts[0]);
			Assertion.AssertEquals ("#7", typeof(SignatureTest[]), ts[1]);
		}
		internal SoapMessage CreateSoapMessage (bool isRequest)
		{
			if (isRequest) return new SoapMessage ();
			
			int n = 0;
			Type[] types = new Type [_methodCallParameters.Length + 1];
			
			if (_methodCallInfo.ReturnType != typeof(void)) {
				types[0] = _methodCallInfo.ReturnType;
				n++;
			}
				
			foreach(ParameterInfo paramInfo in _methodCallParameters)
			{
				if (paramInfo.ParameterType.IsByRef || paramInfo.IsOut)
				{
					Type t = paramInfo.ParameterType;
					if (t.IsByRef) t = t.GetElementType();
					types [n++] = t;
				}
			}
			SoapMessage sm = new SoapMessage ();
			sm.ParamTypes = types;
			return sm;
		}
		// used by the server
		internal object BuildSoapMessageFromMethodResponse(IMethodReturnMessage mrm, out ITransportHeaders responseHeaders)
		{
			responseHeaders = new TransportHeaders();

			if(mrm.Exception == null) {
				// *normal* function return
				
				SoapMessage soapMessage = new SoapMessage();
				
				// fill the transport headers
				responseHeaders["Content-Type"] = "text/xml; charset=\"utf-8\"";

				// build the SoapMessage
				ArrayList paramNames = new ArrayList();
				ArrayList paramValues = new ArrayList();
				ArrayList paramTypes = new ArrayList();
				soapMessage.MethodName = mrm.MethodName+"Response";
				
				Type retType = ((MethodInfo)mrm.MethodBase).ReturnType;
				
				if(retType != typeof(void)) {
					paramNames.Add("return");
					paramValues.Add(mrm.ReturnValue);
					if (mrm.ReturnValue != null)
						paramTypes.Add(mrm.ReturnValue.GetType());
					else
						paramTypes.Add(retType);
				}
				
				for(int i = 0; i < mrm.OutArgCount; i++){
					paramNames.Add(mrm.GetOutArgName(i));
					paramValues.Add(mrm.GetOutArg(i));
					if(mrm.GetOutArg(i) != null) paramTypes.Add(mrm.GetOutArg(i).GetType());
				}
				soapMessage.ParamNames = (string[]) paramNames.ToArray(typeof(string));
				soapMessage.ParamValues = (object[]) paramValues.ToArray(typeof(object));
				soapMessage.ParamTypes = (Type[]) paramTypes.ToArray(typeof(Type));
				soapMessage.XmlNameSpace = _xmlNamespace;
				soapMessage.Headers = BuildMessageHeaders (mrm);
				return soapMessage;
			}
			else {
				// an Exception was thrown while executing the function
				responseHeaders["__HttpStatusCode"] = "500";
				responseHeaders["__HttpReasonPhrase"] = "Bad Request";
				// fill the transport headers
				responseHeaders["Content-Type"] = "text/xml; charset=\"utf-8\"";
				ServerFault serverFault = CreateServerFault(mrm.Exception);
				return new SoapFault("Server", String.Format(" **** {0} - {1}", mrm.Exception.GetType().ToString(), mrm.Exception.Message), null, serverFault);
			}
		}
		// used by the server
		internal IMessage BuildMethodCallFromSoapMessage(SoapMessage soapMessage, string uri) 
		{
			ArrayList headersList = new ArrayList();
			Type[] signature = null;
			
			headersList.Add(new Header("__Uri", uri));
			headersList.Add(new Header("__MethodName", soapMessage.MethodName));
			string typeNamespace, assemblyName;

			if (!SoapServices.DecodeXmlNamespaceForClrTypeNamespace(soapMessage.XmlNameSpace, out typeNamespace, out assemblyName))
				throw new RemotingException ("Could not decode SoapMessage");

			// Note that we don't need to validate the type in
			// this place because MethodCall will do it anyway.

			if (assemblyName == null) // corlib
				_serverType = Type.GetType (typeNamespace, true);
			else
				_serverType = Type.GetType (typeNamespace + ", " + assemblyName, true);

			headersList.Add(new Header("__TypeName", _serverType.FullName, false));
			
			if (soapMessage.Headers != null) {
				foreach (Header h in soapMessage.Headers) {
					headersList.Add (h);
					if (h.Name == "__MethodSignature")
						signature = (Type[]) h.Value;
				}
			}
			
			_xmlNamespace = soapMessage.XmlNameSpace;
			//RemMessageType messageType;
			
			BindingFlags bflags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			
			if (signature == null)
				_methodCallInfo = _serverType.GetMethod(soapMessage.MethodName, bflags); 
			else
				_methodCallInfo = _serverType.GetMethod(soapMessage.MethodName, bflags, null, signature, null);
				
			if (_methodCallInfo == null && (soapMessage.MethodName == "FieldSetter" || soapMessage.MethodName == "FieldGetter"))
				_methodCallInfo = typeof(object).GetMethod (soapMessage.MethodName, bflags);

			// the *out* parameters aren't serialized
			// have to add them here
			_methodCallParameters = _methodCallInfo.GetParameters();
			object[] args = new object[_methodCallParameters.Length];
			int sn = 0;
			for (int n=0; n<_methodCallParameters.Length; n++)
			{
				ParameterInfo paramInfo = _methodCallParameters [n];
				Type paramType = (paramInfo.ParameterType.IsByRef ? paramInfo.ParameterType.GetElementType() : paramInfo.ParameterType);

				if (paramInfo.IsOut && paramInfo.ParameterType.IsByRef) {
					args [n] = GetNullValue (paramType);
				}
				else{
					object val = soapMessage.ParamValues[sn++];
					if(val is IConvertible) 
						args [n] = Convert.ChangeType (val, paramType);
					else
						args [n] = val;
				}
			}
			
			headersList.Add(new Header("__Args", args, false));
						
			Header[] headers = (Header[])headersList.ToArray(typeof(Header));

			// build the MethodCall from the headers
			MethodCall mthCall = new MethodCall(headers);
			return (IMessage)mthCall;
		}
		// used by the client
		internal SoapMessage BuildSoapMessageFromMethodCall(
				IMethodCallMessage mcm,
				out ITransportHeaders requestHeaders)
		{
			
			requestHeaders = new TransportHeaders();
			SoapMessage soapMsg = new SoapMessage();

			GetInfoFromMethodCallMessage(mcm);

			// Format the SoapMessage that will be used to create the RPC
			soapMsg.MethodName = mcm.MethodName;
			//int count = mcm.ArgCount;
			ArrayList paramNames = new ArrayList(_methodCallParameters.Length);
			ArrayList paramTypes = new ArrayList(_methodCallParameters.Length);
			ArrayList paramValues = new ArrayList(_methodCallParameters.Length);
			
			// Add the function parameters to the SoapMessage class
			foreach(ParameterInfo paramInfo in _methodCallParameters) {
				if (!(paramInfo.IsOut && paramInfo.ParameterType.IsByRef)) {
					Type t = paramInfo.ParameterType;
					if (t.IsByRef) t = t.GetElementType ();
					paramNames.Add(paramInfo.Name);
					paramTypes.Add(t);
					paramValues.Add(mcm.Args[paramInfo.Position]);
				}
			}			
			soapMsg.ParamNames = (string[]) paramNames.ToArray(typeof(string));
			soapMsg.ParamTypes = (Type[]) paramTypes.ToArray(typeof(Type));
			soapMsg.ParamValues = (object[]) paramValues.ToArray(typeof(object));
			soapMsg.XmlNameSpace = SoapServices.GetXmlNamespaceForMethodCall(_methodCallInfo);
			soapMsg.Headers = BuildMessageHeaders (mcm);

			// Format the transport headers
			requestHeaders["Content-Type"] = "text/xml; charset=\"utf-8\"";
			requestHeaders["SOAPAction"] = "\""+
				SoapServices.GetSoapActionFromMethodBase(_methodCallInfo)+"\""; 
			requestHeaders[CommonTransportKeys.RequestUri] = mcm.Uri;
			
			return soapMsg;
			
		}
		// used by the server
		internal IMessage BuildMethodCallFromSoapMessage(SoapMessage soapMessage, string uri) 
		{
			ArrayList headersList = new ArrayList();
			Type[] signature = null;
			
			headersList.Add(new Header("__Uri", uri));
			headersList.Add(new Header("__MethodName", soapMessage.MethodName));
			string typeNamespace, assemblyName;
			SoapServices.DecodeXmlNamespaceForClrTypeNamespace(soapMessage.XmlNameSpace, out typeNamespace, out assemblyName);

			_serverType = RemotingServices.GetServerTypeForUri(uri);
			headersList.Add(new Header("__TypeName", _serverType.FullName, false));
			
			if (soapMessage.Headers != null) {
				foreach (Header h in soapMessage.Headers) {
					headersList.Add (h);
					if (h.Name == "__MethodSignature")
						signature = (Type[]) h.Value;
				}
			}
			
			_xmlNamespace = soapMessage.XmlNameSpace;
			//RemMessageType messageType;
			
			BindingFlags bflags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			
			if (signature == null)
				_methodCallInfo = _serverType.GetMethod(soapMessage.MethodName, bflags); 
			else
				_methodCallInfo = _serverType.GetMethod(soapMessage.MethodName, bflags, null, signature, null); 

			// the *out* parameters aren't serialized
			// have to add them here
			_methodCallParameters = _methodCallInfo.GetParameters();
			object[] args = new object[_methodCallParameters.Length];
			int sn = 0;
			for (int n=0; n<_methodCallParameters.Length; n++)
			{
				ParameterInfo paramInfo = _methodCallParameters [n];
				Type paramType = (paramInfo.ParameterType.IsByRef ? paramInfo.ParameterType.GetElementType() : paramInfo.ParameterType);

				if (paramInfo.IsOut && paramInfo.ParameterType.IsByRef) {
					args [n] = GetNullValue (paramType);
				}
				else{
					object val = soapMessage.ParamValues[sn++];
					if(val is IConvertible) 
						args [n] = Convert.ChangeType (val, paramType);
					else
						args [n] = val;
				}
			}
			
			headersList.Add(new Header("__Args", args, false));
						
			Header[] headers = (Header[])headersList.ToArray(typeof(Header));

			// build the MethodCall from the headers
			MethodCall mthCall = new MethodCall(headers);
			return (IMessage)mthCall;
		}