Browse Source

Merge pull request #2857 from icsharpcode/handle-logical-resource-names

pull/2863/head
Siegfried Pammer 3 years ago committed by GitHub
parent
commit
fb9b665325
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectFileWriter.cs
  2. 14
      ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterDefault.cs
  3. 31
      ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterSdkStyle.cs
  4. 131
      ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs
  5. 2
      ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs
  6. 4
      ILSpy/Languages/CSharpLanguage.cs
  7. 3
      ILSpy/Languages/IResourceFileHandler.cs

5
ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectFileWriter.cs

@ -34,9 +34,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -34,9 +34,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
/// </summary>
/// <param name="target">The target to write to.</param>
/// <param name="project">The information about the project being created.</param>
/// <param name="files">A collection of source files to be included into the project, each item is a pair
/// of the project entry type and the file path.</param>
/// <param name="files">A collection of source files to be included into the project.</param>
/// <param name="module">The module being decompiled.</param>
void Write(TextWriter target, IProjectInfoProvider project, IEnumerable<(string itemType, string fileName)> files, PEFile module);
void Write(TextWriter target, IProjectInfoProvider project, IEnumerable<ProjectItemInfo> files, PEFile module);
}
}

14
ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterDefault.cs

@ -25,6 +25,7 @@ using System.Xml; @@ -25,6 +25,7 @@ using System.Xml;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Solution;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
{
@ -43,7 +44,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -43,7 +44,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
public void Write(
TextWriter target,
IProjectInfoProvider project,
IEnumerable<(string itemType, string fileName)> files,
IEnumerable<ProjectItemInfo> files,
PEFile module)
{
const string ns = "http://schemas.microsoft.com/developer/msbuild/2003";
@ -162,13 +163,18 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -162,13 +163,18 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
}
w.WriteEndElement(); // </ItemGroup> (References)
foreach (IGrouping<string, string> gr in from f in files group f.fileName by f.itemType into g orderby g.Key select g)
foreach (IGrouping<string, ProjectItemInfo> gr in files.GroupBy(f => f.ItemType).OrderBy(g => g.Key))
{
w.WriteStartElement("ItemGroup");
foreach (string file in gr.OrderBy(f => f, StringComparer.OrdinalIgnoreCase))
foreach (var item in gr.OrderBy(f => f.FileName, StringComparer.OrdinalIgnoreCase))
{
w.WriteStartElement(gr.Key);
w.WriteAttributeString("Include", file);
w.WriteAttributeString("Include", item.FileName);
if (item.AdditionalProperties != null)
{
foreach (var (key, value) in item.AdditionalProperties)
w.WriteAttributeString(key, value);
}
w.WriteEndElement();
}
w.WriteEndElement();

31
ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterSdkStyle.cs

@ -66,7 +66,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -66,7 +66,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
public void Write(
TextWriter target,
IProjectInfoProvider project,
IEnumerable<(string itemType, string fileName)> files,
IEnumerable<ProjectItemInfo> files,
PEFile module)
{
using (XmlTextWriter xmlWriter = new XmlTextWriter(target))
@ -76,7 +76,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -76,7 +76,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
}
}
static void Write(XmlTextWriter xml, IProjectInfoProvider project, IEnumerable<(string itemType, string fileName)> files, PEFile module)
static void Write(XmlTextWriter xml, IProjectInfoProvider project, IEnumerable<ProjectItemInfo> files, PEFile module)
{
xml.WriteStartElement("Project");
@ -188,27 +188,27 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -188,27 +188,27 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
}
}
static void WriteMiscellaneousPropertyGroup(XmlTextWriter xml, IEnumerable<(string itemType, string fileName)> files)
static void WriteMiscellaneousPropertyGroup(XmlTextWriter xml, IEnumerable<ProjectItemInfo> files)
{
var (itemType, fileName) = files.FirstOrDefault(t => t.itemType == "ApplicationIcon");
var (itemType, fileName) = files.FirstOrDefault(t => t.ItemType == "ApplicationIcon");
if (fileName != null)
xml.WriteElementString("ApplicationIcon", fileName);
(itemType, fileName) = files.FirstOrDefault(t => t.itemType == "ApplicationManifest");
(itemType, fileName) = files.FirstOrDefault(t => t.ItemType == "ApplicationManifest");
if (fileName != null)
xml.WriteElementString("ApplicationManifest", fileName);
if (files.Any(t => t.itemType == "EmbeddedResource"))
if (files.Any(t => t.ItemType == "EmbeddedResource"))
xml.WriteElementString("RootNamespace", string.Empty);
// TODO: We should add CustomToolNamespace for resources, otherwise we should add empty RootNamespace
}
static void WriteResources(XmlTextWriter xml, IEnumerable<(string itemType, string fileName)> files)
static void WriteResources(XmlTextWriter xml, IEnumerable<ProjectItemInfo> files)
{
// remove phase
foreach (var (itemType, fileName) in files.Where(t => t.itemType == "EmbeddedResource"))
foreach (var item in files.Where(t => t.ItemType == "EmbeddedResource"))
{
string buildAction = Path.GetExtension(fileName).ToUpperInvariant() switch {
string buildAction = Path.GetExtension(item.FileName).ToUpperInvariant() switch {
".CS" => "Compile",
".RESX" => "EmbeddedResource",
_ => "None"
@ -217,18 +217,23 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -217,18 +217,23 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
continue;
xml.WriteStartElement(buildAction);
xml.WriteAttributeString("Remove", fileName);
xml.WriteAttributeString("Remove", item.FileName);
xml.WriteEndElement();
}
// include phase
foreach (var (itemType, fileName) in files.Where(t => t.itemType == "EmbeddedResource"))
foreach (var item in files.Where(t => t.ItemType == "EmbeddedResource"))
{
if (Path.GetExtension(fileName) == ".resx")
if (Path.GetExtension(item.FileName) == ".resx")
continue;
xml.WriteStartElement("EmbeddedResource");
xml.WriteAttributeString("Include", fileName);
xml.WriteAttributeString("Include", item.FileName);
if (item.AdditionalProperties != null)
{
foreach (var (key, value) in item.AdditionalProperties)
xml.WriteAttributeString(key, value);
}
xml.WriteEndElement();
}
}

131
ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs

@ -151,8 +151,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -151,8 +151,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
TargetDirectory = targetDirectory;
directories.Clear();
var resources = WriteResourceFilesInProject(moduleDefinition).ToList();
var files = WriteCodeFilesInProject(moduleDefinition, resources.SelectMany(r => r.partialTypes ?? Enumerable.Empty<PartialTypeInfo>()).ToList(), cancellationToken).ToList();
files.AddRange(resources.Select(r => (r.itemType, r.fileName)));
var files = WriteCodeFilesInProject(moduleDefinition, resources.SelectMany(r => r.PartialTypes ?? Enumerable.Empty<PartialTypeInfo>()).ToList(), cancellationToken).ToList();
files.AddRange(resources);
files.AddRange(WriteMiscellaneousFilesInProject(moduleDefinition));
if (StrongNameKeyFile != null)
{
@ -190,7 +190,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -190,7 +190,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
return decompiler;
}
IEnumerable<(string itemType, string fileName)> WriteAssemblyInfo(DecompilerTypeSystem ts, CancellationToken cancellationToken)
IEnumerable<ProjectItemInfo> WriteAssemblyInfo(DecompilerTypeSystem ts, CancellationToken cancellationToken)
{
var decompiler = CreateDecompiler(ts);
decompiler.CancellationToken = cancellationToken;
@ -205,10 +205,10 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -205,10 +205,10 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
{
syntaxTree.AcceptVisitor(new CSharpOutputVisitor(w, Settings.CSharpFormattingOptions));
}
return new[] { ("Compile", assemblyInfo) };
return new[] { new ProjectItemInfo("Compile", assemblyInfo) };
}
IEnumerable<(string itemType, string fileName)> WriteCodeFilesInProject(Metadata.PEFile module, IList<PartialTypeInfo> partialTypes, CancellationToken cancellationToken)
IEnumerable<ProjectItemInfo> WriteCodeFilesInProject(Metadata.PEFile module, IList<PartialTypeInfo> partialTypes, CancellationToken cancellationToken)
{
var metadata = module.Metadata;
var files = module.Metadata.GetTopLevelTypeDefinitions().Where(td => IncludeTypeWhenDecompilingProject(module, td))
@ -229,12 +229,12 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -229,12 +229,12 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
progress.TotalUnits = files.Count;
}
return files.Select(f => ("Compile", f.Key)).Concat(WriteAssemblyInfo(ts, cancellationToken));
return files.Select(f => new ProjectItemInfo("Compile", f.Key)).Concat(WriteAssemblyInfo(ts, cancellationToken));
string GetFileFileNameForHandle(TypeDefinitionHandle h)
{
var type = metadata.GetTypeDefinition(h);
string file = CleanUpFileName(metadata.GetString(type.Name)) + ".cs";
string file = SanitizeFileName(metadata.GetString(type.Name) + ".cs");
string ns = metadata.GetString(type.Namespace);
if (string.IsNullOrEmpty(ns))
{
@ -259,45 +259,43 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -259,45 +259,43 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
CancellationToken = cancellationToken
},
delegate (IGrouping<string, TypeDefinitionHandle> file) {
using (StreamWriter w = new StreamWriter(Path.Combine(TargetDirectory, file.Key)))
try
{
try
using StreamWriter w = new StreamWriter(Path.Combine(TargetDirectory, file.Key));
CSharpDecompiler decompiler = CreateDecompiler(ts);
foreach (var partialType in partialTypes)
{
CSharpDecompiler decompiler = CreateDecompiler(ts);
decompiler.AddPartialTypeDefinition(partialType);
}
decompiler.CancellationToken = cancellationToken;
var declaredTypes = file.ToArray();
var syntaxTree = decompiler.DecompileTypes(declaredTypes);
foreach (var partialType in partialTypes)
foreach (var node in syntaxTree.Descendants)
{
var td = (node.GetResolveResult() as TypeResolveResult)?.Type.GetDefinition();
if (td?.ParentModule != ts.MainModule)
continue;
while (td?.DeclaringTypeDefinition != null)
{
decompiler.AddPartialTypeDefinition(partialType);
td = td.DeclaringTypeDefinition;
}
decompiler.CancellationToken = cancellationToken;
var declaredTypes = file.ToArray();
var syntaxTree = decompiler.DecompileTypes(declaredTypes);
foreach (var node in syntaxTree.Descendants)
if (td != null && td.MetadataToken is { IsNil: false } token && !processedTypes.Contains((TypeDefinitionHandle)token))
{
var td = (node.GetResolveResult() as TypeResolveResult)?.Type.GetDefinition();
if (td?.ParentModule != ts.MainModule)
continue;
while (td?.DeclaringTypeDefinition != null)
{
td = td.DeclaringTypeDefinition;
}
if (td != null && td.MetadataToken is { IsNil: false } token && !processedTypes.Contains((TypeDefinitionHandle)token))
lock (workList)
{
lock (workList)
{
workList.Add((TypeDefinitionHandle)token);
}
workList.Add((TypeDefinitionHandle)token);
}
}
syntaxTree.AcceptVisitor(new CSharpOutputVisitor(w, Settings.CSharpFormattingOptions));
}
catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException))
{
throw new DecompilerException(module, $"Error decompiling for '{file.Key}'", innerException);
}
syntaxTree.AcceptVisitor(new CSharpOutputVisitor(w, Settings.CSharpFormattingOptions));
}
catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException))
{
throw new DecompilerException(module, $"Error decompiling for '{file.Key}'", innerException);
}
progress.Status = file.Key;
Interlocked.Increment(ref progress.UnitsCompleted);
@ -308,7 +306,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -308,7 +306,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
#endregion
#region WriteResourceFilesInProject
protected virtual IEnumerable<(string itemType, string fileName, List<PartialTypeInfo> partialTypes)> WriteResourceFilesInProject(Metadata.PEFile module)
protected virtual IEnumerable<ProjectItemInfo> WriteResourceFilesInProject(Metadata.PEFile module)
{
foreach (var r in module.Resources.Where(r => r.ResourceType == ResourceType.Embedded))
{
@ -318,7 +316,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -318,7 +316,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
if (r.Name.EndsWith(".resources", StringComparison.OrdinalIgnoreCase))
{
bool decodedIntoIndividualFiles;
var individualResources = new List<(string itemType, string fileName, List<PartialTypeInfo> partialTypes)>();
var individualResources = new List<ProjectItemInfo>();
try
{
var resourcesFile = new ResourcesFile(stream);
@ -378,12 +376,12 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -378,12 +376,12 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
stream.Position = 0;
stream.CopyTo(fs);
}
yield return ("EmbeddedResource", fileName, null);
yield return new ProjectItemInfo("EmbeddedResource", fileName).With("LogicalName", r.Name);
}
}
}
protected virtual IEnumerable<(string itemType, string fileName, List<PartialTypeInfo> partialTypes)> WriteResourceToFile(string fileName, string resourceName, Stream entryStream)
protected virtual IEnumerable<ProjectItemInfo> WriteResourceToFile(string fileName, string resourceName, Stream entryStream)
{
if (fileName.EndsWith(".resources", StringComparison.OrdinalIgnoreCase))
{
@ -398,7 +396,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -398,7 +396,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
writer.AddResource(entry.Key, entry.Value);
}
}
return new[] { ("EmbeddedResource", resx, (List<PartialTypeInfo>)null) };
return new[] { new ProjectItemInfo("EmbeddedResource", resx).With("LogicalName", resourceName) };
}
catch (BadImageFormatException)
{
@ -413,7 +411,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -413,7 +411,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
{
entryStream.CopyTo(fs);
}
return new[] { ("EmbeddedResource", fileName, (List<PartialTypeInfo>)null) };
return new[] { new ProjectItemInfo("EmbeddedResource", fileName).With("LogicalName", resourceName) };
}
string GetFileNameForResource(string fullName)
@ -426,7 +424,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -426,7 +424,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
// the directory part Namespace1\Namespace2\... reuses as many existing directories as
// possible, and only the remaining name parts are used as prefix for the filename.
// This is not affected by the UseNestedDirectoriesForNamespaces setting.
string[] splitName = fullName.Split(Path.DirectorySeparatorChar);
string[] splitName = fullName.Split('\\', '/');
string fileName = string.Join(".", splitName);
string separator = Path.DirectorySeparatorChar.ToString();
for (int i = splitName.Length - 1; i > 0; i--)
@ -444,7 +442,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -444,7 +442,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
#endregion
#region WriteMiscellaneousFilesInProject
protected virtual IEnumerable<(string itemType, string fileName)> WriteMiscellaneousFilesInProject(PEFile module)
protected virtual IEnumerable<ProjectItemInfo> WriteMiscellaneousFilesInProject(PEFile module)
{
var resources = module.Reader.ReadWin32Resources();
if (resources == null)
@ -454,21 +452,21 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -454,21 +452,21 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
if (appIcon != null)
{
File.WriteAllBytes(Path.Combine(TargetDirectory, "app.ico"), appIcon);
yield return ("ApplicationIcon", "app.ico");
yield return new ProjectItemInfo("ApplicationIcon", "app.ico");
}
byte[] appManifest = CreateApplicationManifest(resources);
if (appManifest != null && !IsDefaultApplicationManifest(appManifest))
{
File.WriteAllBytes(Path.Combine(TargetDirectory, "app.manifest"), appManifest);
yield return ("ApplicationManifest", "app.manifest");
yield return new ProjectItemInfo("ApplicationManifest", "app.manifest");
}
var appConfig = module.FileName + ".config";
if (File.Exists(appConfig))
{
File.Copy(appConfig, Path.Combine(TargetDirectory, "app.config"), overwrite: true);
yield return ("ApplicationConfig", Path.GetFileName(appConfig));
yield return new ProjectItemInfo("ApplicationConfig", Path.GetFileName(appConfig));
}
}
@ -618,10 +616,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -618,10 +616,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
/// </summary>
static string CleanUpName(string text, bool separateAtDots, bool treatAsFileName)
{
// Remove anything that could be confused with a rooted path.
int pos = text.IndexOf(':');
if (pos > 0)
text = text.Substring(0, pos);
pos = text.IndexOf('`');
if (pos > 0)
text = text.Substring(0, pos);
text = text.Trim();
@ -652,6 +648,12 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -652,6 +648,12 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
}
}
}
// Remove generics
pos = text.IndexOf('`');
if (pos > 0)
{
text = text.Substring(0, pos).Trim();
}
// Whitelist allowed characters, replace everything else:
StringBuilder b = new StringBuilder(text.Length + (extension?.Length ?? 0));
foreach (var c in text)
@ -693,7 +695,15 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -693,7 +695,15 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
b.Append('-');
string name = b.ToString();
if (extension != null)
{
// make sure that adding the extension to the filename
// does not exceed maxSegmentLength.
// trim the name, if necessary.
if (name.Length + extension.Length > maxSegmentLength)
name = name.Remove(name.Length - extension.Length);
name += extension;
}
if (IsReservedFileSystemName(name))
return name + "_";
else if (name == ".")
@ -753,4 +763,25 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -753,4 +763,25 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
return TargetServices.DetectTargetFramework(module).Moniker != null;
}
}
public record struct ProjectItemInfo(string ItemType, string FileName)
{
public List<PartialTypeInfo> PartialTypes { get; set; } = null;
public Dictionary<string, string> AdditionalProperties { get; set; } = null;
public ProjectItemInfo With(string name, string value)
{
AdditionalProperties ??= new Dictionary<string, string>();
AdditionalProperties.Add(name, value);
return this;
}
public ProjectItemInfo With(IEnumerable<KeyValuePair<string, string>> pairs)
{
AdditionalProperties ??= new Dictionary<string, string>();
AdditionalProperties.AddRange(pairs);
return this;
}
}
}

