diff --git a/ILSpy.BamlDecompiler/BamlConnectionId.cs b/ILSpy.BamlDecompiler/BamlConnectionId.cs
index 1e4bf67e7..9bf19607d 100644
--- a/ILSpy.BamlDecompiler/BamlConnectionId.cs
+++ b/ILSpy.BamlDecompiler/BamlConnectionId.cs
@@ -22,6 +22,14 @@
namespace ILSpy.BamlDecompiler
{
+ ///
+ /// Represents a field assignment of a XAML code-behind class.
+ ///
+ internal sealed class FieldAssignment
+ {
+ public string FieldName;
+ }
+
///
/// Represents an event registration of a XAML code-behind class.
///
diff --git a/ILSpy.BamlDecompiler/Handlers/Records/OptimizedStaticResourceHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/OptimizedStaticResourceHandler.cs
index 85b275966..53b5a773e 100644
--- a/ILSpy.BamlDecompiler/Handlers/Records/OptimizedStaticResourceHandler.cs
+++ b/ILSpy.BamlDecompiler/Handlers/Records/OptimizedStaticResourceHandler.cs
@@ -81,7 +81,7 @@ namespace ILSpy.BamlDecompiler.Handlers
name = res.Item1 + "." + res.Item2;
else
name = res.Item1 + "." + res.Item3;
- var xmlns = ctx.GetXmlNamespace("http://schemas.microsoft.com/winfx/2006/xaml/presentation");
+ var xmlns = ctx.GetXmlNamespace(XamlContext.KnownNamespace_Presentation);
attrName = ctx.ToString(parent.Xaml, xmlns.GetName(name));
}
else
diff --git a/ILSpy.BamlDecompiler/Handlers/Records/PropertyWithExtensionHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/PropertyWithExtensionHandler.cs
index c7fe61ca5..35c0a76fd 100644
--- a/ILSpy.BamlDecompiler/Handlers/Records/PropertyWithExtensionHandler.cs
+++ b/ILSpy.BamlDecompiler/Handlers/Records/PropertyWithExtensionHandler.cs
@@ -85,7 +85,7 @@ namespace ILSpy.BamlDecompiler.Handlers
name = res.Item1 + "." + res.Item2;
else
name = res.Item1 + "." + res.Item3;
- var xmlns = ctx.GetXmlNamespace("http://schemas.microsoft.com/winfx/2006/xaml/presentation");
+ var xmlns = ctx.GetXmlNamespace(XamlContext.KnownNamespace_Presentation);
attrName = ctx.ToString(parent.Xaml, xmlns.GetName(name));
}
else
diff --git a/ILSpy.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs b/ILSpy.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs
index 7d4bd1e83..fe22c32ab 100644
--- a/ILSpy.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs
+++ b/ILSpy.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs
@@ -41,20 +41,29 @@ namespace ILSpy.BamlDecompiler.Rewrite
public void Run(XamlContext ctx, XDocument document)
{
- var mappings = DecompileEventMappings(ctx, document);
- ProcessConnectionIds(document.Root, mappings);
+ var connections = DecompileConnections(ctx, document);
+ ProcessConnectionIds(ctx, document.Root, connections);
}
- static void ProcessConnectionIds(XElement element,
- List<(LongSet key, EventRegistration[] value)> eventMappings)
+ static void ProcessConnectionIds(XamlContext ctx, XElement element,
+ (List<(LongSet key, FieldAssignment value)> fieldAssignments,
+ List<(LongSet key, EventRegistration[] value)> eventMappings) connections)
{
foreach (var child in element.Elements())
- ProcessConnectionIds(child, eventMappings);
+ ProcessConnectionIds(ctx, child, connections);
+ var fieldAssignments = connections.fieldAssignments;
+ var eventMappings = connections.eventMappings;
foreach (var annotation in element.Annotations())
{
int index;
- if ((index = eventMappings.FindIndex(item => item.key.Contains(annotation.Id))) > -1)
+ if ((index = fieldAssignments.FindIndex(item => item.key.Contains(annotation.Id))) > -1)
+ {
+ var xName = ctx.GetKnownNamespace("Name", XamlContext.KnownNamespace_Xaml, element);
+ if (element.Attribute("Name") is null && element.Attribute(xName) is null)
+ element.Add(new XAttribute(xName, fieldAssignments[index].value.FieldName));
+ }
+ else if ((index = eventMappings.FindIndex(item => item.key.Contains(annotation.Id))) > -1)
{
foreach (var entry in eventMappings[index].value)
{
@@ -79,28 +88,30 @@ namespace ILSpy.BamlDecompiler.Rewrite
}
}
- List<(LongSet, EventRegistration[])> DecompileEventMappings(XamlContext ctx, XDocument document)
+ (List<(LongSet, FieldAssignment)>, List<(LongSet, EventRegistration[])>) DecompileConnections
+ (XamlContext ctx, XDocument document)
{
- var result = new List<(LongSet, EventRegistration[])>();
+ var fieldAssignments = new List<(LongSet key, FieldAssignment value)>();
+ var eventMappings = new List<(LongSet, EventRegistration[])>();
var xClass = document.Root
.Elements().First()
.Attribute(ctx.GetKnownNamespace("Class", XamlContext.KnownNamespace_Xaml));
if (xClass == null)
- return result;
+ return (fieldAssignments, eventMappings);
var type = ctx.TypeSystem.FindType(new FullTypeName(xClass.Value)).GetDefinition();
if (type == null)
- return result;
+ return (fieldAssignments, eventMappings);
- DecompileEventMappings(ctx, result, componentConnectorTypeName, type);
- DecompileEventMappings(ctx, result, styleConnectorTypeName, type);
+ DecompileConnections(ctx, fieldAssignments, eventMappings, componentConnectorTypeName, type);
+ DecompileConnections(ctx, fieldAssignments, eventMappings, styleConnectorTypeName, type);
- return result;
+ return (fieldAssignments, eventMappings);
}
- void DecompileEventMappings(XamlContext ctx, List<(LongSet, EventRegistration[])> result,
- FullTypeName connectorTypeName, ITypeDefinition type)
+ void DecompileConnections(XamlContext ctx, List<(LongSet, FieldAssignment)> fieldAssignments,
+ List<(LongSet, EventRegistration[])> eventMappings, FullTypeName connectorTypeName, ITypeDefinition type)
{
var connectorInterface = ctx.TypeSystem.FindType(connectorTypeName).GetDefinition();
if (connectorInterface == null)
@@ -148,11 +159,19 @@ namespace ILSpy.BamlDecompiler.Rewrite
{
foreach (var section in ilSwitch.Sections)
{
- events.Clear();
- FindEvents(section.Body, events);
- if (events.Count > 0)
+ var field = FindField(section.Body);
+ if (!(field is null))
{
- result.Add((section.Labels, events.ToArray()));
+ fieldAssignments.Add((section.Labels, field));
+ }
+ else
+ {
+ events.Clear();
+ FindEvents(section.Body, events);
+ if (events.Count > 0)
+ {
+ eventMappings.Add((section.Labels, events.ToArray()));
+ }
}
}
}
@@ -169,16 +188,54 @@ namespace ILSpy.BamlDecompiler.Rewrite
var inst = comp.Kind == ComparisonKind.Inequality
? ifInst.FalseInst
: ifInst.TrueInst;
- events.Clear();
- FindEvents(inst, events);
- if (events.Count > 0)
+
+ var field = FindField(inst);
+ if (!(field is null))
{
- result.Add((new LongSet(id), events.ToArray()));
+ fieldAssignments.Add((new LongSet(id), field));
+ }
+ else
+ {
+ events.Clear();
+ FindEvents(inst, events);
+ if (events.Count > 0)
+ {
+ eventMappings.Add((new LongSet(id), events.ToArray()));
+ }
}
}
}
}
+ FieldAssignment FindField(ILInstruction inst)
+ {
+ switch (inst)
+ {
+ case Block b:
+ var t = b.Instructions.FirstOrDefault();
+ if (!(t is null) && MatchFieldAssignment(t, out var field))
+ return field;
+ return null;
+ case Branch br:
+ return FindField(br.TargetBlock);
+ default:
+ if (MatchFieldAssignment(inst, out field))
+ return field;
+ return null;
+ }
+ }
+
+ bool MatchFieldAssignment(ILInstruction inst, out FieldAssignment field)
+ {
+ field = null;
+ if (!inst.MatchStFld(out _, out var fld, out var value) || !value.MatchCastClass(out var arg, out _)
+ || !(arg.MatchLdLoc(out var t) && t.Kind == VariableKind.Parameter && t.Index == 1))
+ return false;
+
+ field = new FieldAssignment { FieldName = fld.Name };
+ return true;
+ }
+
void FindEvents(ILInstruction inst, List events)
{
EventRegistration @event;