diff --git a/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs b/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs
index 21ea662a6..76ecae963 100644
--- a/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs
+++ b/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs
@@ -7,6 +7,10 @@ using System.ComponentModel.Composition;
using System.IO;
using ICSharpCode.ILSpy.TreeNodes;
+using ICSharpCode.ILSpy;
+using System.Resources;
+using System.Collections;
+using System.Linq;
namespace ILSpy.BamlDecompiler
{
@@ -26,4 +30,19 @@ namespace ILSpy.BamlDecompiler
return null;
}
}
+
+ [Export(typeof(IResourceFileHandler))]
+ public sealed class BamlResourceFileHandler : IResourceFileHandler
+ {
+ public string EntryType => "Page";
+ public bool CanHandle(string name, DecompilationOptions options) => name.EndsWith(".baml", StringComparison.OrdinalIgnoreCase);
+
+ public string WriteResourceToFile(LoadedAssembly assembly, string fileName, Stream stream, DecompilationOptions options)
+ {
+ var document = BamlResourceEntryNode.LoadIntoDocument(assembly.GetAssemblyResolver(), assembly.AssemblyDefinition, stream);
+ fileName = Path.ChangeExtension(fileName, ".xaml");
+ document.Save(Path.Combine(options.SaveAsProjectDirectory, fileName));
+ return fileName;
+ }
+ }
}
diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj
index 5c6e84f5d..243e2275a 100644
--- a/ILSpy/ILSpy.csproj
+++ b/ILSpy/ILSpy.csproj
@@ -137,6 +137,7 @@
+
diff --git a/ILSpy/Languages/CSharpLanguage.cs b/ILSpy/Languages/CSharpLanguage.cs
index 031fa4247..51e81a9b4 100644
--- a/ILSpy/Languages/CSharpLanguage.cs
+++ b/ILSpy/Languages/CSharpLanguage.cs
@@ -511,63 +511,46 @@ namespace ICSharpCode.ILSpy
#region WriteResourceFilesInProject
IEnumerable> WriteResourceFilesInProject(LoadedAssembly assembly, DecompilationOptions options, HashSet directories)
{
- //AppDomain bamlDecompilerAppDomain = null;
- //try {
- foreach (EmbeddedResource r in assembly.ModuleDefinition.Resources.OfType()) {
- string fileName;
- Stream s = r.GetResourceStream();
- s.Position = 0;
- if (r.Name.EndsWith(".g.resources", StringComparison.OrdinalIgnoreCase)) {
- IEnumerable rs = null;
- try {
- rs = new ResourceSet(s).Cast();
+ foreach (EmbeddedResource r in assembly.ModuleDefinition.Resources.OfType()) {
+ Stream stream = r.GetResourceStream();
+ stream.Position = 0;
+
+ IEnumerable entries;
+ if (r.Name.EndsWith(".resources", StringComparison.OrdinalIgnoreCase) && GetEntries(stream, out entries) && entries.All(e => e.Value is Stream)) {
+ foreach (var pair in entries) {
+ string fileName = Path.Combine(((string)pair.Key).Split('/').Select(p => TextView.DecompilerTextView.CleanUpName(p)).ToArray());
+ string dirName = Path.GetDirectoryName(fileName);
+ if (!string.IsNullOrEmpty(dirName) && directories.Add(dirName)) {
+ Directory.CreateDirectory(Path.Combine(options.SaveAsProjectDirectory, dirName));
}
- catch (ArgumentException) {
+ Stream entryStream = (Stream)pair.Value;
+ bool handled = false;
+ foreach (var handler in App.CompositionContainer.GetExportedValues()) {
+ if (handler.CanHandle(fileName, options)) {
+ handled = true;
+ entryStream.Position = 0;
+ yield return Tuple.Create(handler.EntryType, handler.WriteResourceToFile(assembly, fileName, entryStream, options));
+ break;
+ }
}
- if (rs != null && rs.All(e => e.Value is Stream)) {
- foreach (var pair in rs) {
- fileName = Path.Combine(((string)pair.Key).Split('/').Select(p => TextView.DecompilerTextView.CleanUpName(p)).ToArray());
- string dirName = Path.GetDirectoryName(fileName);
- if (!string.IsNullOrEmpty(dirName) && directories.Add(dirName)) {
- Directory.CreateDirectory(Path.Combine(options.SaveAsProjectDirectory, dirName));
- }
- Stream entryStream = (Stream)pair.Value;
+ if (!handled) {
+ using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write))
+ {
entryStream.Position = 0;
- if (fileName.EndsWith(".baml", StringComparison.OrdinalIgnoreCase)) {
-// MemoryStream ms = new MemoryStream();
-// entryStream.CopyTo(ms);
- // TODO implement extension point
-// var decompiler = Baml.BamlResourceEntryNode.CreateBamlDecompilerInAppDomain(ref bamlDecompilerAppDomain, assembly.FileName);
-// string xaml = null;
-// try {
-// xaml = decompiler.DecompileBaml(ms, assembly.FileName, new ConnectMethodDecompiler(assembly), new AssemblyResolver(assembly));
-// }
-// catch (XamlXmlWriterException) { } // ignore XAML writer exceptions
-// if (xaml != null) {
-// File.WriteAllText(Path.Combine(options.SaveAsProjectDirectory, Path.ChangeExtension(fileName, ".xaml")), xaml);
-// yield return Tuple.Create("Page", Path.ChangeExtension(fileName, ".xaml"));
-// continue;
-// }
- }
- using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write)) {
- entryStream.CopyTo(fs);
- }
- yield return Tuple.Create("Resource", fileName);
+ entryStream.CopyTo(fs);
}
- continue;
+ yield return Tuple.Create("EmbeddedResource", fileName);
}
}
- fileName = GetFileNameForResource(r.Name, directories);
- using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write)) {
- s.CopyTo(fs);
+ } else {
+ string fileName = GetFileNameForResource(r.Name, directories);
+ using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write))
+ {
+ stream.CopyTo(fs);
}
yield return Tuple.Create("EmbeddedResource", fileName);
}
- //}
- //finally {
- // if (bamlDecompilerAppDomain != null)
- // AppDomain.Unload(bamlDecompilerAppDomain);
- //}
+ }
}
string GetFileNameForResource(string fullName, HashSet directories)
@@ -584,6 +567,17 @@ namespace ICSharpCode.ILSpy
}
return fileName;
}
+
+ bool GetEntries(Stream stream, out IEnumerable entries)
+ {
+ try {
+ entries = new ResourceSet(stream).Cast();
+ return true;
+ } catch (ArgumentException) {
+ entries = null;
+ return false;
+ }
+ }
#endregion
AstBuilder CreateAstBuilder(DecompilationOptions options, ModuleDefinition currentModule = null, TypeDefinition currentType = null, bool isSingleMember = false)
diff --git a/ILSpy/Languages/IResourceFileHandler.cs b/ILSpy/Languages/IResourceFileHandler.cs
new file mode 100644
index 000000000..fd040b1a1
--- /dev/null
+++ b/ILSpy/Languages/IResourceFileHandler.cs
@@ -0,0 +1,12 @@
+using System;
+using System.IO;
+
+namespace ICSharpCode.ILSpy
+{
+ public interface IResourceFileHandler
+ {
+ string EntryType { get; }
+ bool CanHandle(string name, DecompilationOptions options);
+ string WriteResourceToFile(LoadedAssembly assembly, string fileName, Stream stream, DecompilationOptions options);
+ }
+}
diff --git a/ILSpy/VB/VBLanguage.cs b/ILSpy/VB/VBLanguage.cs
index 4aad4a870..d9e9801e2 100644
--- a/ILSpy/VB/VBLanguage.cs
+++ b/ILSpy/VB/VBLanguage.cs
@@ -324,72 +324,59 @@ namespace ICSharpCode.ILSpy.VB
#region WriteResourceFilesInProject
IEnumerable> WriteResourceFilesInProject(LoadedAssembly assembly, DecompilationOptions options, HashSet directories)
{
- //AppDomain bamlDecompilerAppDomain = null;
- //try {
- foreach (EmbeddedResource r in assembly.ModuleDefinition.Resources.OfType()) {
- string fileName;
- Stream s = r.GetResourceStream();
- s.Position = 0;
- if (r.Name.EndsWith(".g.resources", StringComparison.OrdinalIgnoreCase)) {
- IEnumerable rs = null;
- try {
- rs = new ResourceSet(s).Cast();
+ foreach (EmbeddedResource r in assembly.ModuleDefinition.Resources.OfType()) {
+ Stream stream = r.GetResourceStream();
+ stream.Position = 0;
+
+ IEnumerable entries;
+ if (r.Name.EndsWith(".resources", StringComparison.OrdinalIgnoreCase) && GetEntries(stream, out entries) && entries.All(e => e.Value is Stream)) {
+ foreach (var pair in entries) {
+ string fileName = Path.Combine(((string)pair.Key).Split('/').Select(p => TextView.DecompilerTextView.CleanUpName(p)).ToArray());
+ string dirName = Path.GetDirectoryName(fileName);
+ if (!string.IsNullOrEmpty(dirName) && directories.Add(dirName))
+ {
+ Directory.CreateDirectory(Path.Combine(options.SaveAsProjectDirectory, dirName));
}
- catch (ArgumentException) {
+ Stream entryStream = (Stream)pair.Value;
+ bool handled = false;
+ foreach (var handler in App.CompositionContainer.GetExportedValues())
+ {
+ if (handler.CanHandle(fileName, options)) {
+ handled = true;
+ entryStream.Position = 0;
+ yield return Tuple.Create(handler.EntryType, handler.WriteResourceToFile(assembly, fileName, entryStream, options));
+ break;
+ }
}
- if (rs != null && rs.All(e => e.Value is Stream)) {
- foreach (var pair in rs) {
- fileName = Path.Combine(((string)pair.Key).Split('/').Select(p => TextView.DecompilerTextView.CleanUpName(p)).ToArray());
- string dirName = Path.GetDirectoryName(fileName);
- if (!string.IsNullOrEmpty(dirName) && directories.Add(dirName)) {
- Directory.CreateDirectory(Path.Combine(options.SaveAsProjectDirectory, dirName));
- }
- Stream entryStream = (Stream)pair.Value;
+ if (!handled) {
+ using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write))
+ {
entryStream.Position = 0;
- if (fileName.EndsWith(".baml", StringComparison.OrdinalIgnoreCase)) {
- //MemoryStream ms = new MemoryStream();
- //entryStream.CopyTo(ms);
- // TODO implement extension point
-// var decompiler = Baml.BamlResourceEntryNode.CreateBamlDecompilerInAppDomain(ref bamlDecompilerAppDomain, assembly.FileName);
-// string xaml = null;
-// try {
-// xaml = decompiler.DecompileBaml(ms, assembly.FileName, new ConnectMethodDecompiler(assembly), new AssemblyResolver(assembly));
-// }
-// catch (XamlXmlWriterException) { } // ignore XAML writer exceptions
-// if (xaml != null) {
-// File.WriteAllText(Path.Combine(options.SaveAsProjectDirectory, Path.ChangeExtension(fileName, ".xaml")), xaml);
-// yield return Tuple.Create("Page", Path.ChangeExtension(fileName, ".xaml"));
-// continue;
-// }
- }
- using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write)) {
- entryStream.CopyTo(fs);
- }
- yield return Tuple.Create("Resource", fileName);
+ entryStream.CopyTo(fs);
}
- continue;
+ yield return Tuple.Create("EmbeddedResource", fileName);
}
}
- fileName = GetFileNameForResource(r.Name, directories);
- using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write)) {
- s.CopyTo(fs);
+ } else {
+ string fileName = GetFileNameForResource(r.Name, directories);
+ using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write))
+ {
+ stream.CopyTo(fs);
}
yield return Tuple.Create("EmbeddedResource", fileName);
}
- //}
- //finally {
- // if (bamlDecompilerAppDomain != null)
- // AppDomain.Unload(bamlDecompilerAppDomain);
- //}
+ }
}
string GetFileNameForResource(string fullName, HashSet directories)
{
string[] splitName = fullName.Split('.');
string fileName = TextView.DecompilerTextView.CleanUpName(fullName);
- for (int i = splitName.Length - 1; i > 0; i--) {
+ for (int i = splitName.Length - 1; i > 0; i--)
+ {
string ns = string.Join(".", splitName, 0, i);
- if (directories.Contains(ns)) {
+ if (directories.Contains(ns))
+ {
string name = string.Join(".", splitName, i, splitName.Length - i);
fileName = Path.Combine(ns, TextView.DecompilerTextView.CleanUpName(name));
break;
@@ -397,8 +384,22 @@ namespace ICSharpCode.ILSpy.VB
}
return fileName;
}
+
+ bool GetEntries(Stream stream, out IEnumerable entries)
+ {
+ try
+ {
+ entries = new ResourceSet(stream).Cast();
+ return true;
+ }
+ catch (ArgumentException)
+ {
+ entries = null;
+ return false;
+ }
+ }
#endregion
-
+
public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options)
{
WriteCommentLine(output, TypeToString(method.DeclaringType, includeNamespace: true));