// created on 24/04/2003 at 15:35 // // System.Runtime.Serialization.Formatters.Soap.SoapReader // // Authors: // Jean-Marc Andre (jean-marc.andre@polymtl.ca) // using System; using System.Reflection; using System.Collections; using System.Runtime.Serialization; namespace System.Runtime.Serialization.Formatters.Soap { internal sealed class SoapReader: ISoapReader { public event ElementReadEventHandler ElementReadEvent; private ISoapMessage _soapMessage; private ISoapParser _parser; private SerializationBinder _binder; public SerializationBinder Binder { get { return _binder;} set { _binder = value;} } public ISoapMessage TopObject { get { return _soapMessage; } set { _soapMessage = value; // the first element of the SOAP stream // should be a SOAP RPC _parser.SoapElementReadEvent -= new SoapElementReadEventHandler(SoapElementRead); _parser.SoapElementReadEvent += new SoapElementReadEventHandler(SoapRPCElementRead); } } public SoapReader(ISoapParser parser) { // register the SoapElementReadEvent handler _parser = parser; _parser.SoapElementReadEvent += new SoapElementReadEventHandler(SoapElementRead); } public void SoapRPCElementRead(ISoapParser sender, SoapElementReadEventArgs e) { _parser.SoapElementReadEvent += new SoapElementReadEventHandler(SoapElementRead); _parser.SoapElementReadEvent -= new SoapElementReadEventHandler(SoapRPCElementRead); Queue elementQueue = e.ElementQueue; Queue elementInfoQueue = new Queue(); SoapSerializationEntry root = (SoapSerializationEntry) elementQueue.Dequeue(); // fill the SoapMessage members // MethodName //elementInfoQueue.Enqueue(new ElementInfo(typeof(string), "MethodName", rpcInfo.elementName, ElementType.Nothing, 0, 0); _soapMessage.MethodName = root.elementName; // XmlNamespace //elementInfoQueue.Enqueue(new ElementInfo(typeof(string), "XmlNamespace", rpcInfo.elementNamespace, ElementType.Nothing, 0, 0); _soapMessage.XmlNameSpace = root.elementNamespace; // the root element is a SoapMessage ElementInfo rpcInfo = new ElementInfo(typeof(SoapMessage), String.Empty, _soapMessage, ElementType.Id, 1, null); //todo: headers // add the function parameters to the queue SoapSerializationEntry field; ElementInfo fieldElementInfo; while(elementQueue.Count > 0){ field = (SoapSerializationEntry) elementQueue.Dequeue(); fieldElementInfo = GetElementInfo(field); elementInfoQueue.Enqueue(fieldElementInfo); } // raise the ElementReadEvent ElementReadEvent(this,new ElementReadEventArgs(rpcInfo, elementInfoQueue)); } // called when SoapElementReadEvent is raized by the SoapParser object public void SoapElementRead(ISoapParser sender, SoapElementReadEventArgs e) { Queue elementQueue = e.ElementQueue; Queue elementInfoQueue = new Queue(); SoapSerializationEntry root = (SoapSerializationEntry) elementQueue.Dequeue(); ElementInfo rootInfo = GetElementInfo(root); SoapSerializationEntry field; ElementInfo fieldElementInfo; while(elementQueue.Count > 0){ field = (SoapSerializationEntry) elementQueue.Dequeue(); fieldElementInfo = GetElementInfo(field); elementInfoQueue.Enqueue(fieldElementInfo); } // raise the ElementReadEvent ElementReadEvent(this,new ElementReadEventArgs(rootInfo, elementInfoQueue)); } // Converts the text information from the SoapParser into // information that with by used by the ObjectReader to reconstruct // the object. private ElementInfo GetElementInfo(SoapSerializationEntry entry) { SoapTypeMapping mapping = new SoapTypeMapping(entry.elementName, entry.elementNamespace); Type elementType = SoapTypeMapper.GetType(mapping); if(elementType != null && _binder != null) { elementType = _binder.BindToType(elementType.Assembly.FullName, elementType.FullName); if(elementType == null) throw new SerializationException(); } long id = 0; ElementType elementId = ElementType.Nothing; ICollection attrLst = entry.elementAttributes; int[] arrayRank = null; foreach(SoapAttributeStruct attr in attrLst){ if(attr.attributeName == "id"){ string attrId = ((string)attr.attributeValue).Remove(0,4); id = (new FormatterConverter()).ToInt64(attrId); elementId = ElementType.Id; } else if(attr.attributeName == "href") { string attrId = ((string)attr.attributeValue).Remove(0,5); id = (new FormatterConverter()).ToInt64(attrId); elementId = ElementType.Href; } else if(attr.attributeName == "xsi:null" && attr.attributeValue == "1") { elementId = ElementType.Null; } else if(attr.attributeName == "SOAP-ENC:arrayType") { string[] tokens = attr.attributeValue.Split(new System.Char[] {'[',',',']'}); mapping = new SoapTypeMapping(tokens[0], attr.prefix); elementType = SoapTypeMapper.GetType(mapping); arrayRank = new int[tokens.Length - 2]; for(int i=0; i