Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Framework / System / Windows / Markup / XamlParser.cs / 2 / XamlParser.cs
/****************************************************************************\ * * File: XamlParser.cs * * Purpose: Class for compiling Xaml. * * History: * 6/06/01: rogerg Created * 5/28/03: peterost Ported to wcp * 10/6/03: peterost Reorganized to remove DP - clr distinction * * Copyright (C) 2003 by Microsoft Corporation. All rights reserved. * \***************************************************************************/ using System; using System.Xml; using System.IO; using System.Text; using System.Collections; using System.ComponentModel; using System.Diagnostics; using System.Reflection; using System.Globalization; using System.Security.Permissions; using MS.Utility; using System.Runtime.InteropServices; using MS.Internal; // Disabling 1634 and 1691: // In order to avoid generating warnings about unknown message numbers and // unknown pragmas when compiling C# source code with the C# compiler, // you need to disable warnings 1634 and 1691. (Presharp Documentation) #pragma warning disable 1634, 1691 #if PBTCOMPILER namespace MS.Internal.Markup #else using System.Windows; namespace System.Windows.Markup #endif { #region enums ////// Parser modes. indicates if the Xaml should be parsed [....] or async. /// currently public so test can set these values. /// internal enum XamlParseMode { ////// Not initialized /// Uninitialized, ////// [....] /// Synchronous, ////// Async /// Asynchronous, } #endregion enums ////// XamlParser class. This class is used internally /// internal class XamlParser { #region Constructors ////// Constructor that takes a stream and creates an XmlCompatibilityReader on it. /// public XamlParser( ParserContext parserContext, BamlRecordWriter bamlWriter, Stream xamlStream, bool multipleRoots) : this(parserContext, bamlWriter, new XmlTextReader(xamlStream, multipleRoots ? XmlNodeType.Element : XmlNodeType.Document, (XmlParserContext)parserContext) ) { } #if !PBTCOMPILER ////// Constructor that takes an XmlReader directly /// public XamlParser( ParserContext parserContext, BamlRecordWriter bamlWriter, XmlReader xmlReader, bool wrapWithMarkupCompatReader) : this(parserContext, bamlWriter) { if (wrapWithMarkupCompatReader) { XmlCompatibilityReader xcr = new XmlCompatibilityReader(xmlReader, new IsXmlNamespaceSupportedCallback(IsXmlNamespaceSupported), _predefinedNamespaces ); xmlReader = xcr; } TokenReader = new XamlReaderHelper(this,parserContext,xmlReader); } #endif protected XamlParser( ParserContext parserContext, BamlRecordWriter bamlWriter, XmlTextReader textReader) : this(parserContext, bamlWriter) { // When the XML 1.0 specification was authored, security was not a top concern, and as a result DTDs have the // unfortunate capability of severe Denial of Service (DoS) attacks, typically through the use of an internal // entity expansion technique. In System.Xml V2.0, in order to provide protection against DTD DoS attacks there // is the capability of turning off DTD parsing through the use of the ProhibitDtd property. textReader.ProhibitDtd = true; XmlCompatibilityReader xcr = new XmlCompatibilityReader(textReader, new IsXmlNamespaceSupportedCallback(IsXmlNamespaceSupported), _predefinedNamespaces ); TokenReader = new XamlReaderHelper(this,parserContext,xcr); } protected XamlParser( ParserContext parserContext, BamlRecordWriter bamlWriter) { _parserContext = parserContext; _bamlWriter = bamlWriter; } // Default constructor to aid in subclassing protected XamlParser() { } #endregion Constructors #region PublicMethods #if !PBTCOMPILER ////// Gets the Parse Mode that is either specified /// in the XAML file or explicitly set with SetParseMode. /// If GetParseMode() or SetParseMode() is not set /// before Parse() is called the mode defaults to synchronous /// ///Current parse mode public XamlParseMode GetParseMode() { // loop until hit end or get a parse mode // this loop relies on ReadXaml to set the ParseMode // mode to a default either by having the attribute set // or setting it after the first tag. bool firstRead = true; while (XamlParseMode == XamlParseMode.Uninitialized && ReadXaml(true)) { // If this is the first record we've read, we should know what // the encoding is on the file since the byte order mark will have // been read. Check to make sure its not UTF-7, since // this isn't supported. if (firstRead) { Encoding encoding = TokenReader.Encoding; if (!(encoding is System.Text.UTF8Encoding) && !(encoding is System.Text.UnicodeEncoding)) { ThrowException(SRID.ParserBadEncoding, 1, 1); } } firstRead = false; } // if still unitialized because there aren't any tags // or we are being loaded with parser hooks then // set it to synchronous if (XamlParseMode == XamlParseMode.Uninitialized || (null != ParserHooks)) { XamlParseMode = XamlParseMode.Synchronous; } return XamlParseMode; } #endif ////// Main method to Parse the XAML. /// When in synchronous mode the entire file is parsed before /// this method returns. /// In asynchronous mode at least the root tag is parsed. This /// is necessary for the way binders currently work. /// public void Parse() { // if parseMode hasn't been set then set it now to synchronous. if (XamlParseMode == XamlParseMode.Uninitialized) { XamlParseMode = XamlParseMode.Synchronous; } _Parse(); } ////// Main function called by the XamlCompiler on a Compile. /// If singleRecordMode is true the Read returns after each item read. /// ///True if more nodes to read // !! Review - now that have separate out into XamlReaderHelper // review if still need all the virtuals or the caller of the TokenReader // can dispatch as they feel appropriate. public bool ReadXaml(bool singleRecordMode) { XamlNode xamlNode = null; bool cleanup = !singleRecordMode; bool done = false; try // What do we do with Exceptions we catch on this thread?. { while (TokenReader.Read(ref xamlNode)) { SetParserAction(xamlNode); if (ParserAction == ParserAction.Normal) { // If processing of the xaml node determines that we are done, // then stop now. This can happen if ProcessXamlNode is // overridden (such as when processing styles) and the parsed // block is finished, but the overall file is not. In that // case exit this parser, but leave everything intact. ProcessXamlNode(xamlNode, ref cleanup, ref done); if (done) { break; } // return here in single record mode since we don't want // to set the parser loop to Done. if (singleRecordMode) { return true; } } } } #if PBTCOMPILER || !STRESS catch (Exception e) { if (CriticalExceptions.IsCriticalException(e)) { throw; } else { if (e is XamlParseException) { throw; } // If the exception was a XamlParse exception on the other // side of a Reflection Invoke, then just pull up the Parse exception. if (e is TargetInvocationException && e.InnerException is XamlParseException) { throw e.InnerException; } int lineNumber = 0; int linePosition = 0; string newMessage = null; if (e is XmlException) { XmlException xmlEx = (XmlException)e; lineNumber = xmlEx.LineNumber; linePosition = xmlEx.LinePosition; newMessage = xmlEx.Message; } else { // generic exception, If have a xamlNode then use the // nodes values for the line Numbers. if (null != xamlNode) { lineNumber = xamlNode.LineNumber; linePosition = xamlNode.LinePosition; } newMessage = e.Message + " " + SR.Get(SRID.ParserLineAndOffset, lineNumber.ToString(CultureInfo.CurrentCulture), linePosition.ToString(CultureInfo.CurrentCulture)); } XamlParseException parseException = new XamlParseException(newMessage, lineNumber, linePosition, e); ParseError(parseException); // Recurse on error cleanup = true; throw parseException; } } #endif finally { // Perform cleanup only if we encountered a non-recoverable error, or // we're finished reading the stream (EndDocument reached in single // record mode, or end of stream reached in multi-record mode) if (cleanup) { // Close the reader, which will close the underlying stream. TokenReader.Close(); } } return false; } ////// Big switch to handle all the records. /// /// Node received from TokenReader to process /// True if end of stream reached and document is /// totally finished and should be closed /// True if done processing and want to exit. Doesn't /// necessarily mean document is finished (see cleanup) internal virtual void ProcessXamlNode( XamlNode xamlNode, ref bool cleanup, ref bool done) { switch(xamlNode.TokenType) { case XamlNodeType.DocumentStart: XamlDocumentStartNode xamlDocumentStartNode = (XamlDocumentStartNode) xamlNode; WriteDocumentStart(xamlDocumentStartNode); break; case XamlNodeType.DocumentEnd: XamlDocumentEndNode xamlEndDocumentNode = (XamlDocumentEndNode) xamlNode; cleanup = true; done = true; WriteDocumentEnd(xamlEndDocumentNode); break; case XamlNodeType.ElementStart: XamlElementStartNode xamlElementNode = (XamlElementStartNode) xamlNode; WriteElementStart(xamlElementNode); break; case XamlNodeType.ElementEnd: XamlElementEndNode xamlEndElementNode = (XamlElementEndNode) xamlNode; WriteElementEnd(xamlEndElementNode); break; case XamlNodeType.UnknownTagStart: XamlUnknownTagStartNode xamlUnknownTagStartNode = (XamlUnknownTagStartNode) xamlNode; WriteUnknownTagStart(xamlUnknownTagStartNode); break; case XamlNodeType.UnknownTagEnd: XamlUnknownTagEndNode xamlUnknownTagEndNode = (XamlUnknownTagEndNode) xamlNode; WriteUnknownTagEnd(xamlUnknownTagEndNode); break; case XamlNodeType.XmlnsProperty: XamlXmlnsPropertyNode xamlXmlnsPropertyNode = (XamlXmlnsPropertyNode) xamlNode; WriteNamespacePrefix(xamlXmlnsPropertyNode); break; case XamlNodeType.Property: XamlPropertyNode xamlPropertyNode = (XamlPropertyNode) xamlNode; if (xamlPropertyNode.AttributeUsage == BamlAttributeUsage.RuntimeName) { _parserContext.XamlTypeMapper.ValidateNames( xamlPropertyNode.Value, xamlPropertyNode.LineNumber, xamlPropertyNode.LinePosition); } WriteProperty(xamlPropertyNode); break; case XamlNodeType.PropertyWithExtension: XamlPropertyWithExtensionNode xamlPropertyWithExtensionNode = (XamlPropertyWithExtensionNode)xamlNode; WritePropertyWithExtension(xamlPropertyWithExtensionNode); break; case XamlNodeType.PropertyWithType: XamlPropertyWithTypeNode xamlPropertyWithTypeNode = (XamlPropertyWithTypeNode) xamlNode; WritePropertyWithType(xamlPropertyWithTypeNode); break; case XamlNodeType.UnknownAttribute: XamlUnknownAttributeNode xamlUnknownAttributeNode = (XamlUnknownAttributeNode) xamlNode; WriteUnknownAttribute(xamlUnknownAttributeNode); break; case XamlNodeType.PropertyComplexStart: XamlPropertyComplexStartNode xamlPropertyComplexStartNode = (XamlPropertyComplexStartNode) xamlNode; WritePropertyComplexStart(xamlPropertyComplexStartNode); break; case XamlNodeType.PropertyComplexEnd: XamlPropertyComplexEndNode xamlPropertyComplexEndNode = (XamlPropertyComplexEndNode) xamlNode; WritePropertyComplexEnd(xamlPropertyComplexEndNode); break; #if !PBTCOMPILER case XamlNodeType.RoutedEvent: XamlRoutedEventNode xamlRoutedEventNode = (XamlRoutedEventNode) xamlNode; WriteRoutedEvent(xamlRoutedEventNode); break; #endif case XamlNodeType.LiteralContent: XamlLiteralContentNode xamlLiteralContentNode = (XamlLiteralContentNode) xamlNode; WriteLiteralContent(xamlLiteralContentNode); break; case XamlNodeType.Text: XamlTextNode xamlTextNode = (XamlTextNode) xamlNode; WriteText(xamlTextNode); break; case XamlNodeType.ClrEvent: XamlClrEventNode xamlClrEventNode = (XamlClrEventNode) xamlNode; WriteClrEvent(xamlClrEventNode); break; case XamlNodeType.PropertyArrayStart: XamlPropertyArrayStartNode xamlPropertyArrayStartNode = (XamlPropertyArrayStartNode) xamlNode; WritePropertyArrayStart(xamlPropertyArrayStartNode); break; case XamlNodeType.PropertyArrayEnd: XamlPropertyArrayEndNode xamlPropertyArrayEndNode = (XamlPropertyArrayEndNode) xamlNode; WritePropertyArrayEnd(xamlPropertyArrayEndNode); break; case XamlNodeType.PropertyIListStart: XamlPropertyIListStartNode xamlPropertyIListStartNode = (XamlPropertyIListStartNode) xamlNode; WritePropertyIListStart(xamlPropertyIListStartNode); break; case XamlNodeType.PropertyIListEnd: XamlPropertyIListEndNode xamlPropertyIListEndNode = (XamlPropertyIListEndNode) xamlNode; WritePropertyIListEnd(xamlPropertyIListEndNode); break; case XamlNodeType.PropertyIDictionaryStart: XamlPropertyIDictionaryStartNode xamlPropertyIDictionaryStartNode = (XamlPropertyIDictionaryStartNode) xamlNode; WritePropertyIDictionaryStart(xamlPropertyIDictionaryStartNode); break; case XamlNodeType.PropertyIDictionaryEnd: XamlPropertyIDictionaryEndNode xamlPropertyIDictionaryEndNode = (XamlPropertyIDictionaryEndNode) xamlNode; WritePropertyIDictionaryEnd(xamlPropertyIDictionaryEndNode); break; case XamlNodeType.DefTag: XamlDefTagNode xamlDefTagNode = (XamlDefTagNode) xamlNode; WriteDefTag(xamlDefTagNode); break; case XamlNodeType.DefKeyTypeAttribute: XamlDefAttributeKeyTypeNode xamlDefAttributeKeyTypeNode = (XamlDefAttributeKeyTypeNode) xamlNode; WriteDefAttributeKeyType(xamlDefAttributeKeyTypeNode); break; case XamlNodeType.DefAttribute: XamlDefAttributeNode xamlDefAttributeNode = (XamlDefAttributeNode) xamlNode; if (xamlDefAttributeNode.AttributeUsage == BamlAttributeUsage.RuntimeName) { _parserContext.XamlTypeMapper.ValidateNames( xamlDefAttributeNode.Value, xamlDefAttributeNode.LineNumber, xamlDefAttributeNode.LinePosition); } WriteDefAttributeCore(xamlDefAttributeNode); break; case XamlNodeType.PresentationOptionsAttribute: XamlPresentationOptionsAttributeNode xamlPresentationOptionsAttributeNode = (XamlPresentationOptionsAttributeNode) xamlNode; WritePresentationOptionsAttribute(xamlPresentationOptionsAttributeNode); break; case XamlNodeType.PIMapping: XamlPIMappingNode xamlPIMappingNode = (XamlPIMappingNode) xamlNode; WritePIMapping(xamlPIMappingNode); break; // The following tokens that are used primarily by the markup compiler case XamlNodeType.EndAttributes: XamlEndAttributesNode xamlEndAttributesNode = (XamlEndAttributesNode) xamlNode; // if first tag and haven't alredy set the ParseMode // set it to synchronous. if (0 == xamlEndAttributesNode.Depth) { if (XamlParseMode == XamlParseMode.Uninitialized) { XamlParseMode = XamlParseMode.Synchronous; } } WriteEndAttributes(xamlEndAttributesNode); break; case XamlNodeType.KeyElementStart: XamlKeyElementStartNode xamlKeyElementStartNode = (XamlKeyElementStartNode) xamlNode; WriteKeyElementStart(xamlKeyElementStartNode); break; case XamlNodeType.KeyElementEnd: XamlKeyElementEndNode xamlKeyElementEndNode = (XamlKeyElementEndNode) xamlNode; WriteKeyElementEnd(xamlKeyElementEndNode); break; case XamlNodeType.ConstructorParametersEnd: XamlConstructorParametersEndNode xamlConstructorParametersEndNode = (XamlConstructorParametersEndNode) xamlNode; WriteConstructorParametersEnd(xamlConstructorParametersEndNode); break; case XamlNodeType.ConstructorParametersStart: XamlConstructorParametersStartNode xamlConstructorParametersStartNode = (XamlConstructorParametersStartNode) xamlNode; WriteConstructorParametersStart(xamlConstructorParametersStartNode); break; case XamlNodeType.ContentProperty: XamlContentPropertyNode xamlContentPropertyNode = (XamlContentPropertyNode)xamlNode; WriteContentProperty(xamlContentPropertyNode); break; #if PBTCOMPILER case XamlNodeType.ConstructorParameterType: XamlConstructorParameterTypeNode xamlConstructorParameterTypeNode = (XamlConstructorParameterTypeNode)xamlNode; WriteConstructorParameterType(xamlConstructorParameterTypeNode); break; #endif default: Debug.Assert(false,"Unknown Xaml Token."); break; } } #endregion // PublicMethods #region Virtuals ////// Called when parsing begins /// public virtual void WriteDocumentStart(XamlDocumentStartNode XamlDocumentStartNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteDocumentStart(XamlDocumentStartNode); } } ////// Called when parsing ends /// public virtual void WriteDocumentEnd(XamlDocumentEndNode xamlEndDocumentNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteDocumentEnd(xamlEndDocumentNode); } } ////// Write Start of an Element, which is a tag of the form / public virtual void WriteElementStart(XamlElementStartNode xamlElementStartNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteElementStart(xamlElementStartNode); } } ////// /// Write start of an unknown tag /// public virtual void WriteUnknownTagStart(XamlUnknownTagStartNode xamlUnknownTagStartNode) { // The default action for unknown tags is throw an exception. ThrowException(SRID.ParserUnknownTag , xamlUnknownTagStartNode.Value, xamlUnknownTagStartNode.XmlNamespace, xamlUnknownTagStartNode.LineNumber, xamlUnknownTagStartNode.LinePosition); } ////// Write end of an unknown tag /// public virtual void WriteUnknownTagEnd(XamlUnknownTagEndNode xamlUnknownTagEndNode) { // The default action for unknown tags is throw an exception. This should never // get here unless there is a coding error, since it would first hit // WriteUnknownTagStart ThrowException(SRID.ParserUnknownTag , "???", xamlUnknownTagEndNode.LineNumber, xamlUnknownTagEndNode.LinePosition); } ////// Write End Element /// public virtual void WriteElementEnd(XamlElementEndNode xamlElementEndNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteElementEnd(xamlElementEndNode); } } ////// Called when parsing hits literal content. /// public virtual void WriteLiteralContent(XamlLiteralContentNode xamlLiteralContentNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteLiteralContent(xamlLiteralContentNode); } } ////// Write Start Complex Property, where the tag is of the /// form / public virtual void WritePropertyComplexStart( XamlPropertyComplexStartNode xamlPropertyComplexStartNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WritePropertyComplexStart(xamlPropertyComplexStartNode); } } ////// /// Write End Complex Property /// public virtual void WritePropertyComplexEnd( XamlPropertyComplexEndNode xamlPropertyComplexEndNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WritePropertyComplexEnd(xamlPropertyComplexEndNode); } } ////// Write Start element for a dictionary key section. /// public virtual void WriteKeyElementStart( XamlElementStartNode xamlKeyElementStartNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteKeyElementStart(xamlKeyElementStartNode); } } ////// Write End element for a dictionary key section /// public virtual void WriteKeyElementEnd( XamlElementEndNode xamlKeyElementEndNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteKeyElementEnd(xamlKeyElementEndNode); } } ////// Write unknown attribute /// public virtual void WriteUnknownAttribute(XamlUnknownAttributeNode xamlUnknownAttributeNode) { // The default action for unknown attributes is throw an exception. ThrowException(SRID.ParserUnknownAttribute , xamlUnknownAttributeNode.Name, xamlUnknownAttributeNode.XmlNamespace, xamlUnknownAttributeNode.LineNumber, xamlUnknownAttributeNode.LinePosition); } ////// Write a Property, which has the form in markup of property="value". /// ////// Note that for DependencyProperties, the assemblyName, TypeFullName, PropIdName /// refer to DependencyProperty field /// that the property was found on. This may be different from the ownerType /// of the propId if the property was registered as an alias so if the /// callback is persisting we want to persist the information that the propId /// was found on in case the alias is a private or internal field. /// public virtual void WriteProperty(XamlPropertyNode xamlPropertyNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteProperty(xamlPropertyNode); } } internal void WriteBaseProperty(XamlPropertyNode xamlPropertyNode) { if (BamlRecordWriter != null) { BamlRecordWriter.BaseWriteProperty(xamlPropertyNode); } } ////// Write a Property, which has the form in markup of property="value". /// ////// Note that for DependencyProperties, the assemblyName, TypeFullName, PropIdName /// refer to DependencyProperty field /// that the property was found on. This may be different from the ownerType /// of the propId if the property was registered as an alias so if the /// callback is persisting we want to persist the information that the propId /// was found on in case the alias is a private or internal field. /// public virtual void WritePropertyWithType(XamlPropertyWithTypeNode xamlPropertyNode) { if (BamlRecordWriter != null) { if (xamlPropertyNode.ValueElementType == null) { ThrowException(SRID.ParserNoType, xamlPropertyNode.ValueTypeFullName, xamlPropertyNode.LineNumber, xamlPropertyNode.LinePosition); } BamlRecordWriter.WritePropertyWithType(xamlPropertyNode); } } public virtual void WritePropertyWithExtension(XamlPropertyWithExtensionNode xamlPropertyWithExtensionNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WritePropertyWithExtension(xamlPropertyWithExtensionNode); } } #if !PBTCOMPILER ////// Write out the routed event. /// public virtual void WriteRoutedEvent(XamlRoutedEventNode xamlRoutedEventNode) { // Parser currently doesn't support hooking up Events directly from // XAML so throw an exception. In the compile case this method // is overriden. if (null == ParserHooks) { ThrowException(SRID.ParserNoEvents, xamlRoutedEventNode.LineNumber, xamlRoutedEventNode.LinePosition); } else if (BamlRecordWriter != null) { BamlRecordWriter.WriteRoutedEvent(xamlRoutedEventNode); } } #endif ////// Write out Text, currently don't keep track if originally CData or Text /// public virtual void WriteText(XamlTextNode xamlTextNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteText(xamlTextNode); } } ////// Write a new namespacePrefix to NamespaceURI map /// public virtual void WriteNamespacePrefix(XamlXmlnsPropertyNode xamlXmlnsPropertyNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteNamespacePrefix(xamlXmlnsPropertyNode); } } ////// Xml - Clr namespace mapping /// public virtual void WritePIMapping(XamlPIMappingNode xamlPIMappingNode) { // The only case when the assembly name can be empty is when there is a local assembly // specified in the Mapping PI, but the compiler extension should have resolved it by // now. So if we are still seeing an empty string here that means we in the pure xaml // parsing scenario and should throw. if (xamlPIMappingNode.AssemblyName.Length == 0) { ThrowException(SRID.ParserMapPIMissingKey, xamlPIMappingNode.LineNumber, xamlPIMappingNode.LinePosition); } if (BamlRecordWriter != null) { BamlRecordWriter.WritePIMapping(xamlPIMappingNode); } } ////// Write out the Clr event. /// public virtual void WriteClrEvent(XamlClrEventNode xamlClrEventNode) { // Parser currently doesn't support hooking up Events directly from // XAML so throw an exception. In the compile case this method // is overriden. if (null == ParserHooks) { ThrowException(SRID.ParserNoEvents, xamlClrEventNode.LineNumber, xamlClrEventNode.LinePosition); } else if (BamlRecordWriter != null) { BamlRecordWriter.WriteClrEvent(xamlClrEventNode); } } ////// Write Property Array Start /// public virtual void WritePropertyArrayStart(XamlPropertyArrayStartNode xamlPropertyArrayStartNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WritePropertyArrayStart(xamlPropertyArrayStartNode); } } ////// Write Property Array End /// public virtual void WritePropertyArrayEnd(XamlPropertyArrayEndNode xamlPropertyArrayEndNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WritePropertyArrayEnd(xamlPropertyArrayEndNode); } } ////// Write Property IList Start /// public virtual void WritePropertyIListStart(XamlPropertyIListStartNode xamlPropertyIListStartNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WritePropertyIListStart(xamlPropertyIListStartNode); } } ////// Write Property IList End /// public virtual void WritePropertyIListEnd(XamlPropertyIListEndNode xamlPropertyIListEndNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WritePropertyIListEnd(xamlPropertyIListEndNode); } } ////// Write Property IDictionary Start /// public virtual void WritePropertyIDictionaryStart(XamlPropertyIDictionaryStartNode xamlPropertyIDictionaryStartNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WritePropertyIDictionaryStart(xamlPropertyIDictionaryStartNode); } } ////// Write Property IDictionary End /// public virtual void WritePropertyIDictionaryEnd(XamlPropertyIDictionaryEndNode xamlPropertyIDictionaryEndNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WritePropertyIDictionaryEnd(xamlPropertyIDictionaryEndNode); } } ////// WriteEndAttributes occurs after the last attribute (property, complex property or /// def record) is written. Note that if there are none of the above, then WriteEndAttributes /// is not called for a normal start tag. /// public virtual void WriteEndAttributes(XamlEndAttributesNode xamlEndAttributesNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteEndAttributes(xamlEndAttributesNode); } } ////// WriteDefTag occurs when a x:Whatever tag is encountered. /// Superclasses must interprete this since the base class doesn't understand /// any of them. /// public virtual void WriteDefTag(XamlDefTagNode xamlDefTagNode) { ThrowException(SRID.ParserDefTag, xamlDefTagNode.Value, xamlDefTagNode.LineNumber, xamlDefTagNode.LinePosition); } ////// Write out a key to a dictionary that has been resolved at compile or parse /// time to a Type object. /// public virtual void WriteDefAttributeKeyType(XamlDefAttributeKeyTypeNode xamlDefNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteDefAttributeKeyType(xamlDefNode); } } ////// WriteDefAttribute when attributes of the form x:Whatever are encountered /// public virtual void WriteDefAttribute(XamlDefAttributeNode xamlDefAttributeNode) { string attributeValue = xamlDefAttributeNode.Value; // There are several known def attributes, and these are checked for // correctness by running the known type converters. switch(xamlDefAttributeNode.Name) { case XamlReaderHelper.DefinitionSynchronousMode: if (BamlRecordWriter != null) { #if PBTCOMPILER if (xamlDefAttributeNode.Value == "Async") { ThrowException(SRID.ParserNoBamlAsync, "Async", xamlDefAttributeNode.LineNumber, xamlDefAttributeNode.LinePosition); } #else BamlRecordWriter.SetParseMode( xamlDefAttributeNode.Value == "Async" ? XamlParseMode.Asynchronous : XamlParseMode.Synchronous); #endif } break; case XamlReaderHelper.DefinitionAsyncRecords: // Update the AsyncRecords and don't store this as a def attribute #if PBTCOMPILER ThrowException(SRID.ParserNoBamlAsync, xamlDefAttributeNode.Name, xamlDefAttributeNode.LineNumber, xamlDefAttributeNode.LinePosition); #else if (BamlRecordWriter != null) { int maxAsyncRecords = int.Parse(attributeValue, System.Windows.Markup.TypeConverterHelper.EnglishUSCulture); BamlRecordWriter.SetMaxAsyncRecords(maxAsyncRecords); } #endif break; case XamlReaderHelper.DefinitionShared: Boolean.Parse(attributeValue); // For validation only. if (BamlRecordWriter != null) { BamlRecordWriter.WriteDefAttribute(xamlDefAttributeNode); } break; case XamlReaderHelper.DefinitionUid: case XamlReaderHelper.DefinitionRuntimeName: //Error if x:Uid or x:Name are markup extensions if (MarkupExtensionParser.LooksLikeAMarkupExtension(attributeValue)) { string message = SR.Get(SRID.ParserBadUidOrNameME, attributeValue); message += " "; message += SR.Get(SRID.ParserLineAndOffset, xamlDefAttributeNode.LineNumber.ToString(CultureInfo.CurrentCulture), xamlDefAttributeNode.LinePosition.ToString(CultureInfo.CurrentCulture)); XamlParseException parseException = new XamlParseException(message, xamlDefAttributeNode.LineNumber, xamlDefAttributeNode.LinePosition); throw parseException; } if (BamlRecordWriter != null) { BamlRecordWriter.WriteDefAttribute(xamlDefAttributeNode); } break; case XamlReaderHelper.DefinitionName: if (BamlRecordWriter != null) { BamlRecordWriter.WriteDefAttribute(xamlDefAttributeNode); } break; default: string errorID; #if !PBTCOMPILER if (xamlDefAttributeNode.Name == CLASS || xamlDefAttributeNode.Name == SUBCLASS || xamlDefAttributeNode.Name == TYPEARGUMENTS) { errorID = SRID.ParserUnknownDefAttributeCompiler; } else { #endif errorID = SRID.ParserUnknownDefAttribute; #if !PBTCOMPILER } #endif ThrowException(errorID, xamlDefAttributeNode.Name, xamlDefAttributeNode.LineNumber, xamlDefAttributeNode.LinePosition); break; } } ////// Write attributes of the form PresentationOptions:Whatever to Baml /// public virtual void WritePresentationOptionsAttribute(XamlPresentationOptionsAttributeNode xamlPresentationOptionsAttributeNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WritePresentationOptionsAttribute(xamlPresentationOptionsAttributeNode); } } ////// Write the start of a constructor parameter section /// public virtual void WriteConstructorParametersStart(XamlConstructorParametersStartNode xamlConstructorParametersStartNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteConstructorParametersStart(xamlConstructorParametersStartNode); } } public virtual void WriteContentProperty(XamlContentPropertyNode xamlContentPropertyNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteContentProperty(xamlContentPropertyNode); } } #if PBTCOMPILER ////// Write the constructor parameter record where the parameter is a compile time /// resolved Type object. /// public virtual void WriteConstructorParameterType( XamlConstructorParameterTypeNode xamlConstructorParameterTypeNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteConstructorParameterType(xamlConstructorParameterTypeNode); } } #endif ////// Write the end of a constructor parameter section /// public virtual void WriteConstructorParametersEnd(XamlConstructorParametersEndNode xamlConstructorParametersEndNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteConstructorParametersEnd(xamlConstructorParametersEndNode); } } ////// Can be used by ac to return the type of the element if a class attribute is /// present. If want to override default Type because of class= attribute can do so here. /// Should leave the XmlReader positioned at the Element so if read attributes /// to determine type need to call XmlReader.MoveToElement() /// public virtual bool GetElementType( XmlReader reader, string localName, string namespaceUri, ref string assemblyName, ref string typeFullName, ref Type baseType, ref Type serializerType) { bool result = false; assemblyName = string.Empty; typeFullName = string.Empty; serializerType = null; baseType = null; // if no namespaceURI or local name don't bother if (null == namespaceUri || null == localName) { return false; } TypeAndSerializer typeAndSerializer = XamlTypeMapper.GetTypeAndSerializer(namespaceUri, localName, null); if (typeAndSerializer != null && typeAndSerializer.ObjectType != null) { serializerType = typeAndSerializer.SerializerType; baseType = typeAndSerializer.ObjectType; typeFullName = baseType.FullName; assemblyName = baseType.Assembly.FullName; result = true; Debug.Assert(null != assemblyName, "assembly name returned from GetBaseElement is null"); Debug.Assert(null != typeFullName, "Type name returned from GetBaseElement is null"); } return result; } #endregion Virtuals #if PBTCOMPILER ////// Write a Connector Id for compiler. /// protected internal void WriteConnectionId(Int32 connectionId) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteConnectionId(connectionId); } } #endif ////// A def attribute was encountered. Perform synchonous mode checking /// prior to calling the virtual that may be overridden. /// void WriteDefAttributeCore(XamlDefAttributeNode xamlDefAttributeNode) { string attributeValue = xamlDefAttributeNode.Value; switch(xamlDefAttributeNode.Name) { case XamlReaderHelper.DefinitionSynchronousMode: XamlParseMode documentParseMode = XamlParseMode.Synchronous; if (attributeValue.Equals("Async")) { documentParseMode = XamlParseMode.Asynchronous; } else if (attributeValue.Equals("[....]")) { documentParseMode = XamlParseMode.Synchronous; } else { ThrowException(SRID.ParserBadSyncMode, xamlDefAttributeNode.LineNumber, xamlDefAttributeNode.LinePosition ); } // if we haven't initialized the the parseMode yet set it if (XamlParseMode == XamlParseMode.Uninitialized) { // todo: for now hardcode the string. when finalized // should add a TypeConverter. XamlParseMode = documentParseMode; } break; default: break; } WriteDefAttribute(xamlDefAttributeNode); } #region Methods // virtuals to override the default implementation. used by the compiler // for internal virtuals review why not public as the others? // Used when an exception is thrown.The default action is to shutdown the parser // and throw the exception. internal virtual void ParseError(XamlParseException e) { } ////// Called when the parse was cancelled by the user. /// internal virtual void ParseCancelled() { } ////// called when the parse has been completed successfully. /// internal virtual void ParseCompleted() { } ////// Default parsing is to synchronously read all the xaml nodes /// until done. /// internal virtual void _Parse() { ReadXaml(false /* want to parse the entire thing */); } ////// If there are ParserHooks, call it with the current xamlNode and perform /// as directed by the callback. /// private void SetParserAction(XamlNode xamlNode) { // if no ParserHooks then process as normal if (null == ParserHooks) { ParserAction = ParserAction.Normal; return; } // if ParserHooks want to skip the current node and its children, // check for end of scope where it asked to be skipped. if (ParserAction == ParserAction.Skip) { if (xamlNode.Depth <= SkipActionDepthCount && xamlNode.TokenType == SkipActionToken) { // We found the end token at the correct depth. Reset the depth count // so that in the next call we won't skip calling the ParserHooks. Don't // reset the ParserAction since we want to skip this end token. SkipActionDepthCount = -1; SkipActionToken = XamlNodeType.Unknown; return; } else if (SkipActionDepthCount >= 0) { return; } } // If we get to here, the ParserHooks want to be called. ParserAction = ParserHooks.LoadNode(xamlNode); // if the ParserHooks want to skip the current node and its children then // set the callback depth so that we'll know when to start processing again. if (ParserAction == ParserAction.Skip) { // For tokens with no scope (eg = attributes), don't set the depth so // that we will only skip once Debug.Assert(SkipActionDepthCount == -1); int tokenIndex = ((IList)XamlNode.ScopeStartTokens).IndexOf(xamlNode.TokenType); if (tokenIndex != -1) { SkipActionDepthCount = xamlNode.Depth; SkipActionToken = XamlNode.ScopeEndTokens[tokenIndex]; } } } // helper method called to throw an exception. // todo: update exception with lineNumbers from Node. internal static void ThrowException(string id,int lineNumber,int linePosition) { string message = SR.Get(id); ThrowExceptionWithLine(message, lineNumber, linePosition); } // helper method called to throw an exception. internal static void ThrowException(string id,string value,int lineNumber,int linePosition) { string message = SR.Get(id, value); ThrowExceptionWithLine(message, lineNumber, linePosition); } // helper method called to throw an exception. internal static void ThrowException(string id,string value1, string value2, int lineNumber,int linePosition) { string message = SR.Get(id, value1, value2); ThrowExceptionWithLine(message, lineNumber, linePosition); } internal static void ThrowException(string id, string value1, string value2, string value3, int lineNumber, int linePosition) { string message = SR.Get(id, value1, value2, value3); ThrowExceptionWithLine(message, lineNumber, linePosition); } #if PBTCOMPILER internal static void ThrowException(string id, string value1, string value2, string value3, string value4, int lineNumber, int linePosition) { string message = SR.Get(id, value1, value2, value3, value4); ThrowExceptionWithLine(message, lineNumber, linePosition); } #endif private static void ThrowExceptionWithLine(string message, int lineNumber, int linePosition) { message += " "; message += SR.Get(SRID.ParserLineAndOffset, lineNumber.ToString(CultureInfo.CurrentCulture), linePosition.ToString(CultureInfo.CurrentCulture)); XamlParseException parseException = new XamlParseException(message, lineNumber, linePosition); #if !PBTCOMPILER if (TraceMarkup.IsEnabled) { TraceMarkup.TraceActivityItem(TraceMarkup.ThrowException, parseException); } #endif throw parseException; } // Return true if the passed namespace is known, meaning that it maps // to a set of assemblies and clr namespaces internal bool IsXmlNamespaceSupported(string xmlNamespace, out string newXmlNamespace) { newXmlNamespace = null; if (xmlNamespace.StartsWith(XamlReaderHelper.MappingProtocol, StringComparison.Ordinal)) { return true; } else if (xmlNamespace == XamlReaderHelper.PresentationOptionsNamespaceURI) { // PresentationOptions is expected to be marked as 'ignorable' in most Xaml // so that other Xaml parsers don't have to interpret it, but this parser // does handle it to support it's Freeze attribute. return true; } else { return XamlTypeMapper.IsXmlNamespaceKnown(xmlNamespace, out newXmlNamespace) || TokenReader.IsXmlDataIsland(); } } #endregion Methods #region Properties ////// TokenReader that is being used. /// internal XamlReaderHelper TokenReader { get { return _xamlTokenReader; } set { _xamlTokenReader = value; } } ////// ParserHooks implementation that any parse time callbacks /// should be called on. /// internal ParserHooks ParserHooks { get { return _parserHooks; } set { _parserHooks = value; } } // Set the depth count for how deep we are within // a ParserAction.Skip reference. int SkipActionDepthCount { get { return _skipActionDepthCount; } set { _skipActionDepthCount = value; } } // Set and get the token to watch for when skipping a // section of a xaml file XamlNodeType SkipActionToken { get { return _skipActionToken; } set { _skipActionToken = value; } } // set the operation mode of the parser as determined // by attached ParserHooks ParserAction ParserAction { get { return _parserAction; } set { _parserAction = value; } } ////// Instance of the XamlTypeMapper /// internal XamlTypeMapper XamlTypeMapper { get { return _parserContext.XamlTypeMapper; } } ////// Instance of the BamlMapTable /// internal BamlMapTable MapTable { get { return _parserContext.MapTable; } } ////// BamlRecordWriter being used by the Parser /// public BamlRecordWriter BamlRecordWriter { get { return _bamlWriter; } set { Debug.Assert(null == _bamlWriter || null == value, "XamlParser already had a bamlWriter"); _bamlWriter = value; } } ////// ParseMode the Parser is in. /// internal XamlParseMode XamlParseMode { get { return _xamlParseMode; } set { _xamlParseMode = value; } } ////// Parser context /// internal ParserContext ParserContext { get { return _parserContext; } set { _parserContext = value; } } internal virtual bool CanResolveLocalAssemblies() { return false; } #if !PBTCOMPILER ////// Stream manager that controls reader and writer streams. This may be a simple /// circular record stream for [....] parsing, or a larger memory stream for async. /// It is up to the TreeBuilder to set this up, but it is held here to facilitate /// sharing of the stream by different subparsers. /// internal ReadWriteStreamManager StreamManager { get { return _streamManager; } set { _streamManager = value; } } #endif // Used to determine if strict or loose parsing rules should be enforced. The TokenReader // does some validations that are difficult for the XamlParser to do and in strict parsing // mode the TokenReader should throw exceptions of standard Xaml rules are violated. internal virtual bool StrictParsing { get { return true; } } #endregion Properties #region Data // private Data XamlReaderHelper _xamlTokenReader; ParserContext _parserContext; // todo, need this for the XamlTypeMapper/resolver. XamlParseMode _xamlParseMode; BamlRecordWriter _bamlWriter; // ParserHooks related ParserHooks _parserHooks; ParserAction _parserAction = ParserAction.Normal; int _skipActionDepthCount = -1; // skip mode depth count. XamlNodeType _skipActionToken = XamlNodeType.Unknown; static private string [] _predefinedNamespaces = new string [3] { XamlReaderHelper.DefinitionNamespaceURI, XamlReaderHelper.DefaultNamespaceURI, XamlReaderHelper.DefinitionMetroNamespaceURI }; #if !PBTCOMPILER ReadWriteStreamManager _streamManager; // These are duplicated from ParserExtension to provide better error messages for // the cases where a compiler directive or attribute was used in a Xaml load // scenario. Keep this in [....] with the constants used in ParserExtension. private const string CLASS = "Class"; private const string SUBCLASS = "SubClass"; private const string TYPEARGUMENTS = "TypeArguments"; #endif #endregion Data } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. /****************************************************************************\ * * File: XamlParser.cs * * Purpose: Class for compiling Xaml. * * History: * 6/06/01: rogerg Created * 5/28/03: peterost Ported to wcp * 10/6/03: peterost Reorganized to remove DP - clr distinction * * Copyright (C) 2003 by Microsoft Corporation. All rights reserved. * \***************************************************************************/ using System; using System.Xml; using System.IO; using System.Text; using System.Collections; using System.ComponentModel; using System.Diagnostics; using System.Reflection; using System.Globalization; using System.Security.Permissions; using MS.Utility; using System.Runtime.InteropServices; using MS.Internal; // Disabling 1634 and 1691: // In order to avoid generating warnings about unknown message numbers and // unknown pragmas when compiling C# source code with the C# compiler, // you need to disable warnings 1634 and 1691. (Presharp Documentation) #pragma warning disable 1634, 1691 #if PBTCOMPILER namespace MS.Internal.Markup #else using System.Windows; namespace System.Windows.Markup #endif { #region enums ////// Parser modes. indicates if the Xaml should be parsed [....] or async. /// currently public so test can set these values. /// internal enum XamlParseMode { ////// Not initialized /// Uninitialized, ////// [....] /// Synchronous, ////// Async /// Asynchronous, } #endregion enums ////// XamlParser class. This class is used internally /// internal class XamlParser { #region Constructors ////// Constructor that takes a stream and creates an XmlCompatibilityReader on it. /// public XamlParser( ParserContext parserContext, BamlRecordWriter bamlWriter, Stream xamlStream, bool multipleRoots) : this(parserContext, bamlWriter, new XmlTextReader(xamlStream, multipleRoots ? XmlNodeType.Element : XmlNodeType.Document, (XmlParserContext)parserContext) ) { } #if !PBTCOMPILER ////// Constructor that takes an XmlReader directly /// public XamlParser( ParserContext parserContext, BamlRecordWriter bamlWriter, XmlReader xmlReader, bool wrapWithMarkupCompatReader) : this(parserContext, bamlWriter) { if (wrapWithMarkupCompatReader) { XmlCompatibilityReader xcr = new XmlCompatibilityReader(xmlReader, new IsXmlNamespaceSupportedCallback(IsXmlNamespaceSupported), _predefinedNamespaces ); xmlReader = xcr; } TokenReader = new XamlReaderHelper(this,parserContext,xmlReader); } #endif protected XamlParser( ParserContext parserContext, BamlRecordWriter bamlWriter, XmlTextReader textReader) : this(parserContext, bamlWriter) { // When the XML 1.0 specification was authored, security was not a top concern, and as a result DTDs have the // unfortunate capability of severe Denial of Service (DoS) attacks, typically through the use of an internal // entity expansion technique. In System.Xml V2.0, in order to provide protection against DTD DoS attacks there // is the capability of turning off DTD parsing through the use of the ProhibitDtd property. textReader.ProhibitDtd = true; XmlCompatibilityReader xcr = new XmlCompatibilityReader(textReader, new IsXmlNamespaceSupportedCallback(IsXmlNamespaceSupported), _predefinedNamespaces ); TokenReader = new XamlReaderHelper(this,parserContext,xcr); } protected XamlParser( ParserContext parserContext, BamlRecordWriter bamlWriter) { _parserContext = parserContext; _bamlWriter = bamlWriter; } // Default constructor to aid in subclassing protected XamlParser() { } #endregion Constructors #region PublicMethods #if !PBTCOMPILER ////// Gets the Parse Mode that is either specified /// in the XAML file or explicitly set with SetParseMode. /// If GetParseMode() or SetParseMode() is not set /// before Parse() is called the mode defaults to synchronous /// ///Current parse mode public XamlParseMode GetParseMode() { // loop until hit end or get a parse mode // this loop relies on ReadXaml to set the ParseMode // mode to a default either by having the attribute set // or setting it after the first tag. bool firstRead = true; while (XamlParseMode == XamlParseMode.Uninitialized && ReadXaml(true)) { // If this is the first record we've read, we should know what // the encoding is on the file since the byte order mark will have // been read. Check to make sure its not UTF-7, since // this isn't supported. if (firstRead) { Encoding encoding = TokenReader.Encoding; if (!(encoding is System.Text.UTF8Encoding) && !(encoding is System.Text.UnicodeEncoding)) { ThrowException(SRID.ParserBadEncoding, 1, 1); } } firstRead = false; } // if still unitialized because there aren't any tags // or we are being loaded with parser hooks then // set it to synchronous if (XamlParseMode == XamlParseMode.Uninitialized || (null != ParserHooks)) { XamlParseMode = XamlParseMode.Synchronous; } return XamlParseMode; } #endif ////// Main method to Parse the XAML. /// When in synchronous mode the entire file is parsed before /// this method returns. /// In asynchronous mode at least the root tag is parsed. This /// is necessary for the way binders currently work. /// public void Parse() { // if parseMode hasn't been set then set it now to synchronous. if (XamlParseMode == XamlParseMode.Uninitialized) { XamlParseMode = XamlParseMode.Synchronous; } _Parse(); } ////// Main function called by the XamlCompiler on a Compile. /// If singleRecordMode is true the Read returns after each item read. /// ///True if more nodes to read // !! Review - now that have separate out into XamlReaderHelper // review if still need all the virtuals or the caller of the TokenReader // can dispatch as they feel appropriate. public bool ReadXaml(bool singleRecordMode) { XamlNode xamlNode = null; bool cleanup = !singleRecordMode; bool done = false; try // What do we do with Exceptions we catch on this thread?. { while (TokenReader.Read(ref xamlNode)) { SetParserAction(xamlNode); if (ParserAction == ParserAction.Normal) { // If processing of the xaml node determines that we are done, // then stop now. This can happen if ProcessXamlNode is // overridden (such as when processing styles) and the parsed // block is finished, but the overall file is not. In that // case exit this parser, but leave everything intact. ProcessXamlNode(xamlNode, ref cleanup, ref done); if (done) { break; } // return here in single record mode since we don't want // to set the parser loop to Done. if (singleRecordMode) { return true; } } } } #if PBTCOMPILER || !STRESS catch (Exception e) { if (CriticalExceptions.IsCriticalException(e)) { throw; } else { if (e is XamlParseException) { throw; } // If the exception was a XamlParse exception on the other // side of a Reflection Invoke, then just pull up the Parse exception. if (e is TargetInvocationException && e.InnerException is XamlParseException) { throw e.InnerException; } int lineNumber = 0; int linePosition = 0; string newMessage = null; if (e is XmlException) { XmlException xmlEx = (XmlException)e; lineNumber = xmlEx.LineNumber; linePosition = xmlEx.LinePosition; newMessage = xmlEx.Message; } else { // generic exception, If have a xamlNode then use the // nodes values for the line Numbers. if (null != xamlNode) { lineNumber = xamlNode.LineNumber; linePosition = xamlNode.LinePosition; } newMessage = e.Message + " " + SR.Get(SRID.ParserLineAndOffset, lineNumber.ToString(CultureInfo.CurrentCulture), linePosition.ToString(CultureInfo.CurrentCulture)); } XamlParseException parseException = new XamlParseException(newMessage, lineNumber, linePosition, e); ParseError(parseException); // Recurse on error cleanup = true; throw parseException; } } #endif finally { // Perform cleanup only if we encountered a non-recoverable error, or // we're finished reading the stream (EndDocument reached in single // record mode, or end of stream reached in multi-record mode) if (cleanup) { // Close the reader, which will close the underlying stream. TokenReader.Close(); } } return false; } ////// Big switch to handle all the records. /// /// Node received from TokenReader to process /// True if end of stream reached and document is /// totally finished and should be closed /// True if done processing and want to exit. Doesn't /// necessarily mean document is finished (see cleanup) internal virtual void ProcessXamlNode( XamlNode xamlNode, ref bool cleanup, ref bool done) { switch(xamlNode.TokenType) { case XamlNodeType.DocumentStart: XamlDocumentStartNode xamlDocumentStartNode = (XamlDocumentStartNode) xamlNode; WriteDocumentStart(xamlDocumentStartNode); break; case XamlNodeType.DocumentEnd: XamlDocumentEndNode xamlEndDocumentNode = (XamlDocumentEndNode) xamlNode; cleanup = true; done = true; WriteDocumentEnd(xamlEndDocumentNode); break; case XamlNodeType.ElementStart: XamlElementStartNode xamlElementNode = (XamlElementStartNode) xamlNode; WriteElementStart(xamlElementNode); break; case XamlNodeType.ElementEnd: XamlElementEndNode xamlEndElementNode = (XamlElementEndNode) xamlNode; WriteElementEnd(xamlEndElementNode); break; case XamlNodeType.UnknownTagStart: XamlUnknownTagStartNode xamlUnknownTagStartNode = (XamlUnknownTagStartNode) xamlNode; WriteUnknownTagStart(xamlUnknownTagStartNode); break; case XamlNodeType.UnknownTagEnd: XamlUnknownTagEndNode xamlUnknownTagEndNode = (XamlUnknownTagEndNode) xamlNode; WriteUnknownTagEnd(xamlUnknownTagEndNode); break; case XamlNodeType.XmlnsProperty: XamlXmlnsPropertyNode xamlXmlnsPropertyNode = (XamlXmlnsPropertyNode) xamlNode; WriteNamespacePrefix(xamlXmlnsPropertyNode); break; case XamlNodeType.Property: XamlPropertyNode xamlPropertyNode = (XamlPropertyNode) xamlNode; if (xamlPropertyNode.AttributeUsage == BamlAttributeUsage.RuntimeName) { _parserContext.XamlTypeMapper.ValidateNames( xamlPropertyNode.Value, xamlPropertyNode.LineNumber, xamlPropertyNode.LinePosition); } WriteProperty(xamlPropertyNode); break; case XamlNodeType.PropertyWithExtension: XamlPropertyWithExtensionNode xamlPropertyWithExtensionNode = (XamlPropertyWithExtensionNode)xamlNode; WritePropertyWithExtension(xamlPropertyWithExtensionNode); break; case XamlNodeType.PropertyWithType: XamlPropertyWithTypeNode xamlPropertyWithTypeNode = (XamlPropertyWithTypeNode) xamlNode; WritePropertyWithType(xamlPropertyWithTypeNode); break; case XamlNodeType.UnknownAttribute: XamlUnknownAttributeNode xamlUnknownAttributeNode = (XamlUnknownAttributeNode) xamlNode; WriteUnknownAttribute(xamlUnknownAttributeNode); break; case XamlNodeType.PropertyComplexStart: XamlPropertyComplexStartNode xamlPropertyComplexStartNode = (XamlPropertyComplexStartNode) xamlNode; WritePropertyComplexStart(xamlPropertyComplexStartNode); break; case XamlNodeType.PropertyComplexEnd: XamlPropertyComplexEndNode xamlPropertyComplexEndNode = (XamlPropertyComplexEndNode) xamlNode; WritePropertyComplexEnd(xamlPropertyComplexEndNode); break; #if !PBTCOMPILER case XamlNodeType.RoutedEvent: XamlRoutedEventNode xamlRoutedEventNode = (XamlRoutedEventNode) xamlNode; WriteRoutedEvent(xamlRoutedEventNode); break; #endif case XamlNodeType.LiteralContent: XamlLiteralContentNode xamlLiteralContentNode = (XamlLiteralContentNode) xamlNode; WriteLiteralContent(xamlLiteralContentNode); break; case XamlNodeType.Text: XamlTextNode xamlTextNode = (XamlTextNode) xamlNode; WriteText(xamlTextNode); break; case XamlNodeType.ClrEvent: XamlClrEventNode xamlClrEventNode = (XamlClrEventNode) xamlNode; WriteClrEvent(xamlClrEventNode); break; case XamlNodeType.PropertyArrayStart: XamlPropertyArrayStartNode xamlPropertyArrayStartNode = (XamlPropertyArrayStartNode) xamlNode; WritePropertyArrayStart(xamlPropertyArrayStartNode); break; case XamlNodeType.PropertyArrayEnd: XamlPropertyArrayEndNode xamlPropertyArrayEndNode = (XamlPropertyArrayEndNode) xamlNode; WritePropertyArrayEnd(xamlPropertyArrayEndNode); break; case XamlNodeType.PropertyIListStart: XamlPropertyIListStartNode xamlPropertyIListStartNode = (XamlPropertyIListStartNode) xamlNode; WritePropertyIListStart(xamlPropertyIListStartNode); break; case XamlNodeType.PropertyIListEnd: XamlPropertyIListEndNode xamlPropertyIListEndNode = (XamlPropertyIListEndNode) xamlNode; WritePropertyIListEnd(xamlPropertyIListEndNode); break; case XamlNodeType.PropertyIDictionaryStart: XamlPropertyIDictionaryStartNode xamlPropertyIDictionaryStartNode = (XamlPropertyIDictionaryStartNode) xamlNode; WritePropertyIDictionaryStart(xamlPropertyIDictionaryStartNode); break; case XamlNodeType.PropertyIDictionaryEnd: XamlPropertyIDictionaryEndNode xamlPropertyIDictionaryEndNode = (XamlPropertyIDictionaryEndNode) xamlNode; WritePropertyIDictionaryEnd(xamlPropertyIDictionaryEndNode); break; case XamlNodeType.DefTag: XamlDefTagNode xamlDefTagNode = (XamlDefTagNode) xamlNode; WriteDefTag(xamlDefTagNode); break; case XamlNodeType.DefKeyTypeAttribute: XamlDefAttributeKeyTypeNode xamlDefAttributeKeyTypeNode = (XamlDefAttributeKeyTypeNode) xamlNode; WriteDefAttributeKeyType(xamlDefAttributeKeyTypeNode); break; case XamlNodeType.DefAttribute: XamlDefAttributeNode xamlDefAttributeNode = (XamlDefAttributeNode) xamlNode; if (xamlDefAttributeNode.AttributeUsage == BamlAttributeUsage.RuntimeName) { _parserContext.XamlTypeMapper.ValidateNames( xamlDefAttributeNode.Value, xamlDefAttributeNode.LineNumber, xamlDefAttributeNode.LinePosition); } WriteDefAttributeCore(xamlDefAttributeNode); break; case XamlNodeType.PresentationOptionsAttribute: XamlPresentationOptionsAttributeNode xamlPresentationOptionsAttributeNode = (XamlPresentationOptionsAttributeNode) xamlNode; WritePresentationOptionsAttribute(xamlPresentationOptionsAttributeNode); break; case XamlNodeType.PIMapping: XamlPIMappingNode xamlPIMappingNode = (XamlPIMappingNode) xamlNode; WritePIMapping(xamlPIMappingNode); break; // The following tokens that are used primarily by the markup compiler case XamlNodeType.EndAttributes: XamlEndAttributesNode xamlEndAttributesNode = (XamlEndAttributesNode) xamlNode; // if first tag and haven't alredy set the ParseMode // set it to synchronous. if (0 == xamlEndAttributesNode.Depth) { if (XamlParseMode == XamlParseMode.Uninitialized) { XamlParseMode = XamlParseMode.Synchronous; } } WriteEndAttributes(xamlEndAttributesNode); break; case XamlNodeType.KeyElementStart: XamlKeyElementStartNode xamlKeyElementStartNode = (XamlKeyElementStartNode) xamlNode; WriteKeyElementStart(xamlKeyElementStartNode); break; case XamlNodeType.KeyElementEnd: XamlKeyElementEndNode xamlKeyElementEndNode = (XamlKeyElementEndNode) xamlNode; WriteKeyElementEnd(xamlKeyElementEndNode); break; case XamlNodeType.ConstructorParametersEnd: XamlConstructorParametersEndNode xamlConstructorParametersEndNode = (XamlConstructorParametersEndNode) xamlNode; WriteConstructorParametersEnd(xamlConstructorParametersEndNode); break; case XamlNodeType.ConstructorParametersStart: XamlConstructorParametersStartNode xamlConstructorParametersStartNode = (XamlConstructorParametersStartNode) xamlNode; WriteConstructorParametersStart(xamlConstructorParametersStartNode); break; case XamlNodeType.ContentProperty: XamlContentPropertyNode xamlContentPropertyNode = (XamlContentPropertyNode)xamlNode; WriteContentProperty(xamlContentPropertyNode); break; #if PBTCOMPILER case XamlNodeType.ConstructorParameterType: XamlConstructorParameterTypeNode xamlConstructorParameterTypeNode = (XamlConstructorParameterTypeNode)xamlNode; WriteConstructorParameterType(xamlConstructorParameterTypeNode); break; #endif default: Debug.Assert(false,"Unknown Xaml Token."); break; } } #endregion // PublicMethods #region Virtuals ////// Called when parsing begins /// public virtual void WriteDocumentStart(XamlDocumentStartNode XamlDocumentStartNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteDocumentStart(XamlDocumentStartNode); } } ////// Called when parsing ends /// public virtual void WriteDocumentEnd(XamlDocumentEndNode xamlEndDocumentNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteDocumentEnd(xamlEndDocumentNode); } } ////// Write Start of an Element, which is a tag of the form / public virtual void WriteElementStart(XamlElementStartNode xamlElementStartNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteElementStart(xamlElementStartNode); } } ////// /// Write start of an unknown tag /// public virtual void WriteUnknownTagStart(XamlUnknownTagStartNode xamlUnknownTagStartNode) { // The default action for unknown tags is throw an exception. ThrowException(SRID.ParserUnknownTag , xamlUnknownTagStartNode.Value, xamlUnknownTagStartNode.XmlNamespace, xamlUnknownTagStartNode.LineNumber, xamlUnknownTagStartNode.LinePosition); } ////// Write end of an unknown tag /// public virtual void WriteUnknownTagEnd(XamlUnknownTagEndNode xamlUnknownTagEndNode) { // The default action for unknown tags is throw an exception. This should never // get here unless there is a coding error, since it would first hit // WriteUnknownTagStart ThrowException(SRID.ParserUnknownTag , "???", xamlUnknownTagEndNode.LineNumber, xamlUnknownTagEndNode.LinePosition); } ////// Write End Element /// public virtual void WriteElementEnd(XamlElementEndNode xamlElementEndNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteElementEnd(xamlElementEndNode); } } ////// Called when parsing hits literal content. /// public virtual void WriteLiteralContent(XamlLiteralContentNode xamlLiteralContentNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteLiteralContent(xamlLiteralContentNode); } } ////// Write Start Complex Property, where the tag is of the /// form / public virtual void WritePropertyComplexStart( XamlPropertyComplexStartNode xamlPropertyComplexStartNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WritePropertyComplexStart(xamlPropertyComplexStartNode); } } ////// /// Write End Complex Property /// public virtual void WritePropertyComplexEnd( XamlPropertyComplexEndNode xamlPropertyComplexEndNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WritePropertyComplexEnd(xamlPropertyComplexEndNode); } } ////// Write Start element for a dictionary key section. /// public virtual void WriteKeyElementStart( XamlElementStartNode xamlKeyElementStartNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteKeyElementStart(xamlKeyElementStartNode); } } ////// Write End element for a dictionary key section /// public virtual void WriteKeyElementEnd( XamlElementEndNode xamlKeyElementEndNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteKeyElementEnd(xamlKeyElementEndNode); } } ////// Write unknown attribute /// public virtual void WriteUnknownAttribute(XamlUnknownAttributeNode xamlUnknownAttributeNode) { // The default action for unknown attributes is throw an exception. ThrowException(SRID.ParserUnknownAttribute , xamlUnknownAttributeNode.Name, xamlUnknownAttributeNode.XmlNamespace, xamlUnknownAttributeNode.LineNumber, xamlUnknownAttributeNode.LinePosition); } ////// Write a Property, which has the form in markup of property="value". /// ////// Note that for DependencyProperties, the assemblyName, TypeFullName, PropIdName /// refer to DependencyProperty field /// that the property was found on. This may be different from the ownerType /// of the propId if the property was registered as an alias so if the /// callback is persisting we want to persist the information that the propId /// was found on in case the alias is a private or internal field. /// public virtual void WriteProperty(XamlPropertyNode xamlPropertyNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteProperty(xamlPropertyNode); } } internal void WriteBaseProperty(XamlPropertyNode xamlPropertyNode) { if (BamlRecordWriter != null) { BamlRecordWriter.BaseWriteProperty(xamlPropertyNode); } } ////// Write a Property, which has the form in markup of property="value". /// ////// Note that for DependencyProperties, the assemblyName, TypeFullName, PropIdName /// refer to DependencyProperty field /// that the property was found on. This may be different from the ownerType /// of the propId if the property was registered as an alias so if the /// callback is persisting we want to persist the information that the propId /// was found on in case the alias is a private or internal field. /// public virtual void WritePropertyWithType(XamlPropertyWithTypeNode xamlPropertyNode) { if (BamlRecordWriter != null) { if (xamlPropertyNode.ValueElementType == null) { ThrowException(SRID.ParserNoType, xamlPropertyNode.ValueTypeFullName, xamlPropertyNode.LineNumber, xamlPropertyNode.LinePosition); } BamlRecordWriter.WritePropertyWithType(xamlPropertyNode); } } public virtual void WritePropertyWithExtension(XamlPropertyWithExtensionNode xamlPropertyWithExtensionNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WritePropertyWithExtension(xamlPropertyWithExtensionNode); } } #if !PBTCOMPILER ////// Write out the routed event. /// public virtual void WriteRoutedEvent(XamlRoutedEventNode xamlRoutedEventNode) { // Parser currently doesn't support hooking up Events directly from // XAML so throw an exception. In the compile case this method // is overriden. if (null == ParserHooks) { ThrowException(SRID.ParserNoEvents, xamlRoutedEventNode.LineNumber, xamlRoutedEventNode.LinePosition); } else if (BamlRecordWriter != null) { BamlRecordWriter.WriteRoutedEvent(xamlRoutedEventNode); } } #endif ////// Write out Text, currently don't keep track if originally CData or Text /// public virtual void WriteText(XamlTextNode xamlTextNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteText(xamlTextNode); } } ////// Write a new namespacePrefix to NamespaceURI map /// public virtual void WriteNamespacePrefix(XamlXmlnsPropertyNode xamlXmlnsPropertyNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteNamespacePrefix(xamlXmlnsPropertyNode); } } ////// Xml - Clr namespace mapping /// public virtual void WritePIMapping(XamlPIMappingNode xamlPIMappingNode) { // The only case when the assembly name can be empty is when there is a local assembly // specified in the Mapping PI, but the compiler extension should have resolved it by // now. So if we are still seeing an empty string here that means we in the pure xaml // parsing scenario and should throw. if (xamlPIMappingNode.AssemblyName.Length == 0) { ThrowException(SRID.ParserMapPIMissingKey, xamlPIMappingNode.LineNumber, xamlPIMappingNode.LinePosition); } if (BamlRecordWriter != null) { BamlRecordWriter.WritePIMapping(xamlPIMappingNode); } } ////// Write out the Clr event. /// public virtual void WriteClrEvent(XamlClrEventNode xamlClrEventNode) { // Parser currently doesn't support hooking up Events directly from // XAML so throw an exception. In the compile case this method // is overriden. if (null == ParserHooks) { ThrowException(SRID.ParserNoEvents, xamlClrEventNode.LineNumber, xamlClrEventNode.LinePosition); } else if (BamlRecordWriter != null) { BamlRecordWriter.WriteClrEvent(xamlClrEventNode); } } ////// Write Property Array Start /// public virtual void WritePropertyArrayStart(XamlPropertyArrayStartNode xamlPropertyArrayStartNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WritePropertyArrayStart(xamlPropertyArrayStartNode); } } ////// Write Property Array End /// public virtual void WritePropertyArrayEnd(XamlPropertyArrayEndNode xamlPropertyArrayEndNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WritePropertyArrayEnd(xamlPropertyArrayEndNode); } } ////// Write Property IList Start /// public virtual void WritePropertyIListStart(XamlPropertyIListStartNode xamlPropertyIListStartNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WritePropertyIListStart(xamlPropertyIListStartNode); } } ////// Write Property IList End /// public virtual void WritePropertyIListEnd(XamlPropertyIListEndNode xamlPropertyIListEndNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WritePropertyIListEnd(xamlPropertyIListEndNode); } } ////// Write Property IDictionary Start /// public virtual void WritePropertyIDictionaryStart(XamlPropertyIDictionaryStartNode xamlPropertyIDictionaryStartNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WritePropertyIDictionaryStart(xamlPropertyIDictionaryStartNode); } } ////// Write Property IDictionary End /// public virtual void WritePropertyIDictionaryEnd(XamlPropertyIDictionaryEndNode xamlPropertyIDictionaryEndNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WritePropertyIDictionaryEnd(xamlPropertyIDictionaryEndNode); } } ////// WriteEndAttributes occurs after the last attribute (property, complex property or /// def record) is written. Note that if there are none of the above, then WriteEndAttributes /// is not called for a normal start tag. /// public virtual void WriteEndAttributes(XamlEndAttributesNode xamlEndAttributesNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteEndAttributes(xamlEndAttributesNode); } } ////// WriteDefTag occurs when a x:Whatever tag is encountered. /// Superclasses must interprete this since the base class doesn't understand /// any of them. /// public virtual void WriteDefTag(XamlDefTagNode xamlDefTagNode) { ThrowException(SRID.ParserDefTag, xamlDefTagNode.Value, xamlDefTagNode.LineNumber, xamlDefTagNode.LinePosition); } ////// Write out a key to a dictionary that has been resolved at compile or parse /// time to a Type object. /// public virtual void WriteDefAttributeKeyType(XamlDefAttributeKeyTypeNode xamlDefNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteDefAttributeKeyType(xamlDefNode); } } ////// WriteDefAttribute when attributes of the form x:Whatever are encountered /// public virtual void WriteDefAttribute(XamlDefAttributeNode xamlDefAttributeNode) { string attributeValue = xamlDefAttributeNode.Value; // There are several known def attributes, and these are checked for // correctness by running the known type converters. switch(xamlDefAttributeNode.Name) { case XamlReaderHelper.DefinitionSynchronousMode: if (BamlRecordWriter != null) { #if PBTCOMPILER if (xamlDefAttributeNode.Value == "Async") { ThrowException(SRID.ParserNoBamlAsync, "Async", xamlDefAttributeNode.LineNumber, xamlDefAttributeNode.LinePosition); } #else BamlRecordWriter.SetParseMode( xamlDefAttributeNode.Value == "Async" ? XamlParseMode.Asynchronous : XamlParseMode.Synchronous); #endif } break; case XamlReaderHelper.DefinitionAsyncRecords: // Update the AsyncRecords and don't store this as a def attribute #if PBTCOMPILER ThrowException(SRID.ParserNoBamlAsync, xamlDefAttributeNode.Name, xamlDefAttributeNode.LineNumber, xamlDefAttributeNode.LinePosition); #else if (BamlRecordWriter != null) { int maxAsyncRecords = int.Parse(attributeValue, System.Windows.Markup.TypeConverterHelper.EnglishUSCulture); BamlRecordWriter.SetMaxAsyncRecords(maxAsyncRecords); } #endif break; case XamlReaderHelper.DefinitionShared: Boolean.Parse(attributeValue); // For validation only. if (BamlRecordWriter != null) { BamlRecordWriter.WriteDefAttribute(xamlDefAttributeNode); } break; case XamlReaderHelper.DefinitionUid: case XamlReaderHelper.DefinitionRuntimeName: //Error if x:Uid or x:Name are markup extensions if (MarkupExtensionParser.LooksLikeAMarkupExtension(attributeValue)) { string message = SR.Get(SRID.ParserBadUidOrNameME, attributeValue); message += " "; message += SR.Get(SRID.ParserLineAndOffset, xamlDefAttributeNode.LineNumber.ToString(CultureInfo.CurrentCulture), xamlDefAttributeNode.LinePosition.ToString(CultureInfo.CurrentCulture)); XamlParseException parseException = new XamlParseException(message, xamlDefAttributeNode.LineNumber, xamlDefAttributeNode.LinePosition); throw parseException; } if (BamlRecordWriter != null) { BamlRecordWriter.WriteDefAttribute(xamlDefAttributeNode); } break; case XamlReaderHelper.DefinitionName: if (BamlRecordWriter != null) { BamlRecordWriter.WriteDefAttribute(xamlDefAttributeNode); } break; default: string errorID; #if !PBTCOMPILER if (xamlDefAttributeNode.Name == CLASS || xamlDefAttributeNode.Name == SUBCLASS || xamlDefAttributeNode.Name == TYPEARGUMENTS) { errorID = SRID.ParserUnknownDefAttributeCompiler; } else { #endif errorID = SRID.ParserUnknownDefAttribute; #if !PBTCOMPILER } #endif ThrowException(errorID, xamlDefAttributeNode.Name, xamlDefAttributeNode.LineNumber, xamlDefAttributeNode.LinePosition); break; } } ////// Write attributes of the form PresentationOptions:Whatever to Baml /// public virtual void WritePresentationOptionsAttribute(XamlPresentationOptionsAttributeNode xamlPresentationOptionsAttributeNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WritePresentationOptionsAttribute(xamlPresentationOptionsAttributeNode); } } ////// Write the start of a constructor parameter section /// public virtual void WriteConstructorParametersStart(XamlConstructorParametersStartNode xamlConstructorParametersStartNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteConstructorParametersStart(xamlConstructorParametersStartNode); } } public virtual void WriteContentProperty(XamlContentPropertyNode xamlContentPropertyNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteContentProperty(xamlContentPropertyNode); } } #if PBTCOMPILER ////// Write the constructor parameter record where the parameter is a compile time /// resolved Type object. /// public virtual void WriteConstructorParameterType( XamlConstructorParameterTypeNode xamlConstructorParameterTypeNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteConstructorParameterType(xamlConstructorParameterTypeNode); } } #endif ////// Write the end of a constructor parameter section /// public virtual void WriteConstructorParametersEnd(XamlConstructorParametersEndNode xamlConstructorParametersEndNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteConstructorParametersEnd(xamlConstructorParametersEndNode); } } ////// Can be used by ac to return the type of the element if a class attribute is /// present. If want to override default Type because of class= attribute can do so here. /// Should leave the XmlReader positioned at the Element so if read attributes /// to determine type need to call XmlReader.MoveToElement() /// public virtual bool GetElementType( XmlReader reader, string localName, string namespaceUri, ref string assemblyName, ref string typeFullName, ref Type baseType, ref Type serializerType) { bool result = false; assemblyName = string.Empty; typeFullName = string.Empty; serializerType = null; baseType = null; // if no namespaceURI or local name don't bother if (null == namespaceUri || null == localName) { return false; } TypeAndSerializer typeAndSerializer = XamlTypeMapper.GetTypeAndSerializer(namespaceUri, localName, null); if (typeAndSerializer != null && typeAndSerializer.ObjectType != null) { serializerType = typeAndSerializer.SerializerType; baseType = typeAndSerializer.ObjectType; typeFullName = baseType.FullName; assemblyName = baseType.Assembly.FullName; result = true; Debug.Assert(null != assemblyName, "assembly name returned from GetBaseElement is null"); Debug.Assert(null != typeFullName, "Type name returned from GetBaseElement is null"); } return result; } #endregion Virtuals #if PBTCOMPILER ////// Write a Connector Id for compiler. /// protected internal void WriteConnectionId(Int32 connectionId) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteConnectionId(connectionId); } } #endif ////// A def attribute was encountered. Perform synchonous mode checking /// prior to calling the virtual that may be overridden. /// void WriteDefAttributeCore(XamlDefAttributeNode xamlDefAttributeNode) { string attributeValue = xamlDefAttributeNode.Value; switch(xamlDefAttributeNode.Name) { case XamlReaderHelper.DefinitionSynchronousMode: XamlParseMode documentParseMode = XamlParseMode.Synchronous; if (attributeValue.Equals("Async")) { documentParseMode = XamlParseMode.Asynchronous; } else if (attributeValue.Equals("[....]")) { documentParseMode = XamlParseMode.Synchronous; } else { ThrowException(SRID.ParserBadSyncMode, xamlDefAttributeNode.LineNumber, xamlDefAttributeNode.LinePosition ); } // if we haven't initialized the the parseMode yet set it if (XamlParseMode == XamlParseMode.Uninitialized) { // todo: for now hardcode the string. when finalized // should add a TypeConverter. XamlParseMode = documentParseMode; } break; default: break; } WriteDefAttribute(xamlDefAttributeNode); } #region Methods // virtuals to override the default implementation. used by the compiler // for internal virtuals review why not public as the others? // Used when an exception is thrown.The default action is to shutdown the parser // and throw the exception. internal virtual void ParseError(XamlParseException e) { } ////// Called when the parse was cancelled by the user. /// internal virtual void ParseCancelled() { } ////// called when the parse has been completed successfully. /// internal virtual void ParseCompleted() { } ////// Default parsing is to synchronously read all the xaml nodes /// until done. /// internal virtual void _Parse() { ReadXaml(false /* want to parse the entire thing */); } ////// If there are ParserHooks, call it with the current xamlNode and perform /// as directed by the callback. /// private void SetParserAction(XamlNode xamlNode) { // if no ParserHooks then process as normal if (null == ParserHooks) { ParserAction = ParserAction.Normal; return; } // if ParserHooks want to skip the current node and its children, // check for end of scope where it asked to be skipped. if (ParserAction == ParserAction.Skip) { if (xamlNode.Depth <= SkipActionDepthCount && xamlNode.TokenType == SkipActionToken) { // We found the end token at the correct depth. Reset the depth count // so that in the next call we won't skip calling the ParserHooks. Don't // reset the ParserAction since we want to skip this end token. SkipActionDepthCount = -1; SkipActionToken = XamlNodeType.Unknown; return; } else if (SkipActionDepthCount >= 0) { return; } } // If we get to here, the ParserHooks want to be called. ParserAction = ParserHooks.LoadNode(xamlNode); // if the ParserHooks want to skip the current node and its children then // set the callback depth so that we'll know when to start processing again. if (ParserAction == ParserAction.Skip) { // For tokens with no scope (eg = attributes), don't set the depth so // that we will only skip once Debug.Assert(SkipActionDepthCount == -1); int tokenIndex = ((IList)XamlNode.ScopeStartTokens).IndexOf(xamlNode.TokenType); if (tokenIndex != -1) { SkipActionDepthCount = xamlNode.Depth; SkipActionToken = XamlNode.ScopeEndTokens[tokenIndex]; } } } // helper method called to throw an exception. // todo: update exception with lineNumbers from Node. internal static void ThrowException(string id,int lineNumber,int linePosition) { string message = SR.Get(id); ThrowExceptionWithLine(message, lineNumber, linePosition); } // helper method called to throw an exception. internal static void ThrowException(string id,string value,int lineNumber,int linePosition) { string message = SR.Get(id, value); ThrowExceptionWithLine(message, lineNumber, linePosition); } // helper method called to throw an exception. internal static void ThrowException(string id,string value1, string value2, int lineNumber,int linePosition) { string message = SR.Get(id, value1, value2); ThrowExceptionWithLine(message, lineNumber, linePosition); } internal static void ThrowException(string id, string value1, string value2, string value3, int lineNumber, int linePosition) { string message = SR.Get(id, value1, value2, value3); ThrowExceptionWithLine(message, lineNumber, linePosition); } #if PBTCOMPILER internal static void ThrowException(string id, string value1, string value2, string value3, string value4, int lineNumber, int linePosition) { string message = SR.Get(id, value1, value2, value3, value4); ThrowExceptionWithLine(message, lineNumber, linePosition); } #endif private static void ThrowExceptionWithLine(string message, int lineNumber, int linePosition) { message += " "; message += SR.Get(SRID.ParserLineAndOffset, lineNumber.ToString(CultureInfo.CurrentCulture), linePosition.ToString(CultureInfo.CurrentCulture)); XamlParseException parseException = new XamlParseException(message, lineNumber, linePosition); #if !PBTCOMPILER if (TraceMarkup.IsEnabled) { TraceMarkup.TraceActivityItem(TraceMarkup.ThrowException, parseException); } #endif throw parseException; } // Return true if the passed namespace is known, meaning that it maps // to a set of assemblies and clr namespaces internal bool IsXmlNamespaceSupported(string xmlNamespace, out string newXmlNamespace) { newXmlNamespace = null; if (xmlNamespace.StartsWith(XamlReaderHelper.MappingProtocol, StringComparison.Ordinal)) { return true; } else if (xmlNamespace == XamlReaderHelper.PresentationOptionsNamespaceURI) { // PresentationOptions is expected to be marked as 'ignorable' in most Xaml // so that other Xaml parsers don't have to interpret it, but this parser // does handle it to support it's Freeze attribute. return true; } else { return XamlTypeMapper.IsXmlNamespaceKnown(xmlNamespace, out newXmlNamespace) || TokenReader.IsXmlDataIsland(); } } #endregion Methods #region Properties ////// TokenReader that is being used. /// internal XamlReaderHelper TokenReader { get { return _xamlTokenReader; } set { _xamlTokenReader = value; } } ////// ParserHooks implementation that any parse time callbacks /// should be called on. /// internal ParserHooks ParserHooks { get { return _parserHooks; } set { _parserHooks = value; } } // Set the depth count for how deep we are within // a ParserAction.Skip reference. int SkipActionDepthCount { get { return _skipActionDepthCount; } set { _skipActionDepthCount = value; } } // Set and get the token to watch for when skipping a // section of a xaml file XamlNodeType SkipActionToken { get { return _skipActionToken; } set { _skipActionToken = value; } } // set the operation mode of the parser as determined // by attached ParserHooks ParserAction ParserAction { get { return _parserAction; } set { _parserAction = value; } } ////// Instance of the XamlTypeMapper /// internal XamlTypeMapper XamlTypeMapper { get { return _parserContext.XamlTypeMapper; } } ////// Instance of the BamlMapTable /// internal BamlMapTable MapTable { get { return _parserContext.MapTable; } } ////// BamlRecordWriter being used by the Parser /// public BamlRecordWriter BamlRecordWriter { get { return _bamlWriter; } set { Debug.Assert(null == _bamlWriter || null == value, "XamlParser already had a bamlWriter"); _bamlWriter = value; } } ////// ParseMode the Parser is in. /// internal XamlParseMode XamlParseMode { get { return _xamlParseMode; } set { _xamlParseMode = value; } } ////// Parser context /// internal ParserContext ParserContext { get { return _parserContext; } set { _parserContext = value; } } internal virtual bool CanResolveLocalAssemblies() { return false; } #if !PBTCOMPILER ////// Stream manager that controls reader and writer streams. This may be a simple /// circular record stream for [....] parsing, or a larger memory stream for async. /// It is up to the TreeBuilder to set this up, but it is held here to facilitate /// sharing of the stream by different subparsers. /// internal ReadWriteStreamManager StreamManager { get { return _streamManager; } set { _streamManager = value; } } #endif // Used to determine if strict or loose parsing rules should be enforced. The TokenReader // does some validations that are difficult for the XamlParser to do and in strict parsing // mode the TokenReader should throw exceptions of standard Xaml rules are violated. internal virtual bool StrictParsing { get { return true; } } #endregion Properties #region Data // private Data XamlReaderHelper _xamlTokenReader; ParserContext _parserContext; // todo, need this for the XamlTypeMapper/resolver. XamlParseMode _xamlParseMode; BamlRecordWriter _bamlWriter; // ParserHooks related ParserHooks _parserHooks; ParserAction _parserAction = ParserAction.Normal; int _skipActionDepthCount = -1; // skip mode depth count. XamlNodeType _skipActionToken = XamlNodeType.Unknown; static private string [] _predefinedNamespaces = new string [3] { XamlReaderHelper.DefinitionNamespaceURI, XamlReaderHelper.DefaultNamespaceURI, XamlReaderHelper.DefinitionMetroNamespaceURI }; #if !PBTCOMPILER ReadWriteStreamManager _streamManager; // These are duplicated from ParserExtension to provide better error messages for // the cases where a compiler directive or attribute was used in a Xaml load // scenario. Keep this in [....] with the constants used in ParserExtension. private const string CLASS = "Class"; private const string SUBCLASS = "SubClass"; private const string TYPEARGUMENTS = "TypeArguments"; #endif #endregion Data } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DateTimeOffsetStorage.cs
- MetafileHeaderWmf.cs
- MasterPageCodeDomTreeGenerator.cs
- TemplateApplicationHelper.cs
- DrawListViewColumnHeaderEventArgs.cs
- WhitespaceRuleLookup.cs
- ControlDesigner.cs
- ProxyGenerationError.cs
- IPGlobalProperties.cs
- DescendantQuery.cs
- ClientTargetCollection.cs
- SystemColorTracker.cs
- Buffer.cs
- UserThread.cs
- TreeNodeBinding.cs
- Vector3dCollection.cs
- WorkerRequest.cs
- MD5.cs
- SafeMemoryMappedFileHandle.cs
- ReferentialConstraint.cs
- ConnectionStringSettings.cs
- sitestring.cs
- WebPartEventArgs.cs
- Menu.cs
- FacetValues.cs
- AuthenticationConfig.cs
- ArcSegment.cs
- ControllableStoryboardAction.cs
- EventLogStatus.cs
- StylusSystemGestureEventArgs.cs
- ResourceDescriptionAttribute.cs
- DefinitionBase.cs
- WebControlParameterProxy.cs
- _DigestClient.cs
- CssClassPropertyAttribute.cs
- XmlSchemaSimpleTypeRestriction.cs
- Assembly.cs
- RC2.cs
- ZipIOZip64EndOfCentralDirectoryBlock.cs
- LogLogRecordEnumerator.cs
- ScrollItemPattern.cs
- AccessDataSourceView.cs
- GenericEnumConverter.cs
- TextChangedEventArgs.cs
- EmptyEnumerator.cs
- XmlDataSourceView.cs
- _HeaderInfoTable.cs
- XMLDiffLoader.cs
- _HTTPDateParse.cs
- WebZone.cs
- WebPageTraceListener.cs
- RemotingConfigParser.cs
- TreeNodeStyle.cs
- TextServicesContext.cs
- DBDataPermissionAttribute.cs
- EncoderNLS.cs
- SafeEventLogReadHandle.cs
- ExclusiveTcpTransportManager.cs
- PointConverter.cs
- HostingEnvironment.cs
- AssociationEndMember.cs
- HostingEnvironmentSection.cs
- SerializationFieldInfo.cs
- AuthorizationRuleCollection.cs
- SqlNotificationEventArgs.cs
- EditorPartCollection.cs
- DetailsViewDesigner.cs
- Helper.cs
- CollectionViewGroupRoot.cs
- DefaultParameterValueAttribute.cs
- IsolatedStoragePermission.cs
- GenericAuthenticationEventArgs.cs
- LayoutTableCell.cs
- AttributeConverter.cs
- ToolboxItemFilterAttribute.cs
- SoapTransportImporter.cs
- CapabilitiesAssignment.cs
- ObjectQuery_EntitySqlExtensions.cs
- XslAstAnalyzer.cs
- BinarySerializer.cs
- PasswordDeriveBytes.cs
- EntitySetDataBindingList.cs
- UpdateTranslator.cs
- HttpHandlerActionCollection.cs
- SingleSelectRootGridEntry.cs
- ArrangedElementCollection.cs
- RedirectionProxy.cs
- SafeFileHandle.cs
- CorrelationQuery.cs
- WebSysDefaultValueAttribute.cs
- ToolZoneDesigner.cs
- ExpressionBinding.cs
- TraceContextEventArgs.cs
- SessionStateItemCollection.cs
- GradientBrush.cs
- RoleGroupCollection.cs
- EventLogEntryCollection.cs
- Msec.cs
- CodeTypeDeclaration.cs
- TransformerInfo.cs