private void CompileContentProperty(ElementContextStackData context)
        {
            int depth = XmlReader.Depth;
            object contentPropertyInfo = context.ContentPropertyInfo;
            Type propertyDeclaringType = XamlTypeMapper.GetDeclaringType(contentPropertyInfo);
            string propertyAssemblyName = propertyDeclaringType.Assembly.FullName;
            string contentPropertyName = context.ContentPropertyName;

            WriteContentProperty(depth, LineNumber, LinePosition, contentPropertyInfo,
                propertyAssemblyName, propertyDeclaringType.FullName, contentPropertyName);
        }
        private void ResolveContentProperty(string contentPropertyName,
                        Type elementType,
                        string namespaceUri,
                        out string propertyAssemblyName,
                        out object propertyDynamicObject,
                        out Type propertyDeclaringType)
        {
            propertyDynamicObject = null;
            propertyAssemblyName = null;
            propertyDeclaringType = null;

            string propertyTypeFullName = null;
            string propertyDynamicObjectName = null;
            Type propertyBaseType = null;

            // Push a frame for GetPropertyComplex()
            ElementContextStackData elementContextStackData = new ElementContextStackData();
            elementContextStackData.ContextType = ElementContextType.Default;
            ElementContextStack.Push(elementContextStackData);

            bool resolved = GetPropertyComplex(elementType.Name, contentPropertyName, namespaceUri,
                ref propertyAssemblyName,      ref propertyTypeFullName,
                ref propertyDynamicObjectName, ref propertyBaseType,
                ref propertyDynamicObject,     ref propertyDeclaringType);

            ElementContextStack.Pop();

            PropertyInfo pi = propertyDynamicObject as PropertyInfo;

            if (!resolved  /* resolution was unsuccessful */
                ||
                pi == null /* resolved object is not a PropertyInfo */)
            {
                ThrowException(SRID.ParserInvalidContentPropertyAttribute, elementType.FullName,
                    contentPropertyName);
            }

            // check to see if content property is accessible\allowed.
            bool allowed = true;
            if (typeof(IList).IsAssignableFrom(pi.PropertyType))
            {
                allowed = XamlTypeMapper.IsAllowedPropertyGet(pi);
            }
            else if (!IsAssignableToIXmlSerializable(pi.PropertyType))
            {
                allowed = XamlTypeMapper.IsAllowedPropertySet(pi);
            }

            // We will resolve the content Property even for IAddChild using types
            // because we need to match IAddChild Content against Content Property "content"
            // at "check duplicate property usage" time.
            // This is made more difficult because of the IAddChild using types (FixedDocument.Pages
            // DocumentSequence.References) are non-IList collections and thus fail the above
            // allowed check.   But it is OK if we are IAddChild because we won't be using the
            // content property anyway.
            if (!allowed && !BamlRecordManager.TreatAsIAddChild(elementType))
            {
                ThrowException(SRID.ParserCantSetContentProperty, contentPropertyName, elementType.Name);
            }
        }
 // ContentPropertySeesAProperty drives the "Contiguous Content" state machine.
 // on property elements move from state During to state After.
 private void ContentPropertySeesAProperty(ElementContextStackData context)
 {
     if (context.ContentParserState == ParsingContent.During)
     {
         context.ContentParserState = ParsingContent.After;
     }
 }
 // VerifyContentPropertySeesAnElement drives the "Contiguous Content" state machine.
 // All Content must be together with no property elements interruping the
 //  list of content elements.
 // This method will throw on interrupted groups of content.  But in the
 //  case of a Content Property that is not a collection it will return
 //  false to the caller; who is in a position to generate a better error.
 private bool VerifyContentPropertySeesAnElement(ElementContextStackData context)
 {
     // If this is the first element then all is good.
     if (context.ContentParserState == ParsingContent.Before)
     {
         context.ContentParserState = ParsingContent.During;
         return true;
     }
     // if this is the 2nd or later elements the Property must be a container
     else if (context.ContentParserState == ParsingContent.During)
     {
         return context.IsContentPropertyACollection;
     }
     // if we are done added content then adding content is now an error.
     else  // if (context.ContentParserState == ParsingContent.During)
     {
         ThrowException(SRID.ParserContentMustBeContiguous);
         return false;  // compiler demands this.
     }
 }
        //Used to determine if a container can hold more than one child.
        private static bool IsACollection(ElementContextStackData context)
        {
            //If there is a CPA, check if the property's type is a collection
            if (context.IsContentPropertySet)
            {
                Type contentPropertyType = XamlTypeMapper.GetPropertyType(context.ContentPropertyInfo);
                return IsACollection(contentPropertyType);
            }
            else
            //otherwise, look at the contexttype and decide with that data.
            {
                ElementContextType contextType = context.ContextType;
                switch (contextType)
                {

                    //These can all hold multiple items
                    case ElementContextType.PropertyIList:
                    case ElementContextType.PropertyIDictionary:
                    case ElementContextType.PropertyArray:

                    //In markup compile pass 1, we need to pretend that it is a collection...since it may be.
                    //If it is not a collection, when pass 2 happens, the right answer will be provided.
                    case ElementContextType.Unknown:
                        return true;

                    //Otherwise, look at the contextData's type to see if it is a collection or supports IAddChildInternal
                    case ElementContextType.Default:
                    case ElementContextType.PropertyComplex:
                        Type t = ((Type)context.ContextData);
                        if (IsACollection(t) || BamlRecordManager.TreatAsIAddChild(t))
                            return true;
                        break;
                }
                return false;
            }
        }
        /// <summary>
        /// Called by ReadXAML when an Element node is encountered
        /// </summary>
        /// <returns>true if parsing should continue</returns>
        bool ReadElementNode()
        {
            // element can be of the following types
            //  - Standard DependencyObjects to put in the Tree
            //  - <x: tags or other tags used by the Compiler
            //  - .net objects

            // Get the IsEmptyElement value before getting attributes because
            // attribute loop will reset the value.
            bool isEmptyElement = XmlReader.IsEmptyElement;
            bool endTagHasBeenRead = false;

            // Put an item on the context stack for this element.  The ContextType
            // may be modified by the call to CompileBamlTag.
            ElementContextStackData elementContextStackData = new ElementContextStackData();
            elementContextStackData.IsEmptyElement = isEmptyElement;

            // If we have a parent stack, this context is the same as the parent
            // by default.
            if (null == CurrentContext)
            {
                elementContextStackData.ContextType = ElementContextType.Default;
            }
            else
            {
                if(ShouldImplyContentProperty())
                {
                    ElementContextStackData CpaStackData = new ElementContextStackData();
                    CpaStackData.ContextType = ElementContextType.Default;
                    ElementContextStack.Push(CpaStackData);
                    ParserContext.PushScope();

                    CompileContentProperty(ParentContext);

                    ElementContextStack.Pop();
                    ParserContext.PopScope();
                }
                elementContextStackData.ContextType = CurrentContext.ContextType;
            }

            ElementContextStack.Push(elementContextStackData);
            ParserContext.PushScope();

            // Compile this tag.
            // Handler should return with  the TextReader position either at the
            // current Node if plan on reading children or at the End of the Current Node.
            CompileBamlTag(XmlNodeType.Element, ref endTagHasBeenRead);

            // if the Element is empty or the caller read past the endTag then
            // call EndElement so Start and ends are balanced.
            if (isEmptyElement)
            {
                //Review - should only read past the EndTag for literal or x:
                // if read pastEnd tag for something that turns into an element
                // the proper EndElementRecord won't be generated so we should either
                // add the logic to make sure this doesn't happen or not guarantee
                // the endElement.
                if (!endTagHasBeenRead)
                {
                    CompileBamlTag(XmlNodeType.EndElement, ref endTagHasBeenRead);
                    Debug.Assert(false == endTagHasBeenRead, "Read past end tag on end tag");
                }

                // Empty Complex Properties of type Dictionary should be popped now as
                // a start and end element tag will be added making it really non empty.
                // Ideally the parser should recognize this case and not add any implicit
                // start\end elements in this case. If\when that is fixed, this code below
                // can be removed.
                if (CurrentContext != null && CurrentContext.ContextType == ElementContextType.PropertyIDictionary)
                {
                    ElementContextStack.Pop();
                    ParserContext.PopScope();
                }
            }
            else if (endTagHasBeenRead)
            {
                // Note that we should not pop the stack here since that context info
                // might be needed when the empty element's attributes are being processed.
                ElementContextStack.Pop();
                ParserContext.PopScope();
            }

            return true;

        }