Browse Source

add support for attached events to BAML-Decompiler

pull/155/head
Siegfried Pammer 14 years ago
parent
commit
70ee261147
  1. 20
      ILSpy/BamlDecompiler.cs
  2. 64
      ILSpy/ConnectMethodDecompiler.cs

20
ILSpy/BamlDecompiler.cs

@ -9,6 +9,7 @@ using System.Reflection; @@ -9,6 +9,7 @@ using System.Reflection;
using System.Threading.Tasks;
using System.Windows.Baml2006;
using System.Xaml;
using System.Xaml.Schema;
using System.Xml;
using System.Xml.Linq;
using ICSharpCode.AvalonEdit.Highlighting;
@ -271,7 +272,7 @@ namespace ICSharpCode.ILSpy.Baml @@ -271,7 +272,7 @@ namespace ICSharpCode.ILSpy.Baml
var eventMappings = connectMethodDecompiler.DecompileEventMappings(bamlTypeName);
foreach (var xamlNode in xamlDocument) {
RemoveConnectionIds(xamlNode, eventMappings);
RemoveConnectionIds(xamlNode, eventMappings, reader.SchemaContext);
AvoidContentProperties(xamlNode);
MoveXKeyToFront(xamlNode);
}
@ -297,10 +298,10 @@ namespace ICSharpCode.ILSpy.Baml @@ -297,10 +298,10 @@ namespace ICSharpCode.ILSpy.Baml
return doc.ToString();
}
void RemoveConnectionIds(XamlNode node, Dictionary<int, EventRegistration[]> eventMappings)
void RemoveConnectionIds(XamlNode node, Dictionary<int, EventRegistration[]> eventMappings, XamlSchemaContext context)
{
foreach (XamlNode child in node.Children)
RemoveConnectionIds(child, eventMappings);
RemoveConnectionIds(child, eventMappings, context);
XamlObjectNode obj = node as XamlObjectNode;
if (obj != null && obj.Children.Count > 0) {
@ -313,9 +314,16 @@ namespace ICSharpCode.ILSpy.Baml @@ -313,9 +314,16 @@ namespace ICSharpCode.ILSpy.Baml
if (value.Value is string && int.TryParse(value.Value as string, out id) && eventMappings.ContainsKey(id)) {
var map = eventMappings[id];
foreach (var entry in map) {
var member = new XamlMemberNode(obj.Type.GetMember(entry.EventName));
member.Children.Add(new XamlValueNode(entry.MethodName));
addableNodes.Add(member);
if (entry.IsAttached) {
var type = context.GetXamlType(Type.GetType(entry.AttachSourceType));
var member = new XamlMemberNode(new XamlMember(entry.EventName, type, true));
member.Children.Add(new XamlValueNode(entry.MethodName));
addableNodes.Add(member);
} else {
var member = new XamlMemberNode(obj.Type.GetMember(entry.EventName));
member.Children.Add(new XamlValueNode(entry.MethodName));
addableNodes.Add(member);
}
}
removableNodes.Add(memberNode);
}

64
ILSpy/ConnectMethodDecompiler.cs

@ -15,7 +15,8 @@ namespace ICSharpCode.ILSpy.Baml @@ -15,7 +15,8 @@ namespace ICSharpCode.ILSpy.Baml
[Serializable]
sealed class EventRegistration
{
public string EventName, MethodName;
public string EventName, MethodName, AttachSourceType;
public bool IsAttached;
}
/// <summary>
@ -82,18 +83,73 @@ namespace ICSharpCode.ILSpy.Baml @@ -82,18 +83,73 @@ namespace ICSharpCode.ILSpy.Baml
foreach (var node in block.Body) {
var expr = node as ILExpression;
string eventName, handlerName;
string eventName, handlerName, attachSource;
if (IsAddEvent(expr, out eventName, out handlerName))
events.Add(new EventRegistration {
EventName = eventName,
MethodName = handlerName
});
// TODO : handle attached events
else if (IsAddAttachedEvent(expr, out eventName, out handlerName, out attachSource))
events.Add(new EventRegistration {
EventName = eventName,
MethodName = handlerName,
AttachSourceType = attachSource,
IsAttached = true
});
}
return events.ToArray();
}
bool IsAddAttachedEvent(ILExpression expr, out string eventName, out string handlerName, out string attachSource)
{
eventName = "";
handlerName = "";
attachSource = "";
if (expr == null || !(expr.Code == ILCode.Callvirt || expr.Code == ILCode.Call))
return false;
if (expr.Operand is MethodReference && expr.Arguments.Count == 3) {
var addMethod = expr.Operand as MethodReference;
if (addMethod.Name != "AddHandler" || addMethod.Parameters.Count != 2)
return false;
var arg = expr.Arguments[1];
if (arg.Code != ILCode.Ldsfld || arg.Arguments.Any() || !(arg.Operand is FieldReference))
return false;
FieldReference fldRef = (FieldReference)arg.Operand;
attachSource = GetAssemblyQualifiedName(fldRef.DeclaringType);
eventName = fldRef.Name;
if (eventName.EndsWith("Event") && eventName.Length > "Event".Length)
eventName = eventName.Remove(eventName.Length - "Event".Length);
var arg1 = expr.Arguments[2];
if (arg1.Code != ILCode.Newobj)
return false;
var arg2 = arg1.Arguments[1];
if (arg2.Code != ILCode.Ldftn && arg2.Code != ILCode.Ldvirtftn)
return false;
if (arg2.Operand is MethodReference) {
var m = arg2.Operand as MethodReference;
handlerName = m.Name;
return true;
}
}
return false;
}
string GetAssemblyQualifiedName(TypeReference declaringType)
{
string fullName = declaringType.FullName;
if (declaringType.Scope is AssemblyNameReference)
fullName += ", " + ((AssemblyNameReference)declaringType.Scope).FullName;
else if (declaringType.Scope is ModuleDefinition)
fullName += ", " + ((ModuleDefinition)declaringType.Scope).Assembly.FullName;
return fullName;
}
bool IsAddEvent(ILExpression expr, out string eventName, out string handlerName)
{
eventName = "";
@ -107,7 +163,7 @@ namespace ICSharpCode.ILSpy.Baml @@ -107,7 +163,7 @@ namespace ICSharpCode.ILSpy.Baml
if (addMethod.Name.StartsWith("add_") && addMethod.Parameters.Count == 1)
eventName = addMethod.Name.Substring("add_".Length);
var arg = expr.Arguments[1];
if (arg.Code != ILCode.Newobj && arg.Arguments.Count != 2)
if (arg.Code != ILCode.Newobj || arg.Arguments.Count != 2)
return false;
var arg1 = arg.Arguments[1];
if (arg1.Code != ILCode.Ldftn && arg1.Code != ILCode.Ldvirtftn)

Loading…
Cancel
Save