ResXResourceWriter.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. //
  2. // System.Resources.ResXResourceWriter.cs
  3. //
  4. // Authors:
  5. // Duncan Mak <[email protected]>
  6. // Gonzalo Paniagua Javier ([email protected])
  7. //
  8. // 2001 (C) Ximian, Inc. http://www.ximian.com
  9. // (c) 2004 Novell, Inc. (http://www.novell.com)
  10. //
  11. using System.ComponentModel;
  12. using System.IO;
  13. using System.Runtime.Serialization.Formatters.Binary;
  14. using System.Text;
  15. using System.Xml;
  16. namespace System.Resources
  17. {
  18. public sealed class ResXResourceWriter : IResourceWriter, IDisposable
  19. {
  20. string filename;
  21. Stream stream;
  22. TextWriter textwriter;
  23. XmlTextWriter writer;
  24. bool written;
  25. public ResXResourceWriter (Stream stream)
  26. {
  27. if (stream == null)
  28. throw new ArgumentNullException ("stream");
  29. if (stream.CanWrite == false)
  30. throw new ArgumentException ("stream is not writable.", "stream");
  31. this.stream = stream;
  32. }
  33. public ResXResourceWriter (TextWriter textwriter)
  34. {
  35. if (textwriter == null)
  36. throw new ArgumentNullException ("textwriter");
  37. this.textwriter = textwriter;
  38. }
  39. public ResXResourceWriter (string fileName)
  40. {
  41. if (fileName == null)
  42. throw new ArgumentNullException ("fileName");
  43. this.filename = fileName;
  44. }
  45. void InitWriter ()
  46. {
  47. if (filename != null) {
  48. stream = File.OpenWrite (filename);
  49. textwriter = new StreamWriter (stream, Encoding.UTF8);
  50. }
  51. writer = new XmlTextWriter (textwriter);
  52. writer.Formatting = Formatting.Indented;
  53. writer.WriteStartDocument ();
  54. writer.WriteStartElement ("root");
  55. writer.WriteRaw (schema);
  56. WriteHeader ("resmimetype", "text/microsoft-resx");
  57. WriteHeader ("version", "1.3");
  58. WriteHeader ("reader", typeof (ResXResourceReader).AssemblyQualifiedName);
  59. WriteHeader ("writer", typeof (ResXResourceWriter).AssemblyQualifiedName);
  60. }
  61. void WriteHeader (string name, string value)
  62. {
  63. writer.WriteStartElement ("resheader");
  64. writer.WriteAttributeString ("name", name);
  65. writer.WriteStartElement ("value");
  66. writer.WriteString (value);
  67. writer.WriteEndElement ();
  68. writer.WriteEndElement ();
  69. }
  70. void WriteBytes (string name, string typename, byte [] value, int offset, int length)
  71. {
  72. writer.WriteStartElement ("data");
  73. writer.WriteAttributeString ("name", name);
  74. if (typename != null) {
  75. writer.WriteAttributeString ("type", typename);
  76. } else {
  77. writer.WriteAttributeString ("mimetype",
  78. "application/x-microsoft.net.object.binary.base64");
  79. }
  80. writer.WriteStartElement ("value");
  81. writer.WriteBase64 (value, offset, length);
  82. writer.WriteEndElement ();
  83. writer.WriteEndElement ();
  84. }
  85. void WriteBytes (string name, string typename, byte [] value)
  86. {
  87. WriteBytes (name, typename, value, 0, value.Length);
  88. }
  89. void WriteString (string name, string value)
  90. {
  91. writer.WriteStartElement ("data");
  92. writer.WriteAttributeString ("name", name);
  93. writer.WriteStartElement ("value");
  94. writer.WriteString (value);
  95. writer.WriteEndElement ();
  96. writer.WriteEndElement ();
  97. writer.WriteWhitespace ("\n ");
  98. }
  99. public void AddResource (string name, byte [] value)
  100. {
  101. if (name == null)
  102. throw new ArgumentNullException ("name");
  103. if (value == null)
  104. throw new ArgumentNullException ("value");
  105. if (written)
  106. throw new InvalidOperationException ("The resource is already generated.");
  107. if (writer == null)
  108. InitWriter ();
  109. WriteBytes (name, value.GetType ().AssemblyQualifiedName, value);
  110. }
  111. public void AddResource (string name, object value)
  112. {
  113. if (name == null)
  114. throw new ArgumentNullException ("name");
  115. if (value == null)
  116. throw new ArgumentNullException ("value");
  117. if (written)
  118. throw new InvalidOperationException ("The resource is already generated.");
  119. if (writer == null)
  120. InitWriter ();
  121. TypeConverter converter = TypeDescriptor.GetConverter (value);
  122. if (converter != null && converter.CanConvertTo (typeof (string))) {
  123. string str = (string) converter.ConvertTo (value, typeof (string));
  124. WriteString (name, str);
  125. return;
  126. }
  127. MemoryStream ms = new MemoryStream ();
  128. BinaryFormatter fmt = new BinaryFormatter ();
  129. try {
  130. fmt.Serialize (ms, value);
  131. } catch (Exception e) {
  132. throw new InvalidOperationException ("Cannot add a " + value.GetType () +
  133. "because it cannot be serialized: " +
  134. e.Message);
  135. }
  136. WriteBytes (name, null, ms.GetBuffer (), 0, (int) ms.Length);
  137. ms.Close ();
  138. }
  139. public void AddResource (string name, string value)
  140. {
  141. if (name == null)
  142. throw new ArgumentNullException ("name");
  143. if (value == null)
  144. throw new ArgumentNullException ("value");
  145. if (written)
  146. throw new InvalidOperationException ("The resource is already generated.");
  147. if (writer == null)
  148. InitWriter ();
  149. WriteString (name, value);
  150. }
  151. public void Close ()
  152. {
  153. if (!written) {
  154. Generate ();
  155. }
  156. if (writer != null) {
  157. writer.Close ();
  158. stream = null;
  159. filename = null;
  160. textwriter = null;
  161. }
  162. }
  163. public void Dispose ()
  164. {
  165. Close ();
  166. }
  167. public void Generate ()
  168. {
  169. if (written)
  170. throw new InvalidOperationException ("The resource is already generated.");
  171. written = true;
  172. writer.WriteEndElement ();
  173. writer.Flush ();
  174. }
  175. static string schema = @"
  176. <xsd:schema id='root' xmlns='' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:msdata='urn:schemas-microsoft-com:xml-msdata'>
  177. <xsd:element name='root' msdata:IsDataSet='true'>
  178. <xsd:complexType>
  179. <xsd:choice maxOccurs='unbounded'>
  180. <xsd:element name='data'>
  181. <xsd:complexType>
  182. <xsd:sequence>
  183. <xsd:element name='value' type='xsd:string' minOccurs='0' msdata:Ordinal='1' />
  184. <xsd:element name='comment' type='xsd:string' minOccurs='0' msdata:Ordinal='2' />
  185. </xsd:sequence>
  186. <xsd:attribute name='name' type='xsd:string' msdata:Ordinal='1' />
  187. <xsd:attribute name='type' type='xsd:string' msdata:Ordinal='3' />
  188. <xsd:attribute name='mimetype' type='xsd:string' msdata:Ordinal='4' />
  189. </xsd:complexType>
  190. </xsd:element>
  191. <xsd:element name='resheader'>
  192. <xsd:complexType>
  193. <xsd:sequence>
  194. <xsd:element name='value' type='xsd:string' minOccurs='0' msdata:Ordinal='1' />
  195. </xsd:sequence>
  196. <xsd:attribute name='name' type='xsd:string' use='required' />
  197. </xsd:complexType>
  198. </xsd:element>
  199. </xsd:choice>
  200. </xsd:complexType>
  201. </xsd:element>
  202. </xsd:schema>
  203. ".Replace ("'", "\"");
  204. }
  205. }