Browse Source

Refactor resource loading.

pull/2191/head
Daniel Grunwald 5 years ago
parent
commit
2d0df349d8
  1. 17
      ICSharpCode.Decompiler/Metadata/Dom.cs
  2. 6
      ILSpy.BamlDecompiler/BamlResourceEntryNode.cs
  3. 9
      ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs
  4. 41
      ILSpy/TreeNodes/ResourceNodes/CursorResourceEntryNode.cs
  5. 1
      ILSpy/TreeNodes/ResourceNodes/IResourceNodeFactory.cs
  6. 24
      ILSpy/TreeNodes/ResourceNodes/IconResourceEntryNode.cs
  7. 5
      ILSpy/TreeNodes/ResourceNodes/ImageListResourceEntryNode.cs
  8. 26
      ILSpy/TreeNodes/ResourceNodes/ImageResourceEntryNode.cs
  9. 41
      ILSpy/TreeNodes/ResourceNodes/ResourceEntryNode.cs
  10. 9
      ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs
  11. 9
      ILSpy/TreeNodes/ResourceNodes/ResourcesFileTreeNode.cs
  12. 20
      ILSpy/TreeNodes/ResourceNodes/XamlResourceNode.cs
  13. 24
      ILSpy/TreeNodes/ResourceNodes/XmlResourceNode.cs

17
ICSharpCode.Decompiler/Metadata/Dom.cs

