diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
index 03432b95f..5af3b8fab 100644
--- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
+++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
@@ -17,6 +17,7 @@
false
True
+ True
True
..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.snk
@@ -61,6 +62,7 @@
+
@@ -113,6 +115,7 @@
+
@@ -337,6 +340,7 @@
+
diff --git a/ICSharpCode.Decompiler.Tests/Util/FileUtilityTests.cs b/ICSharpCode.Decompiler.Tests/Util/FileUtilityTests.cs
index cef3d91f3..e188f9478 100644
--- a/ICSharpCode.Decompiler.Tests/Util/FileUtilityTests.cs
+++ b/ICSharpCode.Decompiler.Tests/Util/FileUtilityTests.cs
@@ -16,9 +16,11 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
+using ICSharpCode.Decompiler.Util;
+
using NUnit.Framework;
-namespace ICSharpCode.Decompiler.Util
+namespace ICSharpCode.Decompiler.Tests.Util
{
[TestFixture]
public class FileUtilityTests
diff --git a/ICSharpCode.Decompiler.Tests/Util/ResourceReaderWriterTests.cs b/ICSharpCode.Decompiler.Tests/Util/ResourceReaderWriterTests.cs
new file mode 100644
index 000000000..cad0afa93
--- /dev/null
+++ b/ICSharpCode.Decompiler.Tests/Util/ResourceReaderWriterTests.cs
@@ -0,0 +1,189 @@
+// Copyright (c) 2023 Siegfried Pammer
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Xml.Linq;
+using System.Xml.XPath;
+
+using ICSharpCode.Decompiler.Util;
+
+using NUnit.Framework;
+using NUnit.Framework.Internal;
+
+namespace ICSharpCode.Decompiler.Tests.Util
+{
+ [TestFixture]
+ public class ResourceReaderWriterTests
+ {
+ const string WinFormsAssemblyName = ", System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
+ const string MSCorLibAssemblyName = ", mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
+
+ [Serializable]
+ public class SerializableClass
+ {
+ public string Name { get; set; }
+ public int Age { get; set; }
+ }
+
+ static readonly object[][] TestWriteCases = {
+ new object[] { "Decimal", 1.0m, "1.0", "System.Decimal" + MSCorLibAssemblyName },
+ new object[] { "TimeSpan", TimeSpan.FromSeconds(42), "00:00:42", "System.TimeSpan" + MSCorLibAssemblyName },
+ new object[] { "DateTime", DateTime.Parse("06/18/2023 21:36:30", CultureInfo.InvariantCulture), "06/18/2023 21:36:30", "System.DateTime" + MSCorLibAssemblyName },
+ };
+
+ static readonly object[][] TestReadCases = {
+ new object[] { "Decimal", 1.0m },
+ new object[] { "TimeSpan", TimeSpan.FromSeconds(42) },
+ new object[] { "DateTime", DateTime.Parse("06/18/2023 21:36:30", CultureInfo.InvariantCulture) },
+ };
+
+ static MemoryStream ProduceResourcesTestFile(string name, T value)
+ {
+ var ms = new MemoryStream();
+ var writer = new ResourceWriter(ms);
+ writer.AddResource(name, value);
+ writer.Generate();
+ ms.Position = 0;
+ return ms;
+ }
+
+ static XElement ProduceResXTest(string name, T value)
+ {
+ using var ms = new MemoryStream();
+ var writer = new ResXResourceWriter(ms);
+ writer.AddResource(name, value);
+ writer.Generate();
+ ms.Position = 0;
+ var doc = XDocument.Load(ms);
+ return doc.XPathSelectElement(".//data");
+ }
+
+ [TestCase("Null", null)]
+ [TestCase("String", "Hello World!")]
+ [TestCase("Char", 'A')]
+ [TestCase("Bool", true)]
+ [TestCase("Bool", false)]
+ [TestCase("Byte", (byte)1)]
+ [TestCase("SByte", (sbyte)-1)]
+ [TestCase("Int16", (short)1)]
+ [TestCase("UInt16", (ushort)1)]
+ [TestCase("Int32", 1)]
+ [TestCase("UInt32", (uint)1)]
+ [TestCase("Int64", (long)1)]
+ [TestCase("UInt64", (ulong)1)]
+ [TestCase("Single", 1.0f)]
+ [TestCase("Double", 1.0d)]
+ [TestCase("Bytes", new byte[] { 42, 43, 44 })]
+ [TestCaseSource(nameof(TestReadCases))]
+ public void Read(string name, object value)
+ {
+ using var testFile = ProduceResourcesTestFile(name, value);
+ using var reader = new ResourcesFile(testFile);
+ var items = reader.ToArray();
+ Assert.AreEqual(1, items.Length);
+ Assert.AreEqual(name, items[0].Key);
+ Assert.AreEqual(value, items[0].Value);
+ }
+
+ [TestCase("Null", null, null, "System.Resources.ResXNullRef" + WinFormsAssemblyName)]
+ [TestCase("String", "Hello World!", "Hello World!", null)]
+ [TestCase("Bool", true, "True", "System.Boolean" + MSCorLibAssemblyName)]
+ [TestCase("Bool", false, "False", "System.Boolean" + MSCorLibAssemblyName)]
+ [TestCase("Char", 'A', "A", "System.Char" + MSCorLibAssemblyName)]
+ [TestCase("Byte", (byte)1, "1", "System.Byte" + MSCorLibAssemblyName)]
+ [TestCase("SByte", (sbyte)-1, "-1", "System.SByte" + MSCorLibAssemblyName)]
+ [TestCase("Int16", (short)1, "1", "System.Int16" + MSCorLibAssemblyName)]
+ [TestCase("UInt16", (ushort)1, "1", "System.UInt16" + MSCorLibAssemblyName)]
+ [TestCase("Int32", 1, "1", "System.Int32" + MSCorLibAssemblyName)]
+ [TestCase("UInt32", (uint)1, "1", "System.UInt32" + MSCorLibAssemblyName)]
+ [TestCase("Int64", (long)1, "1", "System.Int64" + MSCorLibAssemblyName)]
+ [TestCase("UInt64", (ulong)1, "1", "System.UInt64" + MSCorLibAssemblyName)]
+ [TestCase("Single", 1.0f, "1", "System.Single" + MSCorLibAssemblyName)]
+ [TestCase("Double", 1.0d, "1", "System.Double" + MSCorLibAssemblyName)]
+ [TestCaseSource(nameof(TestWriteCases))]
+ public void Write(string name, object value, string serializedValue, string typeName)
+ {
+ var element = ProduceResXTest(name, value);
+ Assert.AreEqual(name, element.Attribute("name")?.Value);
+ if (typeName != null)
+ {
+ Assert.AreEqual(typeName, element.Attribute("type")?.Value);
+ }
+ var v = element.Element("value");
+ Assert.IsNotNull(v);
+ Assert.IsTrue(v.IsEmpty ? serializedValue == null : v.Value == serializedValue);
+ }
+
+ [Test]
+ public void ResXSerializableClassIsRejected()
+ {
+ Assert.Throws(
+ () => ProduceResXTest("Serial", new SerializableClass { Name = "Hugo", Age = 42 })
+ );
+ }
+
+ [Test]
+ public void BitmapIsResourceSerializedObject()
+ {
+ Stream stream = typeof(ResourceReaderWriterTests).Assembly
+ .GetManifestResourceStream(typeof(ResourceReaderWriterTests).Namespace + ".Test.resources");
+ using var reader = new ResourcesFile(stream);
+ var items = reader.ToArray();
+ Assert.AreEqual(3, items.Length);
+ var item = items.FirstOrDefault(i => i.Key == "Bitmap");
+ Assert.IsNotNull(item.Key);
+ Assert.IsInstanceOf(item.Value);
+ }
+
+ [Test]
+ public void ByteArrayIsSupported()
+ {
+ Stream stream = typeof(ResourceReaderWriterTests).Assembly
+ .GetManifestResourceStream(typeof(ResourceReaderWriterTests).Namespace + ".Test.resources");
+ using var reader = new ResourcesFile(stream);
+ var items = reader.ToArray();
+ Assert.AreEqual(3, items.Length);
+ var item = items.FirstOrDefault(i => i.Key == "Byte[]");
+ Assert.IsNotNull(item.Key);
+ Assert.IsInstanceOf(item.Value);
+ byte[] array = (byte[])item.Value;
+ Assert.AreEqual(3, array.Length);
+ Assert.AreEqual(42, array[0]);
+ Assert.AreEqual(43, array[1]);
+ Assert.AreEqual(44, array[2]);
+ }
+
+ [Test]
+ public void MemoryStreamIsSupported()
+ {
+ Stream stream = typeof(ResourceReaderWriterTests).Assembly
+ .GetManifestResourceStream(typeof(ResourceReaderWriterTests).Namespace + ".Test.resources");
+ using var reader = new ResourcesFile(stream);
+ var items = reader.ToArray();
+ Assert.AreEqual(3, items.Length);
+ var item = items.FirstOrDefault(i => i.Key == "MemoryStream");
+ Assert.IsNotNull(item.Key);
+ Assert.IsInstanceOf(item.Value);
+ }
+ }
+}
\ No newline at end of file
diff --git a/ICSharpCode.Decompiler.Tests/Util/Test.resources b/ICSharpCode.Decompiler.Tests/Util/Test.resources
new file mode 100644
index 000000000..375a8c249
Binary files /dev/null and b/ICSharpCode.Decompiler.Tests/Util/Test.resources differ
diff --git a/ICSharpCode.Decompiler/Util/ResXResourceWriter.cs b/ICSharpCode.Decompiler/Util/ResXResourceWriter.cs
index b51c2e9ae..7d18ef551 100644
--- a/ICSharpCode.Decompiler/Util/ResXResourceWriter.cs
+++ b/ICSharpCode.Decompiler/Util/ResXResourceWriter.cs
@@ -31,9 +31,8 @@
// includes code by Mike Krüger and Lluis Sanchez
using System;
-using System.ComponentModel;
+using System.Globalization;
using System.IO;
-using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Xml;
@@ -46,25 +45,20 @@ namespace ICSharpCode.Decompiler.Util
#endif
class ResXResourceWriter : IDisposable
{
- #region Local Variables
private string filename;
private Stream stream;
private TextWriter textwriter;
private XmlTextWriter writer;
private bool written;
private string base_path;
- #endregion // Local Variables
- #region Static Fields
public static readonly string BinSerializedObjectMimeType = "application/x-microsoft.net.object.binary.base64";
public static readonly string ByteArraySerializedObjectMimeType = "application/x-microsoft.net.object.bytearray.base64";
public static readonly string DefaultSerializedObjectMimeType = BinSerializedObjectMimeType;
public static readonly string ResMimeType = "text/microsoft-resx";
public static readonly string SoapSerializedObjectMimeType = "application/x-microsoft.net.object.soap.base64";
public static readonly string Version = "2.0";
- #endregion // Static Fields
- #region Constructors & Destructor
public ResXResourceWriter(Stream stream)
{
if (stream == null)
@@ -96,9 +90,9 @@ namespace ICSharpCode.Decompiler.Util
{
Dispose(false);
}
- #endregion // Constructors & Destructor
const string WinFormsAssemblyName = ", System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
+ const string MSCorLibAssemblyName = ", mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
const string ResXNullRefTypeName = "System.Resources.ResXNullRef" + WinFormsAssemblyName;
void InitWriter()
@@ -131,39 +125,23 @@ namespace ICSharpCode.Decompiler.Util
void WriteNiceBase64(byte[] value, int offset, int length)
{
- string b64;
- StringBuilder sb;
- int pos;
- int inc;
- string ins;
-
- b64 = Convert.ToBase64String(value, offset, length);
-
- // Wild guess; two extra newlines, and one newline/tab pair for every 80 chars
- sb = new StringBuilder(b64, b64.Length + ((b64.Length + 160) / 80) * 3);
- pos = 0;
- inc = 80 + Environment.NewLine.Length + 1;
- ins = Environment.NewLine + "\t";
- while (pos < sb.Length)
- {
- sb.Insert(pos, ins);
- pos += inc;
- }
- sb.Insert(sb.Length, Environment.NewLine);
- writer.WriteString(sb.ToString());
+ string base64 = Convert.ToBase64String(
+ value, offset, length,
+ Base64FormattingOptions.InsertLineBreaks);
+ writer.WriteString(base64);
}
- void WriteBytes(string name, Type type, byte[] value, int offset, int length, string comment)
+ void WriteBytes(string name, string type, byte[] value, int offset, int length, string comment)
{
writer.WriteStartElement("data");
writer.WriteAttributeString("name", name);
if (type != null)
{
- writer.WriteAttributeString("type", type.AssemblyQualifiedName);
+ writer.WriteAttributeString("type", type);
// byte[] should never get a mimetype, otherwise MS.NET won't be able
// to parse the data.
- if (type != typeof(byte[]))
+ if (type != "System.Byte[]" + MSCorLibAssemblyName)
writer.WriteAttributeString("mimetype", ByteArraySerializedObjectMimeType);
writer.WriteStartElement("value");
WriteNiceBase64(value, offset, length);
@@ -177,7 +155,7 @@ namespace ICSharpCode.Decompiler.Util
writer.WriteEndElement();
- if (!(comment == null || comment.Equals(String.Empty)))
+ if (!string.IsNullOrEmpty(comment))
{
writer.WriteStartElement("comment");
writer.WriteString(comment);
@@ -187,29 +165,22 @@ namespace ICSharpCode.Decompiler.Util
writer.WriteEndElement();
}
- void WriteBytes(string name, Type type, byte[] value, string comment)
- {
- WriteBytes(name, type, value, 0, value.Length, comment);
- }
-
- void WriteString(string name, string value)
- {
- WriteString(name, value, null);
- }
- void WriteString(string name, string value, string type)
- {
- WriteString(name, value, type, String.Empty);
- }
void WriteString(string name, string value, string type, string comment)
{
writer.WriteStartElement("data");
writer.WriteAttributeString("name", name);
if (type != null)
+ {
writer.WriteAttributeString("type", type);
+ }
+ else
+ {
+ writer.WriteAttributeString("xml:space", "preserve");
+ }
writer.WriteStartElement("value");
writer.WriteString(value);
writer.WriteEndElement();
- if (!(comment == null || comment.Equals(String.Empty)))
+ if (!string.IsNullOrEmpty(comment))
{
writer.WriteStartElement("comment");
writer.WriteString(comment);
@@ -221,34 +192,16 @@ namespace ICSharpCode.Decompiler.Util
public void AddResource(string name, byte[] value)
{
- if (name == null)
- throw new ArgumentNullException(nameof(name));
-
- if (value == null)
- throw new ArgumentNullException(nameof(value));
-
- if (written)
- throw new InvalidOperationException("The resource is already generated.");
-
- if (writer == null)
- InitWriter();
-
- WriteBytes(name, value.GetType(), value, null);
+ AddResource(name, value, string.Empty);
}
public void AddResource(string name, object value)
{
- AddResource(name, value, String.Empty);
+ AddResource(name, value, string.Empty);
}
private void AddResource(string name, object value, string comment)
{
- if (value is string)
- {
- AddResource(name, (string)value, comment);
- return;
- }
-
if (name == null)
throw new ArgumentNullException(nameof(name));
@@ -258,64 +211,74 @@ namespace ICSharpCode.Decompiler.Util
if (writer == null)
InitWriter();
- if (value is byte[])
- {
- WriteBytes(name, value.GetType(), (byte[])value, comment);
- return;
- }
- if (value is MemoryStream memoryStream)
- {
- WriteBytes(name, null, memoryStream.ToArray(), comment);
- return;
- }
- if (value is ResourceSerializedObject rso)
- {
- var bytes = rso.GetBytes();
- WriteBytes(name, null, bytes, 0, bytes.Length, comment);
- return;
- }
-
- if (value == null)
- {
- // nulls written as ResXNullRef
- WriteString(name, "", ResXNullRefTypeName, comment);
- return;
- }
-
- if (value != null && !value.GetType().IsSerializable)
- throw new InvalidOperationException(String.Format("The element '{0}' of type '{1}' is not serializable.", name, value.GetType().Name));
-
- TypeConverter converter = TypeDescriptor.GetConverter(value);
-
- if (converter != null && converter.CanConvertTo(typeof(string)) && converter.CanConvertFrom(typeof(string)))
- {
- string str = (string)converter.ConvertToInvariantString(value);
- WriteString(name, str, value.GetType().AssemblyQualifiedName, comment);
- return;
- }
-
- if (converter != null && converter.CanConvertTo(typeof(byte[])) && converter.CanConvertFrom(typeof(byte[])))
- {
- byte[] b = (byte[])converter.ConvertTo(value, typeof(byte[]));
- WriteBytes(name, value.GetType(), b, comment);
- return;
- }
-
- MemoryStream ms = new MemoryStream();
- BinaryFormatter fmt = new BinaryFormatter();
- try
- {
- fmt.Serialize(ms, value);
- }
- catch (Exception e)
+ switch (value)
{
- throw new InvalidOperationException("Cannot add a " + value.GetType() +
- "because it cannot be serialized: " +
- e.Message);
+ case null:
+ // nulls written as ResXNullRef
+ WriteString(name, "", ResXNullRefTypeName, comment);
+ break;
+ case string s:
+ WriteString(name, s, null, comment);
+ break;
+ case bool bo:
+ WriteString(name, bo.ToString(CultureInfo.InvariantCulture), "System.Boolean" + MSCorLibAssemblyName, comment);
+ break;
+ case char ch:
+ WriteString(name, ch.ToString(CultureInfo.InvariantCulture), "System.Char" + MSCorLibAssemblyName, comment);
+ break;
+ case sbyte sb:
+ WriteString(name, sb.ToString(CultureInfo.InvariantCulture), "System.SByte" + MSCorLibAssemblyName, comment);
+ break;
+ case byte b:
+ WriteString(name, b.ToString(CultureInfo.InvariantCulture), "System.Byte" + MSCorLibAssemblyName, comment);
+ break;
+ case short sh:
+ WriteString(name, sh.ToString(CultureInfo.InvariantCulture), "System.Int16" + MSCorLibAssemblyName, comment);
+ break;
+ case ushort ush:
+ WriteString(name, ush.ToString(CultureInfo.InvariantCulture), "System.UInt16" + MSCorLibAssemblyName, comment);
+ break;
+ case int i:
+ WriteString(name, i.ToString(CultureInfo.InvariantCulture), "System.Int32" + MSCorLibAssemblyName, comment);
+ break;
+ case uint u:
+ WriteString(name, u.ToString(CultureInfo.InvariantCulture), "System.UInt32" + MSCorLibAssemblyName, comment);
+ break;
+ case long l:
+ WriteString(name, l.ToString(CultureInfo.InvariantCulture), "System.Int64" + MSCorLibAssemblyName, comment);
+ break;
+ case ulong ul:
+ WriteString(name, ul.ToString(CultureInfo.InvariantCulture), "System.UInt64" + MSCorLibAssemblyName, comment);
+ break;
+ case float f:
+ WriteString(name, f.ToString(CultureInfo.InvariantCulture), "System.Single" + MSCorLibAssemblyName, comment);
+ break;
+ case double d:
+ WriteString(name, d.ToString(CultureInfo.InvariantCulture), "System.Double" + MSCorLibAssemblyName, comment);
+ break;
+ case decimal m:
+ WriteString(name, m.ToString(CultureInfo.InvariantCulture), "System.Decimal" + MSCorLibAssemblyName, comment);
+ break;
+ case DateTime dt:
+ WriteString(name, dt.ToString(CultureInfo.InvariantCulture), "System.DateTime" + MSCorLibAssemblyName, comment);
+ break;
+ case TimeSpan sp:
+ WriteString(name, sp.ToString(), "System.TimeSpan" + MSCorLibAssemblyName, comment);
+ break;
+ case byte[] array:
+ WriteBytes(name, "System.Byte[]" + MSCorLibAssemblyName, array, 0, array.Length, comment);
+ break;
+ case MemoryStream memoryStream:
+ var arr = memoryStream.ToArray();
+ WriteBytes(name, null, arr, 0, arr.Length, comment);
+ break;
+ case ResourceSerializedObject rso:
+ var bytes = rso.GetBytes();
+ WriteBytes(name, null, bytes, 0, bytes.Length, comment);
+ break;
+ default:
+ throw new NotSupportedException($"Value '{value}' of type {value.GetType().FullName} is not supported by this version of ResXResourceWriter. Use byte arrays or streams instead.");
}
-
- WriteBytes(name, null, ms.GetBuffer(), 0, (int)ms.Length, comment);
- ms.Close();
}
public void AddResource(string name, string value)
@@ -323,179 +286,6 @@ namespace ICSharpCode.Decompiler.Util
AddResource(name, value, string.Empty);
}
- private void AddResource(string name, string value, string comment)
- {
- if (name == null)
- throw new ArgumentNullException(nameof(name));
-
- if (value == null)
- throw new ArgumentNullException(nameof(value));
-
- if (written)
- throw new InvalidOperationException("The resource is already generated.");
-
- if (writer == null)
- InitWriter();
-
- WriteString(name, value, null, comment);
- }
-
- public void AddMetadata(string name, string value)
- {
- if (name == null)
- throw new ArgumentNullException(nameof(name));
-
- if (value == null)
- throw new ArgumentNullException(nameof(value));
-
- if (written)
- throw new InvalidOperationException("The resource is already generated.");
-
- if (writer == null)
- InitWriter();
-
- writer.WriteStartElement("metadata");
- writer.WriteAttributeString("name", name);
- writer.WriteAttributeString("xml:space", "preserve");
-
- writer.WriteElementString("value", value);
-
- writer.WriteEndElement();
- }
-
- public void AddMetadata(string name, byte[] value)
- {
- if (name == null)
- throw new ArgumentNullException(nameof(name));
-
- if (value == null)
- throw new ArgumentNullException(nameof(value));
-
- if (written)
- throw new InvalidOperationException("The resource is already generated.");
-
- if (writer == null)
- InitWriter();
-
- writer.WriteStartElement("metadata");
- writer.WriteAttributeString("name", name);
-
- writer.WriteAttributeString("type", value.GetType().AssemblyQualifiedName);
-
- writer.WriteStartElement("value");
- WriteNiceBase64(value, 0, value.Length);
- writer.WriteEndElement();
-
- writer.WriteEndElement();
- }
-
- public void AddMetadata(string name, object value)
- {
- if (value is string)
- {
- AddMetadata(name, (string)value);
- return;
- }
-
- if (value is byte[])
- {
- AddMetadata(name, (byte[])value);
- return;
- }
-
- if (name == null)
- throw new ArgumentNullException(nameof(name));
-
- if (value == null)
- throw new ArgumentNullException(nameof(value));
-
- if (!value.GetType().IsSerializable)
- throw new InvalidOperationException(String.Format("The element '{0}' of type '{1}' is not serializable.", name, value.GetType().Name));
-
- if (written)
- throw new InvalidOperationException("The resource is already generated.");
-
- if (writer == null)
- InitWriter();
-
- Type type = value.GetType();
-
- TypeConverter converter = TypeDescriptor.GetConverter(value);
- if (converter != null && converter.CanConvertTo(typeof(string)) && converter.CanConvertFrom(typeof(string)))
- {
- string str = (string)converter.ConvertToInvariantString(value);
- writer.WriteStartElement("metadata");
- writer.WriteAttributeString("name", name);
- if (type != null)
- writer.WriteAttributeString("type", type.AssemblyQualifiedName);
- writer.WriteStartElement("value");
- writer.WriteString(str);
- writer.WriteEndElement();
- writer.WriteEndElement();
- writer.WriteWhitespace("\n ");
- return;
- }
-
- if (converter != null && converter.CanConvertTo(typeof(byte[])) && converter.CanConvertFrom(typeof(byte[])))
- {
- byte[] b = (byte[])converter.ConvertTo(value, typeof(byte[]));
- writer.WriteStartElement("metadata");
- writer.WriteAttributeString("name", name);
-
- if (type != null)
- {
- writer.WriteAttributeString("type", type.AssemblyQualifiedName);
- writer.WriteAttributeString("mimetype", ByteArraySerializedObjectMimeType);
- writer.WriteStartElement("value");
- WriteNiceBase64(b, 0, b.Length);
- }
- else
- {
- writer.WriteAttributeString("mimetype", BinSerializedObjectMimeType);
- writer.WriteStartElement("value");
- writer.WriteBase64(b, 0, b.Length);
- }
-
- writer.WriteEndElement();
- writer.WriteEndElement();
- return;
- }
-
- MemoryStream ms = new MemoryStream();
- BinaryFormatter fmt = new BinaryFormatter();
- try
- {
- fmt.Serialize(ms, value);
- }
- catch (Exception e)
- {
- throw new InvalidOperationException("Cannot add a " + value.GetType() +
- "because it cannot be serialized: " +
- e.Message);
- }
-
- writer.WriteStartElement("metadata");
- writer.WriteAttributeString("name", name);
-
- if (type != null)
- {
- writer.WriteAttributeString("type", type.AssemblyQualifiedName);
- writer.WriteAttributeString("mimetype", ByteArraySerializedObjectMimeType);
- writer.WriteStartElement("value");
- WriteNiceBase64(ms.GetBuffer(), 0, ms.GetBuffer().Length);
- }
- else
- {
- writer.WriteAttributeString("mimetype", BinSerializedObjectMimeType);
- writer.WriteStartElement("value");
- writer.WriteBase64(ms.GetBuffer(), 0, ms.GetBuffer().Length);
- }
-
- writer.WriteEndElement();
- writer.WriteEndElement();
- ms.Close();
- }
-
public void Close()
{
if (writer != null)
@@ -534,7 +324,7 @@ namespace ICSharpCode.Decompiler.Util
Close();
}
- static string schema = @"
+ static readonly string schema = @"
@@ -564,11 +354,9 @@ namespace ICSharpCode.Decompiler.Util
".Replace("'", "\"").Replace("\t", " ");
- #region Public Properties
public string BasePath {
get { return base_path; }
set { base_path = value; }
}
- #endregion
}
}