// when Read hits EndObject or EndMember void ExitObject() { if (this.depth <= this.inXClassDepth) { this.inXClassDepth = 0; } this.depth--; this.frontLoadedDirectives = false; if (this.depth == 1) { this.builderStack = null; } else if (this.depth == 0) { // we're about to write out the last tag. Dump our accrued properties // as no more property values are forthcoming. if (this.bufferedProperties != null) { this.bufferedProperties.FlushTo(this.nodeQueue, this); } } }
// pull on our inner reader, map the results as necessary, and pump // mapped results into the streaming node reader that we're offering up. // return true if we need to keep pumping (because we've buffered some nodes on the side) bool ProcessCurrentNode() { bool processedNode = false; this.namespaceTable.ManageNamespace(this.innerReader); switch (this.innerReader.NodeType) { case XamlNodeType.StartMember: XamlMember currentMember = this.innerReader.Member; // find out if the member is a default value for one of // our declared properties. If it is, then we have a complex case // where we need to: // 1) read the nodes into a side list // 2) interleave these nodes with the DynamicActivityProperty nodes // since they need to appear as DynamicActivityProperty.Value // 3) right before we hit the last node, we'll dump the side node-lists // reflecting a zipped up representation of the Properties if (IsXClassName(currentMember.DeclaringType)) { if (this.bufferedProperties == null) { this.bufferedProperties = new BufferedPropertyList(this); } this.bufferedProperties.BufferDefaultValue(currentMember.Name, this.activityPropertyValue, this.innerReader, this.innerReaderLineInfo); return true; // output cursor didn't move forward } else if (this.frontLoadedDirectives && currentMember == XamlLanguage.FactoryMethod) { DisableRewrite(); return false; } else { this.depth++; if (this.depth == 2) { if (currentMember.DeclaringType == this.activityXamlType || currentMember.DeclaringType == this.baseActivityXamlType) { // Rewrite "<Activity.XXX>" to "<DynamicActivity.XXX>" XamlMember member = this.activityReplacementXamlType.GetMember(currentMember.Name); if (member == null) { throw FxTrace.Exception.AsError(CreateXamlException(SR.MemberNotSupportedByActivityXamlServices(currentMember.Name), this.innerReaderLineInfo)); } this.nodeQueue.Writer.WriteStartMember(member, this.innerReaderLineInfo); if (member.Name == "Constraints") { WriteWrappedMember(true); processedNode = true; return true; } processedNode = true; // if we're in ActivityBuilder.Implementation, start buffering nodes if (this.isBuilder && member.Name == "Implementation") { this.builderStack = new BuilderStack(this); } } else if (currentMember == XamlLanguage.Class) { this.inXClassDepth = this.depth; // Rewrite x:Class to DynamicActivity.Name this.nodeQueue.Writer.WriteStartMember(this.activityReplacementXamlType.GetMember("Name"), this.innerReaderLineInfo); processedNode = true; } else if (currentMember == XamlLanguage.Members) { // Rewrite "<x:Members>" to "<DynamicActivity.Properties>" if (this.bufferedProperties == null) { this.bufferedProperties = new BufferedPropertyList(this); } this.bufferedProperties.BufferDefinitions(this); this.depth--; return true; // output cursor didn't move forward } else if (currentMember == XamlLanguage.ClassAttributes) { // Rewrite x:ClassAttributes to DynamicActivity.Attributes this.nodeQueue.Writer.WriteStartMember(this.activityReplacementXamlType.GetMember("Attributes"), this.innerReaderLineInfo); // x:ClassAttributes directive has no following GetObject, but Attributes does since it's not a directive WriteWrappedMember(false); processedNode = true; return true; } } } break; case XamlNodeType.StartObject: { EnterObject(); if (this.depth == 1) { // see if we're deserializing an Activity if (this.innerReader.Type.UnderlyingType == typeof(Activity)) { // Rewrite "<Activity>" to "<DynamicActivity>" this.activityXamlType = this.innerReader.Type; if (this.isBuilder) { this.activityReplacementXamlType = SchemaContext.GetXamlType(typeof(ActivityBuilder)); } else { this.activityReplacementXamlType = SchemaContext.GetXamlType(typeof(DynamicActivity)); } } // or an Activity<TResult> else if (this.innerReader.Type.IsGeneric && this.innerReader.Type.UnderlyingType != null && this.innerReader.Type.UnderlyingType.GetGenericTypeDefinition() == typeof(Activity<>)) { // Rewrite "<Activity typeArgument=T>" to "<DynamicActivity typeArgument=T>" this.activityXamlType = this.innerReader.Type; Type activityType = this.innerReader.Type.TypeArguments[0].UnderlyingType; Type activityReplacementGenericType; if (this.isBuilder) { activityReplacementGenericType = typeof(ActivityBuilder<>).MakeGenericType(activityType); } else { activityReplacementGenericType = typeof(DynamicActivity<>).MakeGenericType(activityType); } this.activityReplacementXamlType = SchemaContext.GetXamlType(activityReplacementGenericType); } // otherwise disable rewriting so that we're a pass through else { DisableRewrite(); return false; } this.nodeQueue.Writer.WriteStartObject(this.activityReplacementXamlType, this.innerReaderLineInfo); processedNode = true; } } break; case XamlNodeType.GetObject: EnterObject(); break; case XamlNodeType.EndObject: case XamlNodeType.EndMember: ExitObject(); break; case XamlNodeType.Value: if (this.inXClassDepth >= this.depth && this.xClassName == null) { string fullName = (string)this.innerReader.Value; string xClassNamespace = ""; string xClassName = fullName; int nameStartIndex = fullName.LastIndexOf('.'); if (nameStartIndex > 0) { xClassNamespace = fullName.Substring(0, nameStartIndex); xClassName = fullName.Substring(nameStartIndex + 1); } this.xClassName = new XamlTypeName(xClassNamespace, xClassName); } break; } if (!processedNode) { if (this.builderStack != null) { bool writeNode = true; this.builderStack.ProcessNode(this.innerReader, this.innerReaderLineInfo, this.nodeQueue.Writer, out writeNode); if (!writeNode) { this.innerReader.Read(); return true; } } this.nodeQueue.Writer.WriteNode(this.innerReader, this.innerReaderLineInfo); } return false; }