@ -35,6 +35,23 @@ namespace ICSharpCode.Decompiler.Metadata @@ -35,6 +35,23 @@ namespace ICSharpCode.Decompiler.Metadata
public abstract Stream TryOpenStream();
}
public class ByteArrayResource : Resource
{
public override string Name { get; }
byte[] data;
public ByteArrayResource(string name, byte[] data)
{
this.Name = name ?? throw new ArgumentNullException(nameof(name));
this.data = data ?? throw new ArgumentNullException(nameof(data));
}
public override Stream TryOpenStream()
{
return new MemoryStream(data);
}
}
sealed class MetadataResource : Resource
{
public PEFile Module { get; }

6
ILSpy.BamlDecompiler/BamlResourceEntryNode.cs

@ -42,7 +42,7 @@ namespace ILSpy.BamlDecompiler @@ -42,7 +42,7 @@ namespace ILSpy.BamlDecompiler
{
public sealed class BamlResourceEntryNode : ResourceEntryNode
{
public BamlResourceEntryNode(string key, Stream data) : base(key, data)
public BamlResourceEntryNode(string key, Func<Stream> data) : base(key, data)
{
}
@ -74,8 +74,8 @@ namespace ILSpy.BamlDecompiler @@ -74,8 +74,8 @@ namespace ILSpy.BamlDecompiler
bool LoadBaml(AvalonEditTextOutput output, CancellationToken cancellationToken)
{
var asm = this.Ancestors().OfType<AssemblyTreeNode>().FirstOrDefault().LoadedAssembly;
Data.Position = 0;
XDocument xamlDocument = LoadIntoDocument(asm.GetPEFileOrNull(), asm.GetAssemblyResolver(), Data, cancellationToken);
using var data = OpenStream();
XDocument xamlDocument = LoadIntoDocument(asm.GetPEFileOrNull(), asm.GetAssemblyResolver(), data, cancellationToken);
output.Write(xamlDocument.ToString());
return true;
}

9
ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs

@ -31,13 +31,8 @@ namespace ILSpy.BamlDecompiler @@ -31,13 +31,8 @@ namespace ILSpy.BamlDecompiler
{
public ILSpyTreeNode CreateNode(Resource resource)
{
return null;
}
public ILSpyTreeNode CreateNode(string key, object data)
{
if (key.EndsWith(".baml", StringComparison.OrdinalIgnoreCase) && data is Stream stream)
return new BamlResourceEntryNode(key, stream);
if (resource.Name.EndsWith(".baml", StringComparison.OrdinalIgnoreCase))
return new BamlResourceEntryNode(resource.Name, resource.TryOpenStream);
else
return null;
}

41
ILSpy/TreeNodes/ResourceNodes/CursorResourceEntryNode.cs

@ -36,20 +36,11 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -36,20 +36,11 @@ namespace ICSharpCode.ILSpy.TreeNodes
public ILSpyTreeNode CreateNode(Resource resource)
{
Stream stream = resource.TryOpenStream();
if (stream == null)
return null;
return CreateNode(resource.Name, stream);
}
public ILSpyTreeNode CreateNode(string key, object data)
{
if (!(data is Stream))
return null;
string key = resource.Name;
foreach (string fileExt in imageFileExtensions)
{
if (key.EndsWith(fileExt, StringComparison.OrdinalIgnoreCase))
return new CursorResourceEntryNode(key, (Stream)data);
return new CursorResourceEntryNode(key, resource.TryOpenStream);
}
return null;
}
@ -57,8 +48,8 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -57,8 +48,8 @@ namespace ICSharpCode.ILSpy.TreeNodes
sealed class CursorResourceEntryNode : ResourceEntryNode
{
public CursorResourceEntryNode(string key, Stream data)
: base(key, data)
public CursorResourceEntryNode(string key, Func<Stream> openStream)
: base(key, openStream)
{
}
@ -69,19 +60,23 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -69,19 +60,23 @@ namespace ICSharpCode.ILSpy.TreeNodes
try
{
AvalonEditTextOutput output = new AvalonEditTextOutput();
Data.Position = 0;
BitmapImage image = new BitmapImage();
//HACK: windows imaging does not understand that .cur files have the same layout as .ico
// so load to data, and modify the ResourceType in the header to make look like an icon...
MemoryStream s = Data as MemoryStream;
if (null == s)
byte[] curData;
using (var data = OpenStream())
{
// data was stored in another stream type (e.g. PinnedBufferedMemoryStream)
s = new MemoryStream();
Data.CopyTo(s);
if (data == null)
return false;
//HACK: windows imaging does not understand that .cur files have the same layout as .ico
// so load to data, and modify the ResourceType in the header to make look like an icon...
MemoryStream s = data as MemoryStream;
if (s == null)
{
// data was stored in another stream type (e.g. PinnedBufferedMemoryStream)
s = new MemoryStream();
data.CopyTo(s);
}
curData = s.ToArray();
}
byte[] curData = s.ToArray();
curData[2] = 1;
using (Stream stream = new MemoryStream(curData))
{

1
ILSpy/TreeNodes/ResourceNodes/IResourceNodeFactory.cs

@ -26,6 +26,5 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -26,6 +26,5 @@ namespace ICSharpCode.ILSpy.TreeNodes
public interface IResourceNodeFactory
{
ILSpyTreeNode CreateNode(Resource resource);
ILSpyTreeNode CreateNode(string key, object data);
}
}

24
ILSpy/TreeNodes/ResourceNodes/IconResourceEntryNode.cs

@ -34,29 +34,17 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -34,29 +34,17 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
public ILSpyTreeNode CreateNode(Resource resource)
{
Stream stream = resource.TryOpenStream();
if (stream == null)
return null;
return CreateNode(resource.Name, stream);
}
public ILSpyTreeNode CreateNode(string key, object data)
{
if (data is System.Drawing.Icon)
if (resource.Name.EndsWith(".ico", StringComparison.OrdinalIgnoreCase))
{
MemoryStream s = new MemoryStream();
((System.Drawing.Icon)data).Save(s);
return new IconResourceEntryNode(key, s);
return new IconResourceEntryNode(resource.Name, resource.TryOpenStream);
}
if (data is Stream && key.EndsWith(".ico", StringComparison.OrdinalIgnoreCase))
return new IconResourceEntryNode(key, (Stream)data);
return null;
}
}
sealed class IconResourceEntryNode : ResourceEntryNode
{
public IconResourceEntryNode(string key, Stream data)
public IconResourceEntryNode(string key, Func<Stream> data)
: base(key, data)
{
}
@ -68,8 +56,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -68,8 +56,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
try
{
AvalonEditTextOutput output = new AvalonEditTextOutput();
Data.Position = 0;
IconBitmapDecoder decoder = new IconBitmapDecoder(Data, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None);
using var data = OpenStream();
if (data == null)
return false;
IconBitmapDecoder decoder = new IconBitmapDecoder(data, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None);
foreach (var frame in decoder.Frames)
{
output.Write(String.Format("{0}x{1}, {2} bit: ", frame.PixelHeight, frame.PixelWidth, frame.Thumbnail.Format.BitsPerPixel));

5
ILSpy/TreeNodes/ResourceNodes/ImageListResourceEntryNode.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System.ComponentModel.Composition;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using ICSharpCode.Decompiler;
@ -65,7 +66,9 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -65,7 +66,9 @@ namespace ICSharpCode.ILSpy.TreeNodes
int i = 0;
foreach (Image image in this.data.Images)
{
var node = ResourceEntryNode.Create("Image" + i.ToString(), image);
using var s = new MemoryStream();
image.Save(s, System.Drawing.Imaging.ImageFormat.Bmp);
var node = ResourceEntryNode.Create("Image" + i.ToString(), s.ToArray());
if (node != null)
Children.Add(node);
++i;

26
ILSpy/TreeNodes/ResourceNodes/ImageResourceEntryNode.cs

@ -36,26 +36,11 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -36,26 +36,11 @@ namespace ICSharpCode.ILSpy.TreeNodes
public ILSpyTreeNode CreateNode(Resource resource)
{
Stream stream = resource.TryOpenStream();
if (stream == null)
return null;
return CreateNode(resource.Name, stream);
}
public ILSpyTreeNode CreateNode(string key, object data)
{
if (data is System.Drawing.Image)
{
MemoryStream s = new MemoryStream();
((System.Drawing.Image)data).Save(s, System.Drawing.Imaging.ImageFormat.Bmp);
return new ImageResourceEntryNode(key, s);
}
if (!(data is Stream))
return null;
string key = resource.Name;
foreach (string fileExt in imageFileExtensions)
{
if (key.EndsWith(fileExt, StringComparison.OrdinalIgnoreCase))
return new ImageResourceEntryNode(key, (Stream)data);
return new ImageResourceEntryNode(key, resource.TryOpenStream);
}
return null;
}
@ -63,8 +48,8 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -63,8 +48,8 @@ namespace ICSharpCode.ILSpy.TreeNodes
sealed class ImageResourceEntryNode : ResourceEntryNode
{
public ImageResourceEntryNode(string key, Stream data)
: base(key, data)
public ImageResourceEntryNode(string key, Func<Stream> openStream)
: base(key, openStream)
{
}
@ -75,10 +60,9 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -75,10 +60,9 @@ namespace ICSharpCode.ILSpy.TreeNodes
try
{
AvalonEditTextOutput output = new AvalonEditTextOutput();
Data.Position = 0;
BitmapImage image = new BitmapImage();
image.BeginInit();
image.StreamSource = Data;
image.StreamSource = OpenStream();
image.EndInit();
output.AddUIElement(() => new Image { Source = image });
output.WriteLine();

41
ILSpy/TreeNodes/ResourceNodes/ResourceEntryNode.cs

@ -20,6 +20,7 @@ using System; @@ -20,6 +20,7 @@ using System;
using System.IO;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.TextView;
using Microsoft.Win32;
@ -32,42 +33,47 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -32,42 +33,47 @@ namespace ICSharpCode.ILSpy.TreeNodes
public class ResourceEntryNode : ILSpyTreeNode
{
private readonly string key;
private readonly Stream data;
private readonly Func<Stream> openStream;
public override object Text => this.key;
public override object Icon => Images.Resource;
protected Stream Data => data;
protected Stream OpenStream()
{
return openStream();
}
public ResourceEntryNode(string key, Stream data)
public ResourceEntryNode(string key, Func<Stream> openStream)
{
if (key == null)
throw new ArgumentNullException(nameof(key));
if (data == null)
throw new ArgumentNullException(nameof(data));
if (openStream == null)
throw new ArgumentNullException(nameof(openStream));
this.key = key;
this.data = data;
this.openStream = openStream;
}
public static ILSpyTreeNode Create(string key, object data)
public static ILSpyTreeNode Create(Resource resource)
{
ILSpyTreeNode result = null;
foreach (var factory in App.ExportProvider.GetExportedValues<IResourceNodeFactory>())
{
result = factory.CreateNode(key, data);
result = factory.CreateNode(resource);
if (result != null)
return result;
break;
}
var streamData = data as Stream;
if (streamData != null)
result = new ResourceEntryNode(key, data as Stream);
return result ?? new ResourceTreeNode(resource);
}
return result;
public static ILSpyTreeNode Create(string name, byte[] data)
{
return Create(new ByteArrayResource(name, data));
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
using var data = OpenStream();
language.WriteCommentLine(output, string.Format("{0} = {1}", key, data));
}
@ -77,12 +83,9 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -77,12 +83,9 @@ namespace ICSharpCode.ILSpy.TreeNodes
dlg.FileName = Path.GetFileName(DecompilerTextView.CleanUpName(key));
if (dlg.ShowDialog() == true)
{
var data = this.Data;
data.Position = 0;
using (var fs = dlg.OpenFile())
{
data.CopyTo(fs);
}
using var data = OpenStream();
using var fs = dlg.OpenFile();
data.CopyTo(fs);
}
return true;
}

9
ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs

@ -119,14 +119,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -119,14 +119,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public static ILSpyTreeNode Create(Resource resource)
{
ILSpyTreeNode result = null;
foreach (var factory in App.ExportProvider.GetExportedValues<IResourceNodeFactory>())
{
result = factory.CreateNode(resource);
if (result != null)
break;
}
return result ?? new ResourceTreeNode(resource);
return ResourceEntryNode.Create(resource);
}
}
}

9
ILSpy/TreeNodes/ResourceNodes/ResourcesFileTreeNode.cs

@ -99,14 +99,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -99,14 +99,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
if (entry.Value is byte[])
{
Children.Add(ResourceEntryNode.Create(entry.Key, new MemoryStream((byte[])entry.Value)));
return;
}
var node = ResourceEntryNode.Create(entry.Key, entry.Value);
if (node != null)
{
Children.Add(node);
Children.Add(ResourceEntryNode.Create(entry.Key, (byte[])entry.Value));
return;
}

20
ILSpy/TreeNodes/ResourceNodes/XamlResourceNode.cs

@ -34,13 +34,8 @@ namespace ICSharpCode.ILSpy.Xaml @@ -34,13 +34,8 @@ namespace ICSharpCode.ILSpy.Xaml
{
public ILSpyTreeNode CreateNode(Resource resource)
{
return null;
}
public ILSpyTreeNode CreateNode(string key, object data)
{
if (key.EndsWith(".xaml", StringComparison.OrdinalIgnoreCase) && data is Stream)
return new XamlResourceEntryNode(key, (Stream)data);
if (resource.Name.EndsWith(".xaml", StringComparison.OrdinalIgnoreCase))
return new XamlResourceEntryNode(resource.Name, resource.TryOpenStream);
else
return null;
}
@ -50,7 +45,7 @@ namespace ICSharpCode.ILSpy.Xaml @@ -50,7 +45,7 @@ namespace ICSharpCode.ILSpy.Xaml
{
string xaml;
public XamlResourceEntryNode(string key, Stream data) : base(key, data)
public XamlResourceEntryNode(string key, Func<Stream> openStream) : base(key, openStream)
{
}
@ -67,7 +62,14 @@ namespace ICSharpCode.ILSpy.Xaml @@ -67,7 +62,14 @@ namespace ICSharpCode.ILSpy.Xaml
// cache read XAML because stream will be closed after first read
if (xaml == null)
{
using (var reader = new StreamReader(Data))
using var data = OpenStream();
if (data == null)
{
output.Write("ILSpy: Failed opening resource stream.");
output.WriteLine();
return output;
}
using (var reader = new StreamReader(data))
{
xaml = reader.ReadToEnd();
}

24
ILSpy/TreeNodes/ResourceNodes/XmlResourceNode.cs

@ -36,20 +36,11 @@ namespace ICSharpCode.ILSpy.Xaml @@ -36,20 +36,11 @@ namespace ICSharpCode.ILSpy.Xaml
public ILSpyTreeNode CreateNode(Resource resource)
{
Stream stream = resource.TryOpenStream();
if (stream == null)
return null;
return CreateNode(resource.Name, stream);
}
public ILSpyTreeNode CreateNode(string key, object data)
{
if (!(data is Stream))
return null;
string key = resource.Name;
foreach (string fileExt in xmlFileExtensions)
{
if (key.EndsWith(fileExt, StringComparison.OrdinalIgnoreCase))
return new XmlResourceEntryNode(key, (Stream)data);
return new XmlResourceEntryNode(key, resource.TryOpenStream);
}
return null;
}
@ -59,7 +50,7 @@ namespace ICSharpCode.ILSpy.Xaml @@ -59,7 +50,7 @@ namespace ICSharpCode.ILSpy.Xaml
{
string xml;
public XmlResourceEntryNode(string key, Stream data)
public XmlResourceEntryNode(string key, Func<Stream> data)
: base(key, data)
{
}
@ -91,7 +82,14 @@ namespace ICSharpCode.ILSpy.Xaml @@ -91,7 +82,14 @@ namespace ICSharpCode.ILSpy.Xaml
// cache read XAML because stream will be closed after first read
if (xml == null)
{
using (var reader = new StreamReader(Data))
using var data = OpenStream();
if (data == null)
{
output.Write("ILSpy: Failed opening resource stream.");
output.WriteLine();
return output;
}
using (var reader = new StreamReader(data))
{
xml = reader.ReadToEnd();
}

Loading…
Cancel
Save