2
ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs

@ -72,6 +72,8 @@ namespace ILSpy.BamlDecompiler @@ -72,6 +72,8 @@ namespace ILSpy.BamlDecompiler
{
fileName = Path.ChangeExtension(fileName, ".xaml");
}
context.AdditionalProperties.Add("Generator", "MSBuild:Compile");
context.AdditionalProperties.Add("SubType", "Designer");
string saveFileName = Path.Combine(context.DecompilationOptions.SaveAsProjectDirectory, fileName);
Directory.CreateDirectory(Path.GetDirectoryName(saveFileName));
result.Xaml.Save(saveFileName);

4
ILSpy/Languages/CSharpLanguage.cs

@ -517,7 +517,7 @@ namespace ICSharpCode.ILSpy @@ -517,7 +517,7 @@ namespace ICSharpCode.ILSpy
this.options = options;
}
protected override IEnumerable<(string itemType, string fileName, List<PartialTypeInfo> partialTypes)> WriteResourceToFile(string fileName, string resourceName, Stream entryStream)
protected override IEnumerable<ProjectItemInfo> WriteResourceToFile(string fileName, string resourceName, Stream entryStream)
{
var context = new ResourceFileHandlerContext(options);
foreach (var handler in App.ExportProvider.GetExportedValues<IResourceFileHandler>())
@ -527,7 +527,7 @@ namespace ICSharpCode.ILSpy @@ -527,7 +527,7 @@ namespace ICSharpCode.ILSpy
entryStream.Position = 0;
fileName = handler.WriteResourceToFile(assembly, fileName, entryStream, context);
return new[] { (handler.EntryType, fileName, context.PartialTypes) };
return new[] { new ProjectItemInfo(handler.EntryType, fileName) { PartialTypes = context.PartialTypes }.With(context.AdditionalProperties) };
}
}
return base.WriteResourceToFile(fileName, resourceName, entryStream);

3
ILSpy/Languages/IResourceFileHandler.cs

@ -36,6 +36,9 @@ namespace ICSharpCode.ILSpy @@ -36,6 +36,9 @@ namespace ICSharpCode.ILSpy
readonly List<PartialTypeInfo> partialTypes = new();
internal List<PartialTypeInfo> PartialTypes => partialTypes;
readonly Dictionary<string, string> additionalProperties = new();
public Dictionary<string, string> AdditionalProperties => additionalProperties;
public DecompilationOptions DecompilationOptions { get; }
public ResourceFileHandlerContext(DecompilationOptions options)

Loading…
Cancel
Save