public override void WriteElementStart(XamlElementStartNode xamlObjectNode) { string classFullName = null; classFullName = _compiler.StartElement(ref _class, _subClass, ref _classModifier, xamlObjectNode.ElementType, string.Empty); // If we have a serializer for this element's type, then use that // serializer rather than doing default serialization. // NOTE: We currently have faith that the serializer will return when // it is done with the subtree and leave everything in the correct // state. We may want to limit how much the called serializer can // read so that it is forced to return at the end of the subtree. if (xamlObjectNode.SerializerType != null) { XamlSerializer serializer; if (xamlObjectNode.SerializerType == typeof(XamlStyleSerializer)) { serializer = new XamlStyleSerializer(ParserHooks); } else if (xamlObjectNode.SerializerType == typeof(XamlTemplateSerializer)) { serializer = new XamlTemplateSerializer(ParserHooks); } else { serializer = Activator.CreateInstance( xamlObjectNode.SerializerType, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance, null, null, null) as XamlSerializer; } if (serializer == null) { ThrowException(SRID.ParserNoSerializer, xamlObjectNode.TypeFullName, xamlObjectNode.LineNumber, xamlObjectNode.LinePosition); } else { serializer.ConvertXamlToBaml(TokenReader, ParserContext, xamlObjectNode, BamlRecordWriter); _compiler.EndElement(_pass2); } } else if (BamlRecordWriter != null) { if (classFullName != null) { bool isRootPublic = _pass2 ? !_isInternalRoot : _compiler.IsRootPublic; Type rootType = isRootPublic ? xamlObjectNode.ElementType : typeof(ParserExtension); XamlElementStartNode xamlRootObjectNode = new XamlElementStartNode( xamlObjectNode.LineNumber, xamlObjectNode.LinePosition, xamlObjectNode.Depth, _compiler.AssemblyName, classFullName, rootType, xamlObjectNode.SerializerType); base.WriteElementStart(xamlRootObjectNode); } else { base.WriteElementStart(xamlObjectNode); } } }
/// <summary> /// Write Start of an Element, which is a tag of the form /<Classname /> /// </summary> /// <remarks> /// For style parsing, determine when it is withing a Trigger or /// MultiTrigger section. This is done for validity checking of /// unknown tags and attributes. /// </remarks> public override void WriteElementStart(XamlElementStartNode xamlElementStartNode) { StyleMode mode = _styleModeStack.Mode; int depth = _styleModeStack.Depth; _setterOrTriggerPropertyInfo = null; bool tagWritten = false; // The very first element encountered within a style block should be the // target type tag, or a Setter. if (mode == StyleMode.Base && depth > 0) { if (KnownTypes.Types[(int)KnownElements.SetterBase].IsAssignableFrom(xamlElementStartNode.ElementType)) { if (_setterPropertyEncountered) { ThrowException(SRID.StyleImpliedAndComplexChildren, xamlElementStartNode.ElementType.Name, XamlStyleSerializer.SettersPropertyName, xamlElementStartNode.LineNumber, xamlElementStartNode.LinePosition); } mode = StyleMode.Setters; _setterElementEncountered = true; } else { ThrowException(SRID.StyleNoTopLevelElement, xamlElementStartNode.ElementType.Name, xamlElementStartNode.LineNumber, xamlElementStartNode.LinePosition); } } else if (mode == StyleMode.TriggerBase && (xamlElementStartNode.ElementType == KnownTypes.Types[(int)KnownElements.Trigger] || xamlElementStartNode.ElementType == KnownTypes.Types[(int)KnownElements.MultiTrigger] || xamlElementStartNode.ElementType == KnownTypes.Types[(int)KnownElements.DataTrigger] || xamlElementStartNode.ElementType == KnownTypes.Types[(int)KnownElements.MultiDataTrigger] || xamlElementStartNode.ElementType == KnownTypes.Types[(int)KnownElements.EventTrigger])) { _inPropertyTriggerDepth = xamlElementStartNode.Depth; } else if (mode == StyleMode.TriggerBase && (KnownTypes.Types[(int)KnownElements.SetterBase].IsAssignableFrom(xamlElementStartNode.ElementType))) { // Just entered the <Setter> section of a Trigger _inSetterDepth = xamlElementStartNode.Depth; } #if PBTCOMPILER else if (mode == StyleMode.TargetTypeProperty && InDeferLoadedSection && depth >= 2 && !_defNameFound) { // We have to treat TargetType="{x:Type SomeType}" as a key in a // resource dictionary, if one is present. This means generating // a series of baml records to use as the key for the defer loaded // body of the Style. if (depth == 2) { base.WriteKeyElementStart(xamlElementStartNode); } else { base.WriteElementStart(xamlElementStartNode); } tagWritten = true; } #endif if (mode == StyleMode.Setters) { if (xamlElementStartNode.ElementType == KnownTypes.Types[(int)KnownElements.EventSetter]) { #if !PBTCOMPILER ThrowException(SRID.StyleNoEventSetters, xamlElementStartNode.LineNumber, xamlElementStartNode.LinePosition); #else _inEventSetter = true; #endif } else if ((depth == 2 && _setterElementEncountered) || (depth == 3 && _setterPropertyEncountered)) { ThrowException(SRID.ParserNoSetterChild, xamlElementStartNode.TypeFullName, xamlElementStartNode.LineNumber, xamlElementStartNode.LinePosition); } } // Handle custom serializers within the style section by creating an instance // of that serializer and handing off control. if (xamlElementStartNode.SerializerType != null && depth > 0) { XamlSerializer serializer; if (xamlElementStartNode.SerializerType == typeof(XamlStyleSerializer)) { #if PBTCOMPILER // reset the event scope so that any other event setters encountered in this // style after the nested Style is done parsing will be added to a new scope _isSameScope = false; #endif serializer = new XamlStyleSerializer(ParserHooks); } else if (xamlElementStartNode.SerializerType == typeof(XamlTemplateSerializer)) { #if PBTCOMPILER // reset the event scope so that any other event setters encountered in this // style after the nested Template is done parsing will be added to a new scope _isSameScope = false; #endif serializer = new XamlTemplateSerializer(ParserHooks); } else { serializer = XamlTypeMapper.CreateInstance(xamlElementStartNode.SerializerType) as XamlSerializer; } if (serializer == null) { ThrowException(SRID.ParserNoSerializer, xamlElementStartNode.TypeFullName, xamlElementStartNode.LineNumber, xamlElementStartNode.LinePosition); } else { // If we're compiling (or otherwise producing baml), convert to baml. // When we don't have a TreeBuilder, we're producing baml. #if !PBTCOMPILER if( TreeBuilder == null ) { #endif serializer.ConvertXamlToBaml(TokenReader, BamlRecordWriter == null ? ParserContext : BamlRecordWriter.ParserContext, xamlElementStartNode, BamlRecordWriter); #if !PBTCOMPILER } else { serializer.ConvertXamlToObject(TokenReader, StreamManager, BamlRecordWriter.ParserContext, xamlElementStartNode, TreeBuilder.RecordReader); } #endif } } else { _styleModeStack.Push(mode); if (!_inEventSetter) { #if PBTCOMPILER // If we DO NOT need a dictionary key, then set the flag that says // a key was already found so that one is not manufactured from // the TargetType property. if (mode == StyleMode.Base && depth == 0) { _defNameFound = !xamlElementStartNode.NeedsDictionaryKey; } #endif if (!tagWritten) { base.WriteElementStart(xamlElementStartNode); } } } }