Пример #1
0
 /// <summary>
 /// Copy fields from BamlReaderWrapper to the corresponding fields of BamlNodeData.
 /// </summary>
 /// <param name="reader">Source BamlReaderWrapper</param>
 /// <param name="nodeData">Destination nodeData where fields are to be copied.</param>
 private static void PopulateBamlNodeData(BamlReaderWrapper reader, BamlNodeData nodeData)
 {
     nodeData.NodeType                  = reader.NodeType;
     nodeData.AssemblyName              = reader.AssemblyName;
     nodeData.Prefix                    = reader.Prefix;
     nodeData.XmlNamespace              = reader.XmlNamespace;
     nodeData.ClrNamespace              = reader.ClrNamespace;
     nodeData.Name                      = reader.Name;
     nodeData.LocalName                 = reader.LocalName;
     nodeData.Value                     = reader.Value;
     nodeData.IsInjected                = reader.IsInjected;
     nodeData.CreateUsingTypeConverter  = reader.CreateUsingTypeConverter;
     nodeData.TypeConverterAssemblyName = reader.TypeConverterAssemblyName;
     nodeData.TypeConverterName         = reader.TypeConverterName;
     nodeData.AttributeUsage            = reader.AttributeUsage;
 }
Пример #2
0
        /// <summary>
        /// A function that compares the actual field values of a BamlNodeData with those expected,
        /// and throws an exception at the first mis-match.
        /// </summary>
        /// <param name="actualData">Actual data</param>
        /// <param name="expectedData">Expected data</param>
        private static void CompareBamlNodes(BamlNodeData actualData, BamlNodeData expectedData)
        {
            // Compare Name
            if (expectedData.Name != actualData.Name)
            {
                throw new Exception("Field different from expected in Baml node type " + actualData.NodeType + "\n" + " Name (expected): " + expectedData.Name + "\n" + " Name (found): " + actualData.Name);
            }

            // Compare LocalName
            if (expectedData.LocalName != actualData.LocalName)
            {
                throw new Exception("Field different from expected in Baml node type " + actualData.NodeType + "\n" + " LocalName (expected): " + expectedData.LocalName + "\n" + " LocalName (found): " + actualData.LocalName);
            }

            // Compare ClrNamespace
            if (expectedData.ClrNamespace != actualData.ClrNamespace)
            {
                throw new Exception("Field different from expected in Baml node type " + actualData.NodeType + "\n" + " ClrNamespace (expected): " + expectedData.ClrNamespace + "\n" + " ClrNamespace (found): " + actualData.ClrNamespace);
            }

            // Compare XmlNamespace
            if (expectedData.XmlNamespace != actualData.XmlNamespace)
            {
                throw new Exception("Field different from expected in Baml node type " + actualData.NodeType + "\n" + " XmlNamespace (expected): " + expectedData.XmlNamespace + "\n" + " XmlNamespace (found): " + actualData.XmlNamespace);
            }

            // Compare AssemblyName
            if (expectedData.AssemblyName != actualData.AssemblyName)
            {
                throw new Exception("Field different from expected in Baml node type " + actualData.NodeType + "\n" + " AssemblyName (expected): " + expectedData.AssemblyName + "\n" + " AssemblyName (found): " + actualData.AssemblyName);
            }

            // Compare Prefix
            if (expectedData.Prefix != actualData.Prefix)
            {
                throw new Exception("Field different from expected in Baml node type " + actualData.NodeType + "\n" + " Prefix (expected): " + expectedData.Prefix + "\n" + " Prefix (found): " + actualData.Prefix);
            }

            // Compare Value
            if (expectedData.Value != actualData.Value)
            {
                throw new Exception("Field different from expected in Baml node type " + actualData.NodeType + "\n" + " Value (expected): " + expectedData.Value + "\n" + " Value (found): " + actualData.Value);
            }
        }
