public string DecompileBaml(MemoryStream bamlCode, string containingAssemblyFile) { bamlCode.Position = 0; TextWriter w = new StringWriter(); Assembly assembly = Assembly.LoadFile(containingAssemblyFile); Baml2006Reader reader = new Baml2006Reader(bamlCode, new XamlReaderSettings() { ValuesMustBeString = true, LocalAssembly = assembly }); XamlXmlWriter writer = new XamlXmlWriter(new XmlTextWriter(w) { Formatting = Formatting.Indented }, reader.SchemaContext); while (reader.Read()) { switch (reader.NodeType) { case XamlNodeType.None: break; case XamlNodeType.StartObject: writer.WriteStartObject(reader.Type); break; case XamlNodeType.GetObject: writer.WriteGetObject(); break; case XamlNodeType.EndObject: writer.WriteEndObject(); break; case XamlNodeType.StartMember: writer.WriteStartMember(reader.Member); break; case XamlNodeType.EndMember: writer.WriteEndMember(); break; case XamlNodeType.Value: // requires XamlReaderSettings.ValuesMustBeString = true to work properly writer.WriteValue(reader.Value); break; case XamlNodeType.NamespaceDeclaration: writer.WriteNamespace(reader.Namespace); break; default: throw new Exception("Invalid value for XamlNodeType"); } } return w.ToString(); }
public string DecompileBaml(MemoryStream bamlCode, string containingAssemblyFile) { bamlCode.Position = 0; TextWriter w = new StringWriter(); Assembly assembly = Assembly.LoadFile(containingAssemblyFile); Baml2006Reader reader = new Baml2006Reader(bamlCode, new XamlReaderSettings() { ValuesMustBeString = true, LocalAssembly = assembly }); XDocument doc = new XDocument(); XamlXmlWriter writer = new XamlXmlWriter(doc.CreateWriter(), reader.SchemaContext); while (reader.Read()) { switch (reader.NodeType) { case XamlNodeType.None: break; case XamlNodeType.StartObject: writer.WriteStartObject(reader.Type); break; case XamlNodeType.GetObject: writer.WriteGetObject(); break; case XamlNodeType.EndObject: writer.WriteEndObject(); break; case XamlNodeType.StartMember: writer.WriteStartMember(reader.Member); break; case XamlNodeType.EndMember: writer.WriteEndMember(); break; case XamlNodeType.Value: // requires XamlReaderSettings.ValuesMustBeString = true to work properly writer.WriteValue(reader.Value); break; case XamlNodeType.NamespaceDeclaration: writer.WriteNamespace(reader.Namespace); break; default: throw new Exception("Invalid value for XamlNodeType"); } } writer.Close(); // Fix namespace references string suffixToRemove = ";assembly=" + assembly.GetName().Name; foreach (XAttribute attrib in doc.Root.Attributes()) { if (attrib.Name.Namespace == XNamespace.Xmlns) { if (attrib.Value.EndsWith(suffixToRemove, StringComparison.Ordinal)) { string newNamespace = attrib.Value.Substring(0, attrib.Value.Length - suffixToRemove.Length); ChangeXmlNamespace(doc, attrib.Value, newNamespace); attrib.Value = newNamespace; } } } // Convert x:Key into an attribute where possible XName xKey = XName.Get("Key", "http://schemas.microsoft.com/winfx/2006/xaml"); foreach (XElement e in doc.Descendants(xKey).ToList()) { if (e.Nodes().Count() != 1) continue; XText text = e.Nodes().Single() as XText; if (text != null) { e.Parent.SetAttributeValue(xKey, text.Value); e.Remove(); } } return doc.ToString(); }