diff --git a/ICSharpCode.Decompiler/Documentation/XmlDocKeyProvider.cs b/ICSharpCode.Decompiler/Documentation/XmlDocKeyProvider.cs index 1ff3d740f..0b3bb773b 100644 --- a/ICSharpCode.Decompiler/Documentation/XmlDocKeyProvider.cs +++ b/ICSharpCode.Decompiler/Documentation/XmlDocKeyProvider.cs @@ -32,7 +32,7 @@ namespace ICSharpCode.Decompiler.Documentation /// /// Provides XML documentation tags. /// - public sealed class XmlDocKeyProvider + public static class XmlDocKeyProvider { #region GetKey public static string GetKey(Entity entity) diff --git a/ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs b/ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs index 806891b49..0a996e200 100644 --- a/ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs +++ b/ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs @@ -8,8 +8,8 @@ using System.Linq; using System.Resources; using System.Threading; using System.Xml.Linq; +using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Tests.Helpers; -using Mono.Cecil; using NUnit.Framework; namespace ILSpy.BamlDecompiler.Tests @@ -112,16 +112,20 @@ namespace ILSpy.BamlDecompiler.Tests void RunTest(string name, string asmPath, string sourcePath) { - var resolver = new DefaultAssemblyResolver(); - resolver.RemoveSearchDirectory("."); - resolver.AddSearchDirectory(Path.GetDirectoryName(asmPath)); - var assembly = AssemblyDefinition.ReadAssembly(asmPath, new ReaderParameters { AssemblyResolver = resolver, InMemory = true }); - Resource res = assembly.MainModule.Resources.First(); - Stream bamlStream = LoadBaml(res, name + ".baml"); - Assert.IsNotNull(bamlStream); - XDocument document = BamlResourceEntryNode.LoadIntoDocument(resolver, assembly, bamlStream, CancellationToken.None); + using (var fileStream = new FileStream(asmPath, FileMode.Open, FileAccess.Read)) { + var module = new PEFile(asmPath, fileStream, System.Reflection.PortableExecutable.PEStreamOptions.Default); + var resolver = new UniversalAssemblyResolver(asmPath, false, true, module.Reader.DetectTargetFrameworkId(), System.Reflection.PortableExecutable.PEStreamOptions.Default); + resolver.RemoveSearchDirectory("."); + resolver.AddSearchDirectory(Path.GetDirectoryName(asmPath)); + module.AssemblyResolver = resolver; + var res = module.Resources.First(); + Stream bamlStream = LoadBaml(res, name + ".baml"); + Assert.IsNotNull(bamlStream); + XDocument document = BamlResourceEntryNode.LoadIntoDocument(module, bamlStream, CancellationToken.None); - XamlIsEqual(File.ReadAllText(sourcePath), document.ToString()); + XamlIsEqual(File.ReadAllText(sourcePath), document.ToString()); + + } } void XamlIsEqual(string input1, string input2) @@ -139,26 +143,23 @@ namespace ILSpy.BamlDecompiler.Tests Stream LoadBaml(Resource res, string name) { - EmbeddedResource er = res as EmbeddedResource; - if (er != null) { - Stream s = er.GetResourceStream(); - s.Position = 0; - ResourceReader reader; - try { - reader = new ResourceReader(s); - } catch (ArgumentException) { - return null; - } - foreach (DictionaryEntry entry in reader.Cast().OrderBy(e => e.Key.ToString())) { - if (entry.Key.ToString() == name) { - if (entry.Value is Stream) - return (Stream)entry.Value; - if (entry.Value is byte[]) - return new MemoryStream((byte[])entry.Value); - } + if (res.ResourceType != ResourceType.Embedded) return null; + Stream s = res.TryOpenStream(); + s.Position = 0; + ResourceReader reader; + try { + reader = new ResourceReader(s); + } catch (ArgumentException) { + return null; + } + foreach (DictionaryEntry entry in reader.Cast().OrderBy(e => e.Key.ToString())) { + if (entry.Key.ToString() == name) { + if (entry.Value is Stream) + return (Stream)entry.Value; + if (entry.Value is byte[]) + return new MemoryStream((byte[])entry.Value); } } - return null; } #endregion diff --git a/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj b/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj index c6ccf4e91..5ee4e0acc 100644 --- a/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj +++ b/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj @@ -38,6 +38,7 @@ + diff --git a/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs b/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs index 20fab5471..61b26deb6 100644 --- a/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs +++ b/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs @@ -10,7 +10,7 @@ using System.Threading.Tasks; using System.Xml.Linq; using ICSharpCode.AvalonEdit.Highlighting; -using ICSharpCode.Decompiler.Dom; +using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Util; using ICSharpCode.ILSpy; using ICSharpCode.ILSpy.TextView; @@ -50,7 +50,7 @@ namespace ILSpy.BamlDecompiler { var asm = this.Ancestors().OfType().FirstOrDefault().LoadedAssembly; Data.Position = 0; - XDocument xamlDocument = LoadIntoDocument(asm.GetAssemblyResolver(), asm.GetPEFileOrNull(), Data, cancellationToken); + XDocument xamlDocument = LoadIntoDocument(asm.GetPEFileOrNull(), Data, cancellationToken); output.Write(xamlDocument.ToString()); return true; } @@ -59,21 +59,21 @@ namespace ILSpy.BamlDecompiler { cancellationToken.ThrowIfCancellationRequested(); XDocument xamlDocument; - using (XmlBamlReader reader = new XmlBamlReader(stream, new NRTypeResolver(resolver, asm))) { + using (XmlBamlReader reader = new XmlBamlReader(stream, new NRTypeResolver(module))) { xamlDocument = XDocument.Load(reader); - ConvertConnectionIds(xamlDocument, asm, cancellationToken); + ConvertConnectionIds(xamlDocument, module, cancellationToken); ConvertToEmptyElements(xamlDocument.Root); MoveNamespacesToRoot(xamlDocument, reader.XmlnsDefinitions); return xamlDocument; } } - static void ConvertConnectionIds(XDocument xamlDocument, AssemblyDefinition asm, CancellationToken cancellationToken) + static void ConvertConnectionIds(XDocument xamlDocument, PEFile asm, CancellationToken cancellationToken) { var attr = xamlDocument.Root.Attribute(XName.Get("Class", XmlBamlReader.XWPFNamespace)); if (attr != null) { string fullTypeName = attr.Value; - var mappings = new ConnectMethodDecompiler(asm).DecompileEventMappings(fullTypeName, cancellationToken); + var mappings = new ConnectMethodDecompiler().DecompileEventMappings(asm, fullTypeName, cancellationToken); RemoveConnectionIds(xamlDocument.Root, mappings); } } diff --git a/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs b/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs index 178e8cb39..740611e07 100644 --- a/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs +++ b/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs @@ -7,7 +7,7 @@ using System.IO; using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy; -using ICSharpCode.Decompiler.Dom; +using ICSharpCode.Decompiler.Metadata; namespace ILSpy.BamlDecompiler { @@ -36,7 +36,7 @@ namespace ILSpy.BamlDecompiler public string WriteResourceToFile(LoadedAssembly assembly, string fileName, Stream stream, DecompilationOptions options) { - var document = BamlResourceEntryNode.LoadIntoDocument(assembly.GetAssemblyResolver(), assembly.GetPEFileOrNull(), stream, options.CancellationToken); + var document = BamlResourceEntryNode.LoadIntoDocument(assembly.GetPEFileOrNull(), stream, options.CancellationToken); fileName = Path.ChangeExtension(fileName, ".xaml"); document.Save(Path.Combine(options.SaveAsProjectDirectory, fileName)); return fileName; diff --git a/ILSpy.BamlDecompiler/CecilTypeResolver.cs b/ILSpy.BamlDecompiler/CecilTypeResolver.cs index cafe37d60..0164fe120 100644 --- a/ILSpy.BamlDecompiler/CecilTypeResolver.cs +++ b/ILSpy.BamlDecompiler/CecilTypeResolver.cs @@ -2,8 +2,8 @@ // This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) using System; +using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; -using Mono.Cecil; using Ricciolo.StylesExplorer.MarkupReflection; namespace ILSpy.BamlDecompiler @@ -13,11 +13,15 @@ namespace ILSpy.BamlDecompiler /// public class NRTypeResolver : IDotNetTypeResolver { + readonly PEFile module; + readonly DecompilerTypeSystem typeSystem; readonly ICompilation compilation; - public NRTypeResolver(ICompilation compilation) + public NRTypeResolver(PEFile module) { - this.compilation = compilation; + this.module = module; + this.typeSystem = new DecompilerTypeSystem(module); + this.compilation = typeSystem.Compilation; } public bool IsLocalAssembly(string name) @@ -66,10 +70,9 @@ namespace ILSpy.BamlDecompiler throw new ArgumentException("Invalid IType: " + ownerType.GetType()); } - public string RuntimeVersion { + public TargetRuntime RuntimeVersion { get { - throw new NotImplementedException(); - //return thisAssembly.MainModule.Runtime.ToString(); + return module.GetRuntime(); } } } diff --git a/ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs b/ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs index 99e07a4b5..8eea04430 100644 --- a/ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs +++ b/ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs @@ -5,14 +5,16 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; +using System.Reflection.Metadata; using System.Threading; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.CSharp; +using ICSharpCode.Decompiler.Documentation; using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; -using Mono.Cecil; +using Metadata = ICSharpCode.Decompiler.Metadata; namespace ILSpy.BamlDecompiler { @@ -29,37 +31,36 @@ namespace ILSpy.BamlDecompiler /// sealed class ConnectMethodDecompiler { - AssemblyDefinition assembly; - - public ConnectMethodDecompiler(AssemblyDefinition assembly) - { - this.assembly = assembly; - } - - public List<(LongSet, EventRegistration[])> DecompileEventMappings(string fullTypeName, CancellationToken cancellationToken) + public List<(LongSet, EventRegistration[])> DecompileEventMappings(Metadata.PEFile module, string fullTypeName, CancellationToken cancellationToken) { var result = new List<(LongSet, EventRegistration[])>(); - TypeDefinition type = this.assembly.MainModule.GetType(fullTypeName); - - if (type == null) + + var typeDefinition = (Metadata.TypeDefinition)XmlDocKeyProvider.FindMemberByKey(module, "T:" + fullTypeName); + if (typeDefinition.IsNil) return result; + + var metadata = module.GetMetadataReader(); + TypeDefinition type = metadata.GetTypeDefinition(typeDefinition.Handle); - MethodDefinition method = null; + MethodDefinition method = default; + MethodDefinitionHandle handle = default; - foreach (var m in type.Methods) { - if (m.Name == "System.Windows.Markup.IComponentConnector.Connect") { + foreach (var h in type.GetMethods()) { + var m = metadata.GetMethodDefinition(h); + if (metadata.GetString(m.Name) == "System.Windows.Markup.IComponentConnector.Connect") { + handle = h; method = m; break; } } - if (method == null) + if (handle.IsNil) return result; // decompile method and optimize the switch - var typeSystem = new DecompilerTypeSystem(method.Module); + var typeSystem = new DecompilerTypeSystem(typeDefinition.Module); var ilReader = new ILReader(typeSystem); - var function = ilReader.ReadIL(method.Body, cancellationToken); + var function = ilReader.ReadIL(typeDefinition.Module, handle, typeDefinition.Module.Reader.GetMethodBody(method.RelativeVirtualAddress), cancellationToken); var context = new ILTransformContext(function, typeSystem) { CancellationToken = cancellationToken diff --git a/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj b/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj index a9aafae32..ce9ec8a62 100644 --- a/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj +++ b/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj @@ -28,6 +28,10 @@ ..\ILSpy\bin\$(Configuration)\ + + 7.2 + + diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/ITypeResolver.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/ITypeResolver.cs index edce5c931..ab366be6b 100644 --- a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/ITypeResolver.cs +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/ITypeResolver.cs @@ -6,7 +6,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection { public interface IDotNetTypeResolver { - string RuntimeVersion { get; } + ICSharpCode.Decompiler.Metadata.TargetRuntime RuntimeVersion { get; } bool IsLocalAssembly(string name); IDotNetType GetTypeByAssemblyQualifiedName(string name); IDependencyPropertyDescriptor GetDependencyPropertyDescriptor(string name, IDotNetType ownerType, IDotNetType targetType); diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/KnownInfo.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/KnownInfo.cs index 807f69743..2ff4f0c9c 100644 --- a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/KnownInfo.cs +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/KnownInfo.cs @@ -34,10 +34,10 @@ namespace Ricciolo.StylesExplorer.MarkupReflection public KnownInfo(IDotNetTypeResolver resolver) { switch (resolver.RuntimeVersion) { - case "Net_2_0": + case ICSharpCode.Decompiler.Metadata.TargetRuntime.Net_2_0: LoadKnownAssemblies30(); break; - case "Net_4_0": + case ICSharpCode.Decompiler.Metadata.TargetRuntime.Net_4_0: LoadKnownAssemblies40(); break; default: diff --git a/ILSpy.sln b/ILSpy.sln index 4e035c102..d2cc02dd0 100644 --- a/ILSpy.sln +++ b/ILSpy.sln @@ -24,6 +24,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestPlugin", "TestPlugin\Te EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Pdb", "cecil\symbols\pdb\Mono.Cecil.Pdb.csproj", "{63E6915C-7EA4-4D76-AB28-0D7191EEA626}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.BamlDecompiler", "ILSpy.BamlDecompiler\ILSpy.BamlDecompiler.csproj", "{A6BAD2BA-76BA-461C-8B6D-418607591247}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.BamlDecompiler.Tests", "ILSpy.BamlDecompiler.Tests\ILSpy.BamlDecompiler.Tests.csproj", "{1169E6D1-1899-43D4-A500-07CE4235B388}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.AddIn", "ILSpy.AddIn\ILSpy.AddIn.csproj", "{9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0A344E19-D1FC-4F4C-8883-0844AC669113}" @@ -65,6 +69,14 @@ Global {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|Any CPU.Build.0 = net_4_0_Release|Any CPU + {A6BAD2BA-76BA-461C-8B6D-418607591247}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A6BAD2BA-76BA-461C-8B6D-418607591247}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A6BAD2BA-76BA-461C-8B6D-418607591247}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A6BAD2BA-76BA-461C-8B6D-418607591247}.Release|Any CPU.Build.0 = Release|Any CPU + {1169E6D1-1899-43D4-A500-07CE4235B388}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1169E6D1-1899-43D4-A500-07CE4235B388}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1169E6D1-1899-43D4-A500-07CE4235B388}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1169E6D1-1899-43D4-A500-07CE4235B388}.Release|Any CPU.Build.0 = Release|Any CPU {9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Debug|Any CPU.Build.0 = Debug|Any CPU {9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Release|Any CPU.ActiveCfg = Release|Any CPU