Пример #3
0
        /// <summary>
        /// Reads an existing BAML using BamlReaderWrapper, allows editing of the contents
        /// and writes the (possibly modified) contents to a new BAML using BamlWriterWrapper.
        ///
        /// After each node is read from the BamlReaderWrapper, it calls the given callback function,
        /// passing the data in the node just read. The callback function can then modify the
        /// data. The callback function is also passed the BamlWriterWrapper, so that it can add
        /// nodes, if it wants.
        ///
        /// The callback function is supposed to return a BamlNodeAction, specifiying
        /// whether the current BAML node should be written to the output BAML file.
        /// By returning BamlNodeAction.Skip, the callback function can specify to delete nodes.
        ///
        /// If the callback function returns BamlNodeAction.Continue, then the (possibly modified)
        /// contents will be written into the new BAML.
        /// </summary>
        /// <param name="bamlIn">Path of the Original BAML</param>
        /// <param name="bamlOut">Path of the BAML to be written</param>
        /// <param name="callback">EditBamlNode callback. Can be null.</param>
        public static void EditBaml(Stream bamlIn, Stream bamlOut, BamlNodeCallback callback)
        {
            BamlReaderWrapper reader = new BamlReaderWrapper(bamlIn);
            BamlWriterWrapper writer = new BamlWriterWrapper(bamlOut);

            // Stack for verifying matching BAML nodes
            Stack        matchingStack = new Stack();
            BamlNodeData expectedData;

            // Default action, in case there is no callback specified.
            BamlNodeAction action = BamlNodeAction.Continue;

            // Go through the input BAML, reading different types of records and
            // writing them to the output BAML
            while (reader.Read())
            {
                // Copy the significant fields from BamlReaderWrapper to BamlNodeData
                // This nodeData can be then passed to a BamlNodeCallback delegate
                BamlNodeData nodeData = new BamlNodeData();
                PopulateBamlNodeData(reader, nodeData);

                // Make another copy for pushing to stack, in case of those nodes
                // which we are checking for node matching
                // We cannot work with the previous copy, since that may be modified by the
                // callback.
                BamlNodeData stackData = new BamlNodeData();
                PopulateBamlNodeData(reader, stackData);

                switch (reader.NodeType)
                {
                case "StartDocument":
                    matchingStack.Push(stackData);
                    if (callback != null)
                    {
                        action = callback(nodeData, writer);
                    }
                    if (BamlNodeAction.Continue == action)
                    {
                        writer.WriteStartDocument();
                    }
                    break;

                case "EndDocument":
                    // Test for matching BAML nodes.
                    // Try to match the data with StartDocument's data
                    if (matchingStack.Count <= 0)
                    {
                        throw new Exception("Unmatched BAML nodes found");
                    }
                    expectedData = matchingStack.Pop() as BamlNodeData;
                    if (expectedData.NodeType != "StartDocument")
                    {
                        throw new Exception("Unmatched BAML nodes found");
                    }
                    CompareBamlNodes(stackData, expectedData);

                    if (callback != null)
                    {
                        action = callback(nodeData, writer);
                    }
                    if (BamlNodeAction.Continue == action)
                    {
                        writer.WriteEndDocument();
                    }
                    break;

                case "StartElement":
                    matchingStack.Push(stackData);
                    if (callback != null)
                    {
                        action = callback(nodeData, writer);
                    }
                    if (BamlNodeAction.Continue == action)
                    {
                        writer.WriteStartElement(nodeData.AssemblyName, nodeData.Name, nodeData.IsInjected, nodeData.CreateUsingTypeConverter);
                    }
                    break;

                case "EndElement":
                    // Test for matching BAML nodes.
                    // Try to match the data with StartElement's data
                    if (matchingStack.Count <= 0)
                    {
                        throw new Exception("Unmatched BAML nodes found");
                    }
                    expectedData = matchingStack.Pop() as BamlNodeData;
                    if (expectedData.NodeType != "StartElement")
                    {
                        throw new Exception("Unmatched BAML nodes found");
                    }
                    CompareBamlNodes(stackData, expectedData);

                    if (callback != null)
                    {
                        action = callback(nodeData, writer);
                    }
                    if (BamlNodeAction.Continue == action)
                    {
                        writer.WriteEndElement();
                    }
                    break;

                case "StartConstructor":
                    matchingStack.Push(stackData);
                    if (callback != null)
                    {
                        action = callback(nodeData, writer);
                    }
                    if (BamlNodeAction.Continue == action)
                    {
                        writer.WriteStartConstructor();
                    }
                    break;

                case "EndConstructor":
                    // Test for matching BAML nodes.
                    // Try to match the data with StartConstructor's data
                    if (matchingStack.Count <= 0)
                    {
                        throw new Exception("Unmatched BAML nodes found");
                    }
                    expectedData = matchingStack.Pop() as BamlNodeData;
                    if (expectedData.NodeType != "StartConstructor")
                    {
                        throw new Exception("Unmatched BAML nodes found");
                    }
                    CompareBamlNodes(stackData, expectedData);

                    if (callback != null)
                    {
                        action = callback(nodeData, writer);
                    }
                    if (BamlNodeAction.Continue == action)
                    {
                        writer.WriteEndConstructor();
                    }
                    break;

                case "StartComplexProperty":
                    matchingStack.Push(stackData);
                    if (callback != null)
                    {
                        action = callback(nodeData, writer);
                    }
                    if (BamlNodeAction.Continue == action)
                    {
                        writer.WriteStartComplexProperty(nodeData.AssemblyName, nodeData.Name.Substring(0, nodeData.Name.LastIndexOf('.')), nodeData.LocalName);
                    }
                    break;

                case "EndComplexProperty":
                    // Test for matching BAML nodes.
                    // Try to match the data with StartComplexProperty's data
                    if (matchingStack.Count <= 0)
                    {
                        throw new Exception("Unmatched BAML nodes found");
                    }
                    expectedData = matchingStack.Pop() as BamlNodeData;
                    if (expectedData.NodeType != "StartComplexProperty")
                    {
                        throw new Exception("Unmatched BAML nodes found");
                    }
                    CompareBamlNodes(stackData, expectedData);

                    if (callback != null)
                    {
                        action = callback(nodeData, writer);
                    }
                    if (BamlNodeAction.Continue == action)
                    {
                        writer.WriteEndComplexProperty();
                    }
                    break;

                case "LiteralContent":
                    if (callback != null)
                    {
                        action = callback(nodeData, writer);
                    }
                    if (BamlNodeAction.Continue == action)
                    {
                        writer.WriteLiteralContent(nodeData.Value);
                    }
                    break;

                case "Text":
                    if (callback != null)
                    {
                        action = callback(nodeData, writer);
                    }
                    if (BamlNodeAction.Continue == action)
                    {
                        writer.WriteText(nodeData.Value, nodeData.TypeConverterAssemblyName, nodeData.TypeConverterName);
                    }
                    break;

                case "RoutedEvent":
                    if (callback != null)
                    {
                        action = callback(nodeData, writer);
                    }
                    if (BamlNodeAction.Continue == action)
                    {
                        writer.WriteRoutedEvent(nodeData.AssemblyName, nodeData.Name.Substring(0, nodeData.Name.LastIndexOf('.')), nodeData.LocalName, nodeData.Value);
                    }
                    break;

                case "Event":
                    if (callback != null)
                    {
                        action = callback(nodeData, writer);
                    }
                    if (BamlNodeAction.Continue == action)
                    {
                        writer.WriteEvent(nodeData.LocalName, nodeData.Value);
                    }
                    break;

                case "IncludeReference":
                    if (callback != null)
                    {
                        action = callback(nodeData, writer);
                    }
                    break;

                case "PIMapping":
                    if (callback != null)
                    {
                        action = callback(nodeData, writer);
                    }
                    if (BamlNodeAction.Continue == action)
                    {
                        writer.WritePIMapping(nodeData.XmlNamespace, nodeData.ClrNamespace, nodeData.AssemblyName);
                    }
                    break;

                default:
                    throw new Exception("Unexpected NodeType read from BamlReaderWrapper");
                }

                // Property nodes are not provided by BamlReaderWrapper when Read() is called
                // We need to go through them separately.
                if (reader.HasProperties)
                {
                    reader.MoveToFirstProperty();
                    do
                    {
                        // This has to be present in this loop, because reader values
                        // keep changing as we move thru the properties
                        PopulateBamlNodeData(reader, nodeData);

                        if (reader.NodeType == "Property")
                        {
                            if (callback != null)
                            {
                                action = callback(nodeData, writer);
                            }
                            if (BamlNodeAction.Continue == action)
                            {
                                writer.WriteProperty(nodeData.AssemblyName, nodeData.Name.Substring(0, nodeData.Name.LastIndexOf('.')), nodeData.LocalName, nodeData.Value, nodeData.AttributeUsage);
                            }
                        }
                        else if (reader.NodeType == "ContentProperty")
                        {
                            if (callback != null)
                            {
                                action = callback(nodeData, writer);
                            }
                            if (BamlNodeAction.Continue == action)
                            {
                                writer.WriteContentProperty(nodeData.AssemblyName, nodeData.Name.Substring(0, nodeData.Name.LastIndexOf('.')), nodeData.LocalName);
                            }
                        }
                        else if (reader.NodeType == "DefAttribute")
                        {
                            if (callback != null)
                            {
                                action = callback(nodeData, writer);
                            }
                            if (BamlNodeAction.Continue == action)
                            {
                                writer.WriteDefAttribute(nodeData.Name, nodeData.Value);
                            }
                        }
                        else if (reader.NodeType == "XmlnsProperty")
                        {
                            if (callback != null)
                            {
                                action = callback(nodeData, writer);
                            }
                            if (BamlNodeAction.Continue == action)
                            {
                                writer.WriteXmlnsProperty(nodeData.LocalName, nodeData.Value);
                            }
                        }
                        else if (reader.NodeType == "ConnectionId")
                        {
                            if (callback != null)
                            {
                                action = callback(nodeData, writer);
                            }
                            if (BamlNodeAction.Continue == action)
                            {
                                writer.WriteConnectionId(Int32.Parse(nodeData.Value));
                            }
                        }
                        else
                        {
                            throw new Exception("Unexpected NodeType read from BamlReaderWrapper while trying to read properties on an element");
                        }
                    } while (reader.MoveToNextProperty());
                }
            }

            // Check that matching stack is empty
            if (matchingStack.Count != 0)
            {
                throw new Exception("Unmatched BAML nodes found");
            }
        }