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 } }