Browse Source

fix #775 - Invalid BAML namespace decompilation

pull/728/merge
Siegfried Pammer 9 years ago
parent
commit
1604952c3b
  1. 38
      ILSpy.BamlDecompiler/BamlResourceEntryNode.cs
  2. 2
      ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj
  3. 9
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlElement.cs
  4. 402
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs
  5. 36
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlNamespace.cs
  6. 58
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlPIMapping.cs
  7. 31
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlToClrNamespaceMapping.cs
  8. 36
      ILSpy.BamlDecompiler/Tests/BamlTestRunner.cs
  9. 5
      ILSpy.BamlDecompiler/Tests/Cases/Issue775.xaml
  10. 2
      ILSpy.BamlDecompiler/Tests/Cases/MarkupExtension.xaml
  11. 2
      ILSpy.BamlDecompiler/Tests/Cases/SimplePropertyElement.xaml
  12. 3
      ILSpy.BamlDecompiler/Tests/ILSpy.BamlDecompiler.Tests.csproj

38
ILSpy.BamlDecompiler/BamlResourceEntryNode.cs

@ -56,12 +56,13 @@ namespace ILSpy.BamlDecompiler
internal static XDocument LoadIntoDocument(IAssemblyResolver resolver, AssemblyDefinition asm, Stream stream) internal static XDocument LoadIntoDocument(IAssemblyResolver resolver, AssemblyDefinition asm, Stream stream)
{ {
XDocument xamlDocument; XDocument xamlDocument;
using (XmlBamlReader reader = new XmlBamlReader(stream, new CecilTypeResolver(resolver, asm))) using (XmlBamlReader reader = new XmlBamlReader(stream, new CecilTypeResolver(resolver, asm))) {
xamlDocument = XDocument.Load(reader); xamlDocument = XDocument.Load(reader);
ConvertConnectionIds(xamlDocument, asm); ConvertConnectionIds(xamlDocument, asm);
ConvertToEmptyElements(xamlDocument.Root); ConvertToEmptyElements(xamlDocument.Root);
MoveNamespacesToRoot(xamlDocument); MoveNamespacesToRoot(xamlDocument, reader.XmlnsDefinitions);
return xamlDocument; return xamlDocument;
}
} }
static void ConvertConnectionIds(XDocument xamlDocument, AssemblyDefinition asm) static void ConvertConnectionIds(XDocument xamlDocument, AssemblyDefinition asm)
@ -74,12 +75,35 @@ namespace ILSpy.BamlDecompiler
} }
} }
static void MoveNamespacesToRoot(XDocument xamlDocument) class XAttributeComparer : IEqualityComparer<XAttribute>
{
public bool Equals(XAttribute x, XAttribute y)
{
if (ReferenceEquals(x, y))
return true;
if (x == null || y == null)
return false;
return x.ToString() == y.ToString();
}
public int GetHashCode(XAttribute obj)
{
return obj.ToString().GetHashCode();
}
}
static void MoveNamespacesToRoot(XDocument xamlDocument, IEnumerable<XmlNamespace> missingXmlns)
{ {
var additionalXmlns = new List<XAttribute> { var additionalXmlns = new HashSet<XAttribute>(new XAttributeComparer()) {
new XAttribute("xmlns", XmlBamlReader.DefaultWPFNamespace), new XAttribute("xmlns", XmlBamlReader.DefaultWPFNamespace),
new XAttribute(XName.Get("x", XNamespace.Xmlns.NamespaceName), XmlBamlReader.XWPFNamespace) new XAttribute(XName.Get("x", XNamespace.Xmlns.NamespaceName), XmlBamlReader.XWPFNamespace)
}; };
additionalXmlns.AddRange(
missingXmlns
.Where(ns => !string.IsNullOrWhiteSpace(ns.Prefix))
.Select(ns => new XAttribute(XName.Get(ns.Prefix, XNamespace.Xmlns.NamespaceName), ns.Namespace))
);
foreach (var element in xamlDocument.Root.DescendantsAndSelf()) { foreach (var element in xamlDocument.Root.DescendantsAndSelf()) {
if (element.Name.NamespaceName != XmlBamlReader.DefaultWPFNamespace && !additionalXmlns.Any(ka => ka.Value == element.Name.NamespaceName)) { if (element.Name.NamespaceName != XmlBamlReader.DefaultWPFNamespace && !additionalXmlns.Any(ka => ka.Value == element.Name.NamespaceName)) {

2
ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj

@ -112,7 +112,7 @@
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\XmlBamlSimpleProperty.cs" /> <Compile Include="Ricciolo.StylesExplorer.MarkupReflection\XmlBamlSimpleProperty.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\XmlBamlText.cs" /> <Compile Include="Ricciolo.StylesExplorer.MarkupReflection\XmlBamlText.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\XmlNamespace.cs" /> <Compile Include="Ricciolo.StylesExplorer.MarkupReflection\XmlNamespace.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\XmlPIMapping.cs" /> <Compile Include="Ricciolo.StylesExplorer.MarkupReflection\XmlToClrNamespaceMapping.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup />
<ItemGroup> <ItemGroup>

9
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlElement.cs

@ -1,14 +1,13 @@
// Copyright (c) Cristian Civera (cristian@aspitalia.com) // Copyright (c) Cristian Civera (cristian@aspitalia.com)
// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) // This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt)
using System.Collections.Generic;
using System.Xml; using System.Xml;
namespace Ricciolo.StylesExplorer.MarkupReflection namespace Ricciolo.StylesExplorer.MarkupReflection
{ {
class XmlBamlElement : XmlBamlNode class XmlBamlElement : XmlBamlNode
{ {
XmlNamespaceCollection _namespaces = new XmlNamespaceCollection();
public XmlBamlElement() public XmlBamlElement()
{ {
} }
@ -19,11 +18,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
this.Namespaces.AddRange(parent.Namespaces); this.Namespaces.AddRange(parent.Namespaces);
} }
public XmlNamespaceCollection Namespaces { public List<XmlNamespace> Namespaces { get; } = new List<XmlNamespace>();
get { return _namespaces; }
}
public XmlBamlElement Parent { get; private set; } public XmlBamlElement Parent { get; }
public TypeDeclaration TypeDeclaration { get; set; } public TypeDeclaration TypeDeclaration { get; set; }

402
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs

@ -29,7 +29,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
Stack<XmlBamlElement> elements = new Stack<XmlBamlElement>(); Stack<XmlBamlElement> elements = new Stack<XmlBamlElement>();
Stack<XmlBamlElement> readingElements = new Stack<XmlBamlElement>(); Stack<XmlBamlElement> readingElements = new Stack<XmlBamlElement>();
NodesCollection nodes = new NodesCollection(); NodesCollection nodes = new NodesCollection();
List<XmlPIMapping> _mappings = new List<XmlPIMapping>(); List<XmlToClrNamespaceMapping> mappings = new List<XmlToClrNamespaceMapping>();
XmlBamlNode _currentNode; XmlBamlNode _currentNode;
readonly KnownInfo KnownInfo; readonly KnownInfo KnownInfo;
@ -94,15 +94,17 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
readonly XmlNameTable _nameTable = new NameTable(); readonly XmlNameTable _nameTable = new NameTable();
IDictionary<string, string> _rootNamespaces; IDictionary<string, string> _rootNamespaces;
public const string XWPFNamespace = "http://schemas.microsoft.com/winfx/2006/xaml"; public const string XWPFNamespace = XmlToClrNamespaceMapping.XamlNamespace;
public const string DefaultWPFNamespace = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"; public const string DefaultWPFNamespace = XmlToClrNamespaceMapping.PresentationNamespace;
public ISet<XmlNamespace> XmlnsDefinitions { get; } = new HashSet<XmlNamespace>();
public XmlBamlReader(Stream stream, ITypeResolver resolver) public XmlBamlReader(Stream stream, ITypeResolver resolver)
{ {
if (stream == null) if (stream == null)
throw new ArgumentNullException("stream"); throw new ArgumentNullException(nameof(stream));
if (resolver == null) if (resolver == null)
throw new ArgumentNullException("resolver"); throw new ArgumentNullException(nameof(resolver));
_resolver = resolver; _resolver = resolver;
reader = new BamlBinaryReader(stream); reader = new BamlBinaryReader(stream);
@ -111,86 +113,31 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
KnownInfo = new KnownInfo(resolver); KnownInfo = new KnownInfo(resolver);
} }
///<summary>
///When overridden in a derived class, gets the value of the attribute with the specified <see cref="P:System.Xml.XmlReader.Name"></see>.
///</summary>
///
///<returns>
///The value of the specified attribute. If the attribute is not found, null is returned.
///</returns>
///
///<param name="name">The qualified name of the attribute. </param>
public override string GetAttribute(string name) public override string GetAttribute(string name)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
///<summary>
///When overridden in a derived class, gets the value of the attribute with the specified <see cref="P:System.Xml.XmlReader.LocalName"></see> and <see cref="P:System.Xml.XmlReader.NamespaceURI"></see>.
///</summary>
///
///<returns>
///The value of the specified attribute. If the attribute is not found, null is returned. This method does not move the reader.
///</returns>
///
///<param name="namespaceURI">The namespace URI of the attribute. </param>
///<param name="name">The local name of the attribute. </param>
public override string GetAttribute(string name, string namespaceURI) public override string GetAttribute(string name, string namespaceURI)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
///<summary>
///When overridden in a derived class, gets the value of the attribute with the specified index.
///</summary>
///
///<returns>
///The value of the specified attribute. This method does not move the reader.
///</returns>
///
///<param name="i">The index of the attribute. The index is zero-based. (The first attribute has index 0.) </param>
public override string GetAttribute(int i) public override string GetAttribute(int i)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
///<summary>
///When overridden in a derived class, moves to the attribute with the specified <see cref="P:System.Xml.XmlReader.Name"></see>.
///</summary>
///
///<returns>
///true if the attribute is found; otherwise, false. If false, the reader's position does not change.
///</returns>
///
///<param name="name">The qualified name of the attribute. </param>
public override bool MoveToAttribute(string name) public override bool MoveToAttribute(string name)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
///<summary>
///When overridden in a derived class, moves to the attribute with the specified <see cref="P:System.Xml.XmlReader.LocalName"></see> and <see cref="P:System.Xml.XmlReader.NamespaceURI"></see>.
///</summary>
///
///<returns>
///true if the attribute is found; otherwise, false. If false, the reader's position does not change.
///</returns>
///
///<param name="name">The local name of the attribute. </param>
///<param name="ns">The namespace URI of the attribute. </param>
public override bool MoveToAttribute(string name, string ns) public override bool MoveToAttribute(string name, string ns)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
///<summary>
///When overridden in a derived class, moves to the first attribute.
///</summary>
///
///<returns>
///true if an attribute exists (the reader moves to the first attribute); otherwise, false (the position of the reader does not change).
///</returns>
///
public override bool MoveToFirstAttribute() public override bool MoveToFirstAttribute()
{ {
intoAttribute = false; intoAttribute = false;
@ -202,14 +149,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
return false; return false;
} }
///<summary>
///When overridden in a derived class, moves to the next attribute.
///</summary>
///
///<returns>
///true if there is a next attribute; false if there are no more attributes.
///</returns>
///
public override bool MoveToNextAttribute() public override bool MoveToNextAttribute()
{ {
intoAttribute = false; intoAttribute = false;
@ -221,14 +160,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
return false; return false;
} }
///<summary>
///When overridden in a derived class, moves to the element that contains the current attribute node.
///</summary>
///
///<returns>
///true if the reader is positioned on an attribute (the reader moves to the element that owns the attribute); false if the reader is not positioned on an attribute (the position of the reader does not change).
///</returns>
///
public override bool MoveToElement() public override bool MoveToElement()
{ {
while (nodes.Peek() is XmlBamlProperty || nodes.Peek() is XmlBamlSimpleProperty) while (nodes.Peek() is XmlBamlProperty || nodes.Peek() is XmlBamlSimpleProperty)
@ -239,14 +170,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
return true; return true;
} }
///<summary>
///When overridden in a derived class, parses the attribute value into one or more Text, EntityReference, or EndEntity nodes.
///</summary>
///
///<returns>
///true if there are nodes to return.false if the reader is not positioned on an attribute node when the initial call is made or if all the attribute values have been read.An empty attribute, such as, misc="", returns true with a single node with a value of String.Empty.
///</returns>
///
public override bool ReadAttributeValue() public override bool ReadAttributeValue()
{ {
if (!intoAttribute) if (!intoAttribute)
@ -257,15 +180,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
return false; return false;
} }
///<summary>
///When overridden in a derived class, reads the next node from the stream.
///</summary>
///
///<returns>
///true if the next node was read successfully; false if there are no more nodes to read.
///</returns>
///
///<exception cref="T:System.Xml.XmlException">An error occurred while parsing the XML. </exception>
public override bool Read() public override bool Read()
{ {
return ReadInternal(); return ReadInternal();
@ -288,7 +202,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
long position = reader.BaseStream.Position; long position = reader.BaseStream.Position;
ComputeBytesToSkip(); bytesToSkip = ComputeBytesToSkip();
ProcessNext(); ProcessNext();
if (bytesToSkip > 0) if (bytesToSkip > 0)
@ -318,12 +232,13 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
currentType = BamlRecordType.DocumentEnd; currentType = BamlRecordType.DocumentEnd;
else else
currentType = (BamlRecordType)type; currentType = (BamlRecordType)type;
#if DEBUG
if (currentType.ToString().EndsWith("End")) if (currentType.ToString().EndsWith("End", StringComparison.Ordinal))
Debug.Unindent(); Debug.Unindent();
Debug.WriteLine(string.Format("{0} (0x{0:x})", currentType)); Debug.WriteLine(string.Format("{0} (0x{0:x})", currentType));
if (currentType.ToString().EndsWith("Start")) if (currentType.ToString().EndsWith("Start", StringComparison.Ordinal))
Debug.Indent(); Debug.Indent();
#endif
} }
bool SetNextNode() bool SetNextNode()
@ -507,9 +422,8 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
nodes.Enqueue(new XmlBamlText(text)); nodes.Enqueue(new XmlBamlText(text));
} }
void ComputeBytesToSkip() int ComputeBytesToSkip()
{ {
bytesToSkip = 0;
switch (currentType) switch (currentType)
{ {
case BamlRecordType.PropertyWithConverter: case BamlRecordType.PropertyWithConverter:
@ -528,8 +442,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
case BamlRecordType.AttributeInfo: case BamlRecordType.AttributeInfo:
case BamlRecordType.StringInfo: case BamlRecordType.StringInfo:
case BamlRecordType.TypeSerializerInfo: case BamlRecordType.TypeSerializerInfo:
bytesToSkip = reader.ReadCompressedInt32(); return reader.ReadCompressedInt32();
break; default:
return 0;
} }
} }
@ -552,77 +467,44 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
} }
} }
///<summary>
///When overridden in a derived class, changes the <see cref="P:System.Xml.XmlReader.ReadState"></see> to Closed.
///</summary>
///
public override void Close() public override void Close()
{ {
//if (reader != null)
// reader.Close();
reader = null; reader = null;
} }
///<summary>
///When overridden in a derived class, resolves a namespace prefix in the current element's scope.
///</summary>
///
///<returns>
///The namespace URI to which the prefix maps or null if no matching prefix is found.
///</returns>
///
///<param name="prefix">The prefix whose namespace URI you want to resolve. To match the default namespace, pass an empty string. </param>
public override string LookupNamespace(string prefix) public override string LookupNamespace(string prefix)
{ {
if (readingElements.Count == 0) return null; if (readingElements.Count == 0) return null;
XmlNamespaceCollection namespaces = readingElements.Peek().Namespaces; var namespaces = readingElements.Peek().Namespaces;
for (int x = 0; x < namespaces.Count; x++) for (int i = 0; i < namespaces.Count; i++) {
{ if (String.CompareOrdinal(namespaces[i].Prefix, prefix) == 0)
if (String.CompareOrdinal(namespaces[x].Prefix, prefix) == 0) return namespaces[i].Namespace;
return namespaces[x].Namespace;
} }
return null; return null;
} }
///<summary>
///When overridden in a derived class, resolves the entity reference for EntityReference nodes.
///</summary>
///
///<exception cref="T:System.InvalidOperationException">The reader is not positioned on an EntityReference node; this implementation of the reader cannot resolve entities (<see cref="P:System.Xml.XmlReader.CanResolveEntity"></see> returns false). </exception>
public override void ResolveEntity() public override void ResolveEntity()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
///<summary>
///When overridden in a derived class, gets the type of the current node.
///</summary>
///
///<returns>
///One of the <see cref="T:System.Xml.XmlNodeType"></see> values representing the type of the current node.
///</returns>
///
public override XmlNodeType NodeType public override XmlNodeType NodeType
{ {
get get {
{
if (intoAttribute) return XmlNodeType.Text; if (intoAttribute) return XmlNodeType.Text;
return this.CurrentNode.NodeType; return this.CurrentNode.NodeType;
} }
} }
///<summary>
///When overridden in a derived class, gets the local name of the current node.
///</summary>
///
///<returns>
///The name of the current node with the prefix removed. For example, LocalName is book for the element &lt;bk:book&gt;.For node types that do not have a name (like Text, Comment, and so on), this property returns String.Empty.
///</returns>
///
public override string LocalName public override string LocalName
{ {
get get
@ -1033,37 +915,38 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
keys.Add(new KeyMapping(text) { Position = position }); keys.Add(new KeyMapping(text) { Position = position });
} }
void ReadXmlnsProperty() void ReadXmlnsProperty()
{ {
string prefix = reader.ReadString(); string prefix = reader.ReadString();
string @namespace = reader.ReadString(); string @namespace = reader.ReadString();
string[] textArray = new string[(uint)reader.ReadInt16()]; string[] textArray = new string[(uint)reader.ReadInt16()];
for (int i = 0; i < textArray.Length; i++) for (int i = 0; i < textArray.Length; i++) {
{
textArray[i] = this.assemblyTable[reader.ReadInt16()]; textArray[i] = this.assemblyTable[reader.ReadInt16()];
} }
XmlNamespaceCollection namespaces = elements.Peek().Namespaces; var namespaces = elements.Peek().Namespaces;
// Mapping locale, ci aggiunto l'assembly
if (@namespace.StartsWith("clr-namespace:") && @namespace.IndexOf("assembly=") < 0) // The XmlnsProperty record corresponds to an assembly
{ // We need to add the assembly name to the entry.
XmlPIMapping mappingToChange = null; if (@namespace.StartsWith("clr-namespace:", StringComparison.Ordinal) && @namespace.IndexOf("assembly=", StringComparison.Ordinal) < 0) {
foreach (XmlPIMapping mapping in this.Mappings) XmlToClrNamespaceMapping mappingToChange = null;
{ foreach (XmlToClrNamespaceMapping mapping in mappings) {
if (String.CompareOrdinal(mapping.XmlNamespace, @namespace) == 0) if (String.CompareOrdinal(mapping.XmlNamespace, @namespace) == 0) {
{
mappingToChange = mapping; mappingToChange = mapping;
break; break;
} }
} }
if (mappingToChange == null) if (mappingToChange == null)
throw new InvalidOperationException("Cannot find mapping"); throw new InvalidOperationException("Cannot find mapping");
if (mappingToChange.AssemblyId > 0) {
@namespace = String.Format("{0};assembly={1}", @namespace, mappingToChange.Assembly.Replace(" ", "")); @namespace = String.Format("{0};assembly={1}", @namespace, mappingToChange.AssemblyName.Replace(" ", ""));
mappingToChange.XmlNamespace = @namespace; mappingToChange.XmlNamespace = @namespace;
}
} }
namespaces.Add(new XmlNamespace(prefix, @namespace)); var ns = new XmlNamespace(prefix, @namespace);
XmlnsDefinitions.Add(ns);
namespaces.Add(ns);
} }
void ReadElementEnd() void ReadElementEnd()
@ -1292,22 +1175,26 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
nodes.Enqueue(property); nodes.Enqueue(property);
} }
XmlPIMapping FindByClrNamespaceAndAssemblyId(TypeDeclaration declaration) XmlToClrNamespaceMapping FindByClrNamespaceAndAssemblyId(TypeDeclaration declaration)
{ {
return FindByClrNamespaceAndAssemblyName(declaration.Namespace, declaration.Assembly); return FindByClrNamespaceAndAssemblyName(declaration.Namespace, declaration.Assembly);
} }
XmlPIMapping FindByClrNamespaceAndAssemblyName(string clrNamespace, string assemblyName) XmlToClrNamespaceMapping FindByClrNamespaceAndAssemblyName(string clrNamespace, string assemblyName)
{ {
if (clrNamespace == XamlTypeDeclaration.Namespace && assemblyName == XamlTypeDeclaration.Assembly) if (assemblyName == XamlTypeDeclaration.Assembly) {
return new XmlPIMapping(XmlPIMapping.XamlNamespace, assemblyName, clrNamespace); if (clrNamespace == XamlTypeDeclaration.Namespace)
for (int x = 0; x < Mappings.Count; x++) { return new XmlToClrNamespaceMapping(XmlToClrNamespaceMapping.XamlNamespace, -1, XamlTypeDeclaration.Assembly, XamlTypeDeclaration.Namespace);
XmlPIMapping xp = Mappings[x]; return new XmlToClrNamespaceMapping(XmlToClrNamespaceMapping.PresentationNamespace, -1, assemblyName, clrNamespace);
if (string.Equals(xp.Assembly, assemblyName, StringComparison.Ordinal) && string.Equals(xp.ClrNamespace, clrNamespace, StringComparison.Ordinal)) }
for (int x = 0; x < mappings.Count; x++) {
XmlToClrNamespaceMapping xp = mappings[x];
if (string.Equals(xp.AssemblyName, assemblyName, StringComparison.Ordinal) && string.Equals(xp.ClrNamespace, clrNamespace, StringComparison.Ordinal))
return xp; return xp;
} }
return null; return new XmlToClrNamespaceMapping(XmlToClrNamespaceMapping.PresentationNamespace, -1, assemblyName, clrNamespace);
} }
void ReadPIMapping() void ReadPIMapping()
@ -1316,7 +1203,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
string clrNamespace = reader.ReadString(); string clrNamespace = reader.ReadString();
short assemblyId = reader.ReadInt16(); short assemblyId = reader.ReadInt16();
Mappings.Add(new XmlPIMapping(xmlNamespace, GetAssembly(assemblyId), clrNamespace)); mappings.Add(new XmlToClrNamespaceMapping(xmlNamespace, assemblyId, GetAssembly(assemblyId), clrNamespace));
} }
void ReadContentProperty() void ReadContentProperty()
@ -1484,7 +1371,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
else else
throw new InvalidOperationException("Invalid resource: " + resource.GetType()); throw new InvalidOperationException("Invalid resource: " + resource.GetType());
string prefix = this.LookupPrefix(XmlPIMapping.XamlNamespace, false); string prefix = this.LookupPrefix(XmlToClrNamespaceMapping.XamlNamespace, false);
if (String.IsNullOrEmpty(prefix)) if (String.IsNullOrEmpty(prefix))
return String.Format("{{Static {0}}}", name); return String.Format("{{Static {0}}}", name);
else else
@ -1498,7 +1385,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
string GetTypeExtension(short typeIdentifier) string GetTypeExtension(short typeIdentifier)
{ {
string prefix = this.LookupPrefix(XmlPIMapping.XamlNamespace, false); string prefix = this.LookupPrefix(XmlToClrNamespaceMapping.XamlNamespace, false);
if (String.IsNullOrEmpty(prefix)) if (String.IsNullOrEmpty(prefix))
return String.Format("{{Type {0}}}", FormatTypeDeclaration(GetTypeDeclaration(typeIdentifier))); return String.Format("{{Type {0}}}", FormatTypeDeclaration(GetTypeDeclaration(typeIdentifier)));
else else
@ -1507,7 +1394,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
string FormatTypeDeclaration(TypeDeclaration typeDeclaration) string FormatTypeDeclaration(TypeDeclaration typeDeclaration)
{ {
XmlPIMapping mapping = FindByClrNamespaceAndAssemblyName(typeDeclaration.Namespace, typeDeclaration.Assembly); XmlToClrNamespaceMapping mapping = FindByClrNamespaceAndAssemblyName(typeDeclaration.Namespace, typeDeclaration.Assembly);
string prefix = (mapping != null) ? this.LookupPrefix(mapping.XmlNamespace, false) : null; string prefix = (mapping != null) ? this.LookupPrefix(mapping.XmlNamespace, false) : null;
string name = typeDeclaration.Name; string name = typeDeclaration.Name;
if (name.EndsWith("Extension")) if (name.EndsWith("Extension"))
@ -1534,7 +1421,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
bool differentType = ((propertyDeclaration.DeclaringType != propertyDeclaration.DeclaringType || !isDescendant)); bool differentType = ((propertyDeclaration.DeclaringType != propertyDeclaration.DeclaringType || !isDescendant));
if (withPrefix) { if (withPrefix) {
XmlPIMapping mapping = FindByClrNamespaceAndAssemblyName(propertyDeclaration.DeclaringType.Namespace, propertyDeclaration.DeclaringType.Assembly); XmlToClrNamespaceMapping mapping = FindByClrNamespaceAndAssemblyName(propertyDeclaration.DeclaringType.Namespace, propertyDeclaration.DeclaringType.Assembly);
string prefix = (mapping != null) ? this.LookupPrefix(mapping.XmlNamespace, false) : null; string prefix = (mapping != null) ? this.LookupPrefix(mapping.XmlNamespace, false) : null;
if (!String.IsNullOrEmpty(prefix)) { if (!String.IsNullOrEmpty(prefix)) {
@ -1559,7 +1446,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
PropertyDeclaration pd = this.GetPropertyDeclaration(propertyId); PropertyDeclaration pd = this.GetPropertyDeclaration(propertyId);
object staticResource = GetStaticResource(index); object staticResource = GetStaticResource(index);
string prefix = this.LookupPrefix(XmlPIMapping.PresentationNamespace, false); string prefix = this.LookupPrefix(XmlToClrNamespaceMapping.PresentationNamespace, false);
string value = String.Format("{{{0}{1}StaticResource {2}}}", prefix, (String.IsNullOrEmpty(prefix)) ? String.Empty : ":", staticResource); string value = String.Format("{{{0}{1}StaticResource {2}}}", prefix, (String.IsNullOrEmpty(prefix)) ? String.Empty : ":", staticResource);
XmlBamlProperty property = new XmlBamlProperty(elements.Peek(), PropertyType.Value, pd); XmlBamlProperty property = new XmlBamlProperty(elements.Peek(), PropertyType.Value, pd);
@ -1658,12 +1545,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
get { return _currentNode; } get { return _currentNode; }
} }
///<summary>
///When overridden in a derived class, gets the namespace URI (as defined in the W3C Namespace specification) of the node on which the reader is positioned.
///</summary>
///<returns>
///The namespace URI of the current node; otherwise an empty string.
///</returns>
public override string NamespaceURI { public override string NamespaceURI {
get { get {
if (intoAttribute) return String.Empty; if (intoAttribute) return String.Empty;
@ -1676,8 +1557,8 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
declaration = ((XmlBamlProperty)node).PropertyDeclaration.DeclaringType; declaration = ((XmlBamlProperty)node).PropertyDeclaration.DeclaringType;
TypeDeclaration elementDeclaration = this.readingElements.Peek().TypeDeclaration; TypeDeclaration elementDeclaration = this.readingElements.Peek().TypeDeclaration;
XmlPIMapping propertyMapping = FindByClrNamespaceAndAssemblyId(declaration) ?? XmlPIMapping.GetPresentationMapping(GetAssembly); XmlToClrNamespaceMapping propertyMapping = FindByClrNamespaceAndAssemblyId(declaration);
XmlPIMapping elementMapping = FindByClrNamespaceAndAssemblyId(elementDeclaration) ?? XmlPIMapping.GetPresentationMapping(GetAssembly); XmlToClrNamespaceMapping elementMapping = FindByClrNamespaceAndAssemblyId(elementDeclaration);
if (((XmlBamlProperty)node).PropertyDeclaration.Name == "Name" && if (((XmlBamlProperty)node).PropertyDeclaration.Name == "Name" &&
_resolver.IsLocalAssembly(((XmlBamlProperty)node).Parent.TypeDeclaration.Assembly)) _resolver.IsLocalAssembly(((XmlBamlProperty)node).Parent.TypeDeclaration.Assembly))
@ -1699,36 +1580,23 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
else else
return String.Empty; return String.Empty;
XmlPIMapping mapping = FindByClrNamespaceAndAssemblyId(declaration); XmlToClrNamespaceMapping mapping = FindByClrNamespaceAndAssemblyId(declaration);
if (mapping == null)
mapping = XmlPIMapping.GetPresentationMapping(GetAssembly);
return mapping.XmlNamespace; return mapping.XmlNamespace;
} }
} }
///<summary>
///When overridden in a derived class, gets the namespace prefix associated with the current node.
///</summary>
///<returns>
///The namespace prefix associated with the current node.
///</returns>
public override string Prefix public override string Prefix
{ {
get get {
{
if (!intoAttribute) if (!intoAttribute)
return ((IXmlNamespaceResolver)this).LookupPrefix(this.NamespaceURI) ?? String.Empty; return ((IXmlNamespaceResolver)this).LookupPrefix(this.NamespaceURI) ?? String.Empty;
return String.Empty; return String.Empty;
} }
} }
///<summary>
///When overridden in a derived class, gets a value indicating whether the current node can have a <see cref="P:System.Xml.XmlReader.Value"></see>.
///</summary>
///<returns>
///true if the node on which the reader is currently positioned can have a Value; otherwise, false. If false, the node has a value of String.Empty.
///</returns>
public override bool HasValue public override bool HasValue
{ {
get { return this.Value != null; } get { return this.Value != null; }
@ -1742,16 +1610,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
get { return _resolver; } get { return _resolver; }
} }
///<summary>
///When overridden in a derived class, gets the text value of the current node.
///</summary>
///<returns>
///The value returned depends on the <see cref="P:System.Xml.XmlReader.NodeType"></see> of the node. The following table lists node types that have a value to return. All other node types return String.Empty.Node type Value AttributeThe value of the attribute. CDATAThe content of the CDATA section. CommentThe content of the comment. DocumentTypeThe internal subset. ProcessingInstructionThe entire content, excluding the target. SignificantWhitespaceThe white space between markup in a mixed content model. TextThe content of the text node. WhitespaceThe white space between markup. XmlDeclarationThe content of the declaration.
///</returns>
public override string Value public override string Value
{ {
get get {
{
XmlBamlNode node = this.CurrentNode; XmlBamlNode node = this.CurrentNode;
if (node is XmlBamlSimpleProperty) if (node is XmlBamlSimpleProperty)
return ((XmlBamlSimpleProperty)node).Value; return ((XmlBamlSimpleProperty)node).Value;
@ -1766,116 +1627,39 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
} }
} }
/// <summary> public IDictionary<string, string> RootNamespaces => _rootNamespaces;
/// Return root namespaces
/// </summary>
public IDictionary<string, string> RootNamespaces
{
get { return _rootNamespaces; }
}
///<summary> public override int Depth => readingElements.Count;
///When overridden in a derived class, gets the depth of the current node in the XML document.
///</summary>
///<returns>
///The depth of the current node in the XML document.
///</returns>
public override int Depth
{
get { return this.readingElements.Count; }
}
///<summary> public override string BaseURI => string.Empty;
///When overridden in a derived class, gets the base URI of the current node.
///</summary>
///<returns>
///The base URI of the current node.
///</returns>
public override string BaseURI
{
get { return String.Empty; }
}
///<summary> public override bool IsEmptyElement => false;
///When overridden in a derived class, gets a value indicating whether the current node is an empty element (for example, &lt;MyElement/&gt;).
///</summary> public override bool EOF => _eof;
///<returns>
///true if the current node is an element (<see cref="P:System.Xml.XmlReader.NodeType"></see> equals XmlNodeType.Element) that ends with /&gt;; otherwise, false.
///</returns>
public override bool IsEmptyElement
{
get { return false; }
}
///<summary>
///When overridden in a derived class, gets the number of attributes on the current node.
///</summary>
///<returns>
///The number of attributes on the current node.
///</returns>
public override int AttributeCount { public override int AttributeCount {
get { throw new NotImplementedException(); } get { throw new NotImplementedException(); }
} }
///<summary>
///When overridden in a derived class, gets a value indicating whether the reader is positioned at the end of the stream.
///</summary>
///<returns>
///true if the reader is positioned at the end of the stream; otherwise, false.
///</returns>
public override bool EOF {
get { return _eof; }
}
///<summary>
///When overridden in a derived class, gets the state of the reader.
///</summary>
///<returns>
///One of the <see cref="T:System.Xml.ReadState"></see> values.
///</returns>
public override ReadState ReadState { public override ReadState ReadState {
get { get {
if (!initialized) if (!initialized)
return ReadState.Initial; return ReadState.Initial;
else if (reader == null) if (reader == null)
return ReadState.Closed; return ReadState.Closed;
else if (this.EOF) if (this.EOF)
return ReadState.EndOfFile; return ReadState.EndOfFile;
else return ReadState.Interactive;
return ReadState.Interactive;
} }
} }
public List<XmlPIMapping> Mappings public override XmlNameTable NameTable => _nameTable;
{
get { return _mappings; }
}
///<summary>
///When overridden in a derived class, gets the <see cref="T:System.Xml.XmlNameTable"></see> associated with this implementation.
///</summary>
///<returns>
///The XmlNameTable enabling you to get the atomized version of a string within the node.
///</returns>
public override XmlNameTable NameTable
{
get { return _nameTable; }
}
#region IXmlNamespaceResolver Members #region IXmlNamespaceResolver Members
///<summary>
///Gets a collection of defined prefix-namespace Mappings that are currently in scope.
///</summary>
///
///<returns>
///An <see cref="T:System.Collections.IDictionary"></see> that contains the current in-scope namespaces.
///</returns>
///
///<param name="scope">An <see cref="T:System.Xml.XmlNamespaceScope"></see> value that specifies the type of namespace nodes to return.</param>
IDictionary<string, string> IXmlNamespaceResolver.GetNamespacesInScope(XmlNamespaceScope scope) IDictionary<string, string> IXmlNamespaceResolver.GetNamespacesInScope(XmlNamespaceScope scope)
{ {
XmlNamespaceCollection namespaces = readingElements.Peek().Namespaces; var namespaces = readingElements.Peek().Namespaces;
Dictionary<String, String> list = new Dictionary<string, string>(); Dictionary<String, String> list = new Dictionary<string, string>();
foreach (XmlNamespace ns in namespaces) foreach (XmlNamespace ns in namespaces)
{ {
@ -1885,29 +1669,11 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
return list; return list;
} }
///<summary>
///Gets the namespace URI mapped to the specified prefix.
///</summary>
///
///<returns>
///The namespace URI that is mapped to the prefix; null if the prefix is not mapped to a namespace URI.
///</returns>
///
///<param name="prefix">The prefix whose namespace URI you wish to find.</param>
string IXmlNamespaceResolver.LookupNamespace(string prefix) string IXmlNamespaceResolver.LookupNamespace(string prefix)
{ {
return this.LookupNamespace(prefix); return this.LookupNamespace(prefix);
} }
///<summary>
///Gets the prefix that is mapped to the specified namespace URI.
///</summary>
///
///<returns>
///The prefix that is mapped to the namespace URI; null if the namespace URI is not mapped to a prefix.
///</returns>
///
///<param name="namespaceName">The namespace URI whose prefix you wish to find.</param>
string IXmlNamespaceResolver.LookupPrefix(string namespaceName) string IXmlNamespaceResolver.LookupPrefix(string namespaceName)
{ {
return this.LookupPrefix(namespaceName, true); return this.LookupPrefix(namespaceName, true);
@ -1922,12 +1688,10 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
elements = this.elements; elements = this.elements;
if (elements.Count == 0) return null; if (elements.Count == 0) return null;
XmlNamespaceCollection namespaces = elements.Peek().Namespaces; return LookupPrefix(namespaceName, elements.Peek().Namespaces);
return LookupPrefix(namespaceName, namespaces);
} }
static string LookupPrefix(string namespaceName, XmlNamespaceCollection namespaces) static string LookupPrefix(string namespaceName, IList<XmlNamespace> namespaces)
{ {
for (int x = 0; x < namespaces.Count; x++) for (int x = 0; x < namespaces.Count; x++)
{ {
@ -1940,8 +1704,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
#endregion #endregion
#region IntegerCollectionType
internal enum IntegerCollectionType : byte internal enum IntegerCollectionType : byte
{ {
Byte = 2, Byte = 2,
@ -1950,7 +1712,5 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
Unknown = 0, Unknown = 0,
UShort = 3 UShort = 3
} }
#endregion
} }
} }

36
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlNamespace.cs

@ -1,47 +1,33 @@
// Copyright (c) Cristian Civera (cristian@aspitalia.com) // Copyright (c) Cristian Civera (cristian@aspitalia.com)
// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) // This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt)
using System.Collections.Generic; using System;
namespace Ricciolo.StylesExplorer.MarkupReflection namespace Ricciolo.StylesExplorer.MarkupReflection
{ {
internal class XmlNamespace public class XmlNamespace
{ {
private string _prefix;
private string _namespace;
public XmlNamespace(string prefix, string ns) public XmlNamespace(string prefix, string ns)
{ {
_prefix = prefix; Prefix = prefix;
_namespace = ns; Namespace = ns;
} }
public string Prefix public string Prefix { get; }
{
get { return _prefix; }
}
public string Namespace public string Namespace { get; }
{
get { return _namespace; }
}
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
if (obj is XmlNamespace) XmlNamespace o = obj as XmlNamespace;
{ if (o == null)
XmlNamespace o = (XmlNamespace)obj; return false;
return (o.Prefix.Equals(this.Prefix) && o.Namespace.Equals(this.Namespace)); return o.Prefix.Equals(Prefix) && o.Namespace.Equals(Namespace);
}
return base.Equals(obj);
} }
public override int GetHashCode() public override int GetHashCode()
{ {
return _prefix.GetHashCode() + _namespace.GetHashCode() >> 20; return Prefix.GetHashCode() + Namespace.GetHashCode() >> 20;
} }
} }
internal class XmlNamespaceCollection : List<XmlNamespace>
{}
} }

58
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlPIMapping.cs

@ -1,58 +0,0 @@
// Copyright (c) Cristian Civera (cristian@aspitalia.com)
// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt)
using System;
namespace Ricciolo.StylesExplorer.MarkupReflection
{
/// <summary>
/// Rappresenta la mappatura tra namespace XML e namespace CLR con relativo assembly
/// </summary>
public class XmlPIMapping
{
string _xmlNamespace;
string assemblyName;
string _clrNamespace;
public const string XamlNamespace = "http://schemas.microsoft.com/winfx/2006/xaml";
public const string PresentationNamespace = "http://schemas.microsoft.com/winfx/2006/xaml/presentation";
public const string PresentationOptionsNamespace = "http://schemas.microsoft.com/winfx/2006/xaml/presentation/options";
public const string McNamespace = "http://schemas.openxmlformats.org/markup-compatibility/2006";
public XmlPIMapping(string xmlNamespace, string assembly, string clrNamespace)
{
_xmlNamespace = xmlNamespace;
assemblyName = assembly;
_clrNamespace = clrNamespace;
}
/// <summary>
/// Restituisce o imposta il namespace XML
/// </summary>
public string XmlNamespace
{
get { return _xmlNamespace; }
set { _xmlNamespace = value;}
}
/// <summary>
/// Name of the assembly.
/// </summary>
public string Assembly {
get { return assemblyName; }
}
/// <summary>
/// Restituisce il namespace clr
/// </summary>
public string ClrNamespace
{
get { return _clrNamespace; }
}
public static XmlPIMapping GetPresentationMapping(Func<short, string> assemblyResolve)
{
return new XmlPIMapping(PresentationNamespace, assemblyResolve(0), string.Empty);
}
}
}

31
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlToClrNamespaceMapping.cs

@ -0,0 +1,31 @@
// Copyright (c) Cristian Civera (cristian@aspitalia.com)
// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt)
using System;
namespace Ricciolo.StylesExplorer.MarkupReflection
{
/// <summary>
/// Represents a mapping between an XML namespace and a CLR namespace and assembly.
/// </summary>
public class XmlToClrNamespaceMapping
{
public const string XamlNamespace = "http://schemas.microsoft.com/winfx/2006/xaml";
public const string PresentationNamespace = "http://schemas.microsoft.com/winfx/2006/xaml/presentation";
public const string PresentationOptionsNamespace = "http://schemas.microsoft.com/winfx/2006/xaml/presentation/options";
public const string McNamespace = "http://schemas.openxmlformats.org/markup-compatibility/2006";
public XmlToClrNamespaceMapping(string xmlNamespace, short assemblyId, string assemblyName, string clrNamespace)
{
XmlNamespace = xmlNamespace;
AssemblyId = assemblyId;
AssemblyName = assemblyName;
ClrNamespace = clrNamespace;
}
public short AssemblyId { get; }
public string XmlNamespace { get; set; }
public string AssemblyName { get; }
public string ClrNamespace { get; }
}
}

36
ILSpy.BamlDecompiler/Tests/BamlTestRunner.cs

@ -21,68 +21,73 @@ namespace ILSpy.BamlDecompiler.Tests
{ {
RunTest("cases/simple"); RunTest("cases/simple");
} }
[Test] [Test]
public void SimpleDictionary() public void SimpleDictionary()
{ {
RunTest("cases/simpledictionary"); RunTest("cases/simpledictionary");
} }
[Test] [Test]
public void Resources() public void Resources()
{ {
RunTest("cases/resources"); RunTest("cases/resources");
} }
[Test] [Test]
[Ignore("Broken on AppVeyor CI (extra x:ConnectionId attribute)")]
public void SimpleNames() public void SimpleNames()
{ {
RunTest("cases/simplenames"); RunTest("cases/simplenames");
} }
[Test] [Test]
public void AvalonDockBrushes() public void AvalonDockBrushes()
{ {
RunTest("cases/avalondockbrushes"); RunTest("cases/avalondockbrushes");
} }
[Test] [Test]
public void AvalonDockCommon() public void AvalonDockCommon()
{ {
RunTest("cases/avalondockcommon"); RunTest("cases/avalondockcommon");
} }
[Test] [Test]
public void AttachedEvent() public void AttachedEvent()
{ {
RunTest("cases/attachedevent"); RunTest("cases/attachedevent");
} }
[Test] [Test]
public void Dictionary1() public void Dictionary1()
{ {
RunTest("cases/dictionary1"); RunTest("cases/dictionary1");
} }
[Test]
public void Issue775()
{
RunTest("cases/issue775");
}
[Test] [Test]
public void MarkupExtension() public void MarkupExtension()
{ {
RunTest("cases/markupextension"); RunTest("cases/markupextension");
} }
[Test] [Test]
public void SimplePropertyElement() public void SimplePropertyElement()
{ {
RunTest("cases/simplepropertyelement"); RunTest("cases/simplepropertyelement");
} }
[Test] [Test]
public void Issue445() public void Issue445()
{ {
RunTest("cases/issue445"); RunTest("cases/issue445");
} }
[Test] [Test]
public void NamespacePrefix() public void NamespacePrefix()
{ {
@ -94,13 +99,13 @@ namespace ILSpy.BamlDecompiler.Tests
{ {
RunTest("cases/escapesequence"); RunTest("cases/escapesequence");
} }
#region RunTest #region RunTest
void RunTest(string name) void RunTest(string name)
{ {
RunTest(name, typeof(BamlTestRunner).Assembly.Location, Path.Combine("..\\..\\Tests", name + ".xaml")); RunTest(name, typeof(BamlTestRunner).Assembly.Location, Path.Combine("..\\..\\Tests", name + ".xaml"));
} }
void RunTest(string name, string asmPath, string sourcePath) void RunTest(string name, string asmPath, string sourcePath)
{ {
var resolver = new DefaultAssemblyResolver(); var resolver = new DefaultAssemblyResolver();
@ -135,8 +140,7 @@ namespace ILSpy.BamlDecompiler.Tests
ResourceReader reader; ResourceReader reader;
try { try {
reader = new ResourceReader(s); reader = new ResourceReader(s);
} } catch (ArgumentException) {
catch (ArgumentException) {
return null; return null;
} }
foreach (DictionaryEntry entry in reader.Cast<DictionaryEntry>().OrderBy(e => e.Key.ToString())) { foreach (DictionaryEntry entry in reader.Cast<DictionaryEntry>().OrderBy(e => e.Key.ToString())) {
@ -148,7 +152,7 @@ namespace ILSpy.BamlDecompiler.Tests
} }
} }
} }
return null; return null;
} }
#endregion #endregion

5
ILSpy.BamlDecompiler/Tests/Cases/Issue775.xaml

@ -0,0 +1,5 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:MyNamespace="clr-namespace:ILSpy.BamlDecompiler.Tests.Cases">
<Style x:Key="style1">
<Setter Property="MyNamespace:CustomControl.CustomName" Value="Test" />
</Style>
</ResourceDictionary>

2
ILSpy.BamlDecompiler/Tests/Cases/MarkupExtension.xaml

@ -1,4 +1,4 @@
<Label DataContext="{Binding Blub}" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <Label DataContext="{Binding Blub}" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Label.Style> <Label.Style>
<Style /> <Style />
</Label.Style> </Label.Style>

2
ILSpy.BamlDecompiler/Tests/Cases/SimplePropertyElement.xaml

@ -1,4 +1,4 @@
<Label xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <Label xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Label.Style> <Label.Style>
<Style /> <Style />
</Label.Style> </Label.Style>

3
ILSpy.BamlDecompiler/Tests/ILSpy.BamlDecompiler.Tests.csproj

@ -129,6 +129,9 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Cases\Issue775.xaml">
<SubType>Designer</SubType>
</Page>
<Page Include="Cases\MarkupExtension.xaml" /> <Page Include="Cases\MarkupExtension.xaml" />
<Page Include="Cases\MyControl.xaml" /> <Page Include="Cases\MyControl.xaml" />
<Page Include="Cases\NamespacePrefix.xaml" /> <Page Include="Cases\NamespacePrefix.xaml" />

Loading…
Cancel
Save