ObjectStateFormatter.cs 25 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040
  1. //
  2. // System.Web.UI.ObjectStateFormatter
  3. //
  4. // Authors:
  5. // Ben Maurer ([email protected])
  6. // Gonzalo Paniagua ([email protected])
  7. //
  8. // (C) 2003 Ben Maurer
  9. // (c) Copyright 2004-2010 Novell, Inc. (http://www.novell.com)
  10. //
  11. //
  12. // Permission is hereby granted, free of charge, to any person obtaining
  13. // a copy of this software and associated documentation files (the
  14. // "Software"), to deal in the Software without restriction, including
  15. // without limitation the rights to use, copy, modify, merge, publish,
  16. // distribute, sublicense, and/or sell copies of the Software, and to
  17. // permit persons to whom the Software is furnished to do so, subject to
  18. // the following conditions:
  19. //
  20. // The above copyright notice and this permission notice shall be
  21. // included in all copies or substantial portions of the Software.
  22. //
  23. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  27. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  28. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  29. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  30. //
  31. //#define TRACE
  32. using System.Collections;
  33. using System.ComponentModel;
  34. using System.Globalization;
  35. using System.Drawing;
  36. using System.IO;
  37. using System.Reflection;
  38. using System.Runtime.Serialization.Formatters.Binary;
  39. using System.Runtime.Serialization;
  40. using System.Text;
  41. using System.Web.UI.WebControls;
  42. using System.Web.Util;
  43. using System.Diagnostics;
  44. using System.Web.Configuration;
  45. namespace System.Web.UI
  46. {
  47. public sealed class ObjectStateFormatter : IFormatter, IStateFormatter
  48. {
  49. Page page;
  50. MachineKeySection section;
  51. public ObjectStateFormatter ()
  52. {
  53. }
  54. internal ObjectStateFormatter (Page page)
  55. {
  56. this.page = page;
  57. }
  58. bool EnableMac {
  59. get {
  60. return (page == null) ? (section != null) : page.EnableViewStateMac;
  61. }
  62. }
  63. bool NeedViewStateEncryption {
  64. get {
  65. return (page == null) ? false : page.NeedViewStateEncryption;
  66. }
  67. }
  68. internal MachineKeySection Section {
  69. get {
  70. if (section == null)
  71. section = (MachineKeySection) WebConfigurationManager.GetWebApplicationSection ("system.web/machineKey");
  72. return section;
  73. }
  74. set {
  75. section = value;
  76. }
  77. }
  78. public object Deserialize (Stream inputStream)
  79. {
  80. if (inputStream == null)
  81. throw new ArgumentNullException ("inputStream");
  82. return DeserializeObject (new BinaryReader (inputStream));
  83. }
  84. public object Deserialize (string inputString)
  85. {
  86. if (inputString == null)
  87. throw new ArgumentNullException ("inputString");
  88. if (inputString.Length == 0)
  89. throw new ArgumentNullException ("inputString");
  90. byte [] data = Convert.FromBase64String (inputString);
  91. if (data == null || (data.Length) == 0)
  92. throw new ArgumentNullException ("inputString");
  93. if (NeedViewStateEncryption) {
  94. if (EnableMac) {
  95. data = MachineKeySectionUtils.VerifyDecrypt (Section, data);
  96. } else {
  97. data = MachineKeySectionUtils.Decrypt (Section, data);
  98. }
  99. } else if (EnableMac) {
  100. data = MachineKeySectionUtils.Verify (Section, data);
  101. }
  102. if (data == null)
  103. throw new HttpException ("Unable to validate data.");
  104. using (MemoryStream ms = new MemoryStream (data)) {
  105. return Deserialize (ms);
  106. }
  107. }
  108. public string Serialize (object stateGraph)
  109. {
  110. if (stateGraph == null)
  111. return String.Empty;
  112. byte[] data = null;
  113. using (MemoryStream ms = new MemoryStream ()) {
  114. Serialize (ms, stateGraph);
  115. data = ms.GetBuffer ();
  116. }
  117. if (NeedViewStateEncryption) {
  118. if (EnableMac) {
  119. data = MachineKeySectionUtils.EncryptSign (Section, data);
  120. } else {
  121. data = MachineKeySectionUtils.Encrypt (Section, data);
  122. }
  123. } else if (EnableMac) {
  124. data = MachineKeySectionUtils.Sign (Section, data);
  125. }
  126. return Convert.ToBase64String (data, 0, data.Length);
  127. }
  128. public void Serialize (Stream outputStream, object stateGraph)
  129. {
  130. if (outputStream == null)
  131. throw new ArgumentNullException ("outputStream");
  132. if (stateGraph == null)
  133. throw new ArgumentNullException ("stateGraph");
  134. SerializeValue (new BinaryWriter (outputStream), stateGraph);
  135. }
  136. void SerializeValue (BinaryWriter w, object o)
  137. {
  138. ObjectFormatter.WriteObject (w, o, new WriterContext ());
  139. }
  140. object DeserializeObject (BinaryReader r)
  141. {
  142. return ObjectFormatter.ReadObject (r, new ReaderContext ());
  143. }
  144. #region IFormatter
  145. object IFormatter.Deserialize (Stream serializationStream)
  146. {
  147. return Deserialize (serializationStream);
  148. }
  149. void IFormatter.Serialize (Stream serializationStream, object stateGraph)
  150. {
  151. Serialize (serializationStream, stateGraph);
  152. }
  153. SerializationBinder IFormatter.Binder {
  154. get { return null; }
  155. set { }
  156. }
  157. StreamingContext IFormatter.Context {
  158. get { return new StreamingContext (StreamingContextStates.All); }
  159. set { }
  160. }
  161. ISurrogateSelector IFormatter.SurrogateSelector {
  162. get { return null; }
  163. set { }
  164. }
  165. #endregion
  166. #region Object Readers/Writers
  167. sealed class WriterContext
  168. {
  169. Hashtable cache;
  170. short nextKey = 0;
  171. short key = 0;
  172. public short Key {
  173. get { return key; }
  174. }
  175. public bool RegisterCache (object o)
  176. {
  177. if (nextKey == short.MaxValue)
  178. return false;
  179. if (cache == null) {
  180. cache = new Hashtable ();
  181. cache.Add (o, key = nextKey++);
  182. return false;
  183. }
  184. object posKey = cache [o];
  185. if (posKey == null) {
  186. cache.Add (o, key = nextKey++);
  187. return false;
  188. }
  189. key = (short) posKey;
  190. return true;
  191. }
  192. }
  193. sealed class ReaderContext
  194. {
  195. ArrayList cache;
  196. public void CacheItem (object o)
  197. {
  198. if (cache == null)
  199. cache = new ArrayList ();
  200. cache.Add (o);
  201. }
  202. public object GetCache (short key)
  203. {
  204. return cache [key];
  205. }
  206. }
  207. abstract class ObjectFormatter
  208. {
  209. static readonly Hashtable writeMap = new Hashtable ();
  210. static ObjectFormatter [] readMap = new ObjectFormatter [256];
  211. static BinaryObjectFormatter binaryObjectFormatter;
  212. static TypeFormatter typeFormatter;
  213. static EnumFormatter enumFormatter;
  214. static SingleRankArrayFormatter singleRankArrayFormatter;
  215. static TypeConverterFormatter typeConverterFormatter;
  216. static ObjectFormatter ()
  217. {
  218. new StringFormatter ().Register ();
  219. new Int64Formatter ().Register ();
  220. new Int32Formatter ().Register ();
  221. new Int16Formatter ().Register ();
  222. new ByteFormatter ().Register ();
  223. new BooleanFormatter ().Register ();
  224. new CharFormatter ().Register ();
  225. new DateTimeFormatter ().Register ();
  226. new PairFormatter ().Register ();
  227. new TripletFormatter ().Register ();
  228. new ArrayListFormatter ().Register ();
  229. new HashtableFormatter ().Register ();
  230. new ObjectArrayFormatter ().Register ();
  231. new UnitFormatter ().Register ();
  232. new FontUnitFormatter ().Register ();
  233. new IndexedStringFormatter ().Register ();
  234. new ColorFormatter ().Register ();
  235. enumFormatter = new EnumFormatter ();
  236. enumFormatter.Register ();
  237. typeFormatter = new TypeFormatter ();
  238. typeFormatter.Register ();
  239. singleRankArrayFormatter = new SingleRankArrayFormatter ();
  240. singleRankArrayFormatter.Register ();
  241. typeConverterFormatter = new TypeConverterFormatter ();
  242. typeConverterFormatter.Register ();
  243. binaryObjectFormatter = new BinaryObjectFormatter ();
  244. binaryObjectFormatter.Register ();
  245. }
  246. // 0 == null
  247. static byte nextId = 1;
  248. public ObjectFormatter ()
  249. {
  250. PrimaryId = nextId ++;
  251. if (NumberOfIds == 1)
  252. return;
  253. SecondaryId = nextId ++;
  254. if (NumberOfIds == 2)
  255. return;
  256. TertiaryId = nextId ++;
  257. if (NumberOfIds == 3)
  258. return;
  259. throw new Exception ();
  260. }
  261. protected readonly byte PrimaryId, SecondaryId = 255, TertiaryId = 255;
  262. protected abstract void Write (BinaryWriter w, object o, WriterContext ctx);
  263. protected abstract object Read (byte token, BinaryReader r, ReaderContext ctx);
  264. protected abstract Type Type { get; }
  265. protected virtual int NumberOfIds { get { return 1; } }
  266. public virtual void Register ()
  267. {
  268. writeMap [Type] = this;
  269. readMap [PrimaryId] = this;
  270. if (SecondaryId != 255) {
  271. readMap [SecondaryId] = this;
  272. if (TertiaryId != 255)
  273. readMap [TertiaryId] = this;
  274. }
  275. }
  276. public static void WriteObject (BinaryWriter w, object o, WriterContext ctx)
  277. {
  278. #if TRACE && !TARGET_J2EE
  279. if (o != null) {
  280. Trace.WriteLine (String.Format ("Writing {0} (type: {1})", o, o.GetType ()));
  281. Trace.Indent ();
  282. } else {
  283. Trace.WriteLine ("Writing null");
  284. }
  285. long pos = w.BaseStream.Position;
  286. #endif
  287. if (o == null) {
  288. w.Write ((byte) 0);
  289. return;
  290. }
  291. Type t = o.GetType ();
  292. #if TRACE
  293. Trace.WriteLine (String.Format ("Looking up formatter for type {0}", t));
  294. #endif
  295. ObjectFormatter fmt = writeMap [t] as ObjectFormatter;
  296. #if TRACE
  297. Trace.WriteLine (String.Format ("Formatter from writeMap: '{0}'", fmt));
  298. #endif
  299. if (fmt == null) {
  300. // Handle abstract types here
  301. if (o is Type)
  302. fmt = typeFormatter;
  303. else if (t.IsEnum)
  304. fmt = enumFormatter;
  305. else if (t.IsArray && ((Array) o).Rank == 1)
  306. fmt = singleRankArrayFormatter;
  307. else {
  308. TypeConverter converter;
  309. converter = TypeDescriptor.GetConverter (o);
  310. #if TRACE
  311. Trace.WriteLine (String.Format ("Type converter: '{0}' (to string: {1}; from {2}: {3})",
  312. converter,
  313. converter != null ? converter.CanConvertTo (typeof (string)) : false,
  314. t,
  315. converter != null ? converter.CanConvertFrom (t) : false));
  316. #endif
  317. // Do not use the converter if it's an instance of
  318. // TypeConverter itself - it reports it is able to
  319. // convert to string, but it's only a conversion
  320. // consisting of a call to ToString() with no
  321. // reverse conversion supported. This leads to
  322. // problems when deserializing the object.
  323. if (converter == null || converter.GetType () == typeof (TypeConverter) ||
  324. !converter.CanConvertTo (typeof (string)) || !converter.CanConvertFrom (typeof (string)))
  325. fmt = binaryObjectFormatter;
  326. else {
  327. typeConverterFormatter.Converter = converter;
  328. fmt = typeConverterFormatter;
  329. }
  330. }
  331. }
  332. #if TRACE
  333. Trace.WriteLine (String.Format ("Writing with formatter '{0}'", fmt.GetType ()));
  334. #endif
  335. fmt.Write (w, o, ctx);
  336. #if TRACE && !TARGET_J2EE
  337. Trace.Unindent ();
  338. Trace.WriteLine (String.Format ("Wrote {0} (type: {1}) {2} bytes", o, o.GetType (), w.BaseStream.Position - pos));
  339. #endif
  340. }
  341. public static object ReadObject (BinaryReader r, ReaderContext ctx)
  342. {
  343. byte sig = r.ReadByte ();
  344. if (sig == 0)
  345. return null;
  346. return readMap [sig].Read (sig, r, ctx);
  347. }
  348. protected void Write7BitEncodedInt (BinaryWriter w, int value)
  349. {
  350. do {
  351. int high = (value >> 7) & 0x01ffffff;
  352. byte b = (byte)(value & 0x7f);
  353. if (high != 0)
  354. b = (byte)(b | 0x80);
  355. w.Write(b);
  356. value = high;
  357. } while(value != 0);
  358. }
  359. protected int Read7BitEncodedInt (BinaryReader r)
  360. {
  361. int ret = 0;
  362. int shift = 0;
  363. byte b;
  364. do {
  365. b = r.ReadByte();
  366. ret = ret | ((b & 0x7f) << shift);
  367. shift += 7;
  368. } while ((b & 0x80) == 0x80);
  369. return ret;
  370. }
  371. }
  372. #region Primitive Formatters
  373. class StringFormatter : ObjectFormatter
  374. {
  375. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  376. {
  377. if (ctx.RegisterCache (o)) {
  378. w.Write (SecondaryId);
  379. w.Write (ctx.Key);
  380. } else {
  381. w.Write (PrimaryId);
  382. w.Write ((string)o);
  383. }
  384. }
  385. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  386. {
  387. if (token == PrimaryId) {
  388. string s = r.ReadString ();
  389. ctx.CacheItem (s);
  390. return s;
  391. } else {
  392. return ctx.GetCache (r.ReadInt16 ());
  393. }
  394. }
  395. protected override Type Type {
  396. get { return typeof (string); }
  397. }
  398. protected override int NumberOfIds {
  399. get { return 2; }
  400. }
  401. }
  402. class IndexedStringFormatter : StringFormatter
  403. {
  404. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  405. {
  406. IndexedString s = o as IndexedString;
  407. if (s == null)
  408. throw new InvalidOperationException ("object is not of the IndexedString type");
  409. base.Write (w, s.Value, ctx);
  410. }
  411. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  412. {
  413. string s = base.Read (token, r, ctx) as string;
  414. if (String.IsNullOrEmpty (s))
  415. throw new InvalidOperationException ("string must not be null or empty.");
  416. return new IndexedString (s);
  417. }
  418. protected override Type Type {
  419. get { return typeof (IndexedString); }
  420. }
  421. protected override int NumberOfIds {
  422. get { return 2; }
  423. }
  424. }
  425. class Int64Formatter : ObjectFormatter
  426. {
  427. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  428. {
  429. w.Write (PrimaryId);
  430. w.Write ((long)o);
  431. }
  432. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  433. {
  434. return r.ReadInt64 ();
  435. }
  436. protected override Type Type {
  437. get { return typeof (long); }
  438. }
  439. }
  440. class Int32Formatter : ObjectFormatter
  441. {
  442. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  443. {
  444. int i = (int) o;
  445. if ((int)(byte) i == i) {
  446. w.Write (SecondaryId);
  447. w.Write ((byte) i);
  448. } else {
  449. w.Write (PrimaryId);
  450. w.Write (i);
  451. }
  452. }
  453. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  454. {
  455. if (token == PrimaryId)
  456. return r.ReadInt32 ();
  457. else
  458. return (int) r.ReadByte ();
  459. }
  460. protected override Type Type {
  461. get { return typeof (int); }
  462. }
  463. protected override int NumberOfIds {
  464. get { return 2; }
  465. }
  466. }
  467. class Int16Formatter : ObjectFormatter
  468. {
  469. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  470. {
  471. w.Write (PrimaryId);
  472. w.Write ((short)o);
  473. }
  474. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  475. {
  476. return r.ReadInt16 ();
  477. }
  478. protected override Type Type {
  479. get { return typeof (short); }
  480. }
  481. }
  482. class ByteFormatter : ObjectFormatter
  483. {
  484. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  485. {
  486. w.Write (PrimaryId);
  487. w.Write ((byte)o);
  488. }
  489. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  490. {
  491. return r.ReadByte ();
  492. }
  493. protected override Type Type {
  494. get { return typeof (byte); }
  495. }
  496. }
  497. class BooleanFormatter : ObjectFormatter
  498. {
  499. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  500. {
  501. if ((bool)o == true)
  502. w.Write (PrimaryId);
  503. else
  504. w.Write (SecondaryId);
  505. }
  506. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  507. {
  508. return token == PrimaryId;
  509. }
  510. protected override Type Type {
  511. get { return typeof (bool); }
  512. }
  513. protected override int NumberOfIds {
  514. get { return 2; }
  515. }
  516. }
  517. class CharFormatter : ObjectFormatter
  518. {
  519. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  520. {
  521. w.Write (PrimaryId);
  522. w.Write ((char) o);
  523. }
  524. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  525. {
  526. return r.ReadChar ();
  527. }
  528. protected override Type Type {
  529. get { return typeof (char); }
  530. }
  531. }
  532. class DateTimeFormatter : ObjectFormatter
  533. {
  534. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  535. {
  536. w.Write (PrimaryId);
  537. w.Write (((DateTime) o).Ticks);
  538. }
  539. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  540. {
  541. return new DateTime (r.ReadInt64 ());
  542. }
  543. protected override Type Type {
  544. get { return typeof (DateTime); }
  545. }
  546. }
  547. class PairFormatter : ObjectFormatter
  548. {
  549. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  550. {
  551. Pair p = (Pair) o;
  552. w.Write (PrimaryId);
  553. WriteObject (w, p.First, ctx);
  554. WriteObject (w, p.Second, ctx);
  555. }
  556. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  557. {
  558. Pair p = new Pair ();
  559. p.First = ReadObject (r, ctx);
  560. p.Second = ReadObject (r, ctx);
  561. return p;
  562. }
  563. protected override Type Type {
  564. get { return typeof (Pair); }
  565. }
  566. }
  567. class TripletFormatter : ObjectFormatter
  568. {
  569. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  570. {
  571. Triplet t = (Triplet) o;
  572. w.Write (PrimaryId);
  573. WriteObject (w, t.First, ctx);
  574. WriteObject (w, t.Second, ctx);
  575. WriteObject (w, t.Third, ctx);
  576. }
  577. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  578. {
  579. Triplet t = new Triplet ();
  580. t.First = ReadObject (r, ctx);
  581. t.Second = ReadObject (r, ctx);
  582. t.Third = ReadObject (r, ctx);
  583. return t;
  584. }
  585. protected override Type Type {
  586. get { return typeof (Triplet); }
  587. }
  588. }
  589. class ArrayListFormatter : ObjectFormatter
  590. {
  591. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  592. {
  593. ArrayList l = (ArrayList) o;
  594. w.Write (PrimaryId);
  595. Write7BitEncodedInt (w, l.Count);
  596. for (int i = 0; i < l.Count; i++)
  597. WriteObject (w, l [i], ctx);
  598. }
  599. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  600. {
  601. int len = Read7BitEncodedInt (r);
  602. ArrayList l = new ArrayList (len);
  603. for (int i = 0; i < len; i++)
  604. l.Add (ReadObject (r, ctx));
  605. return l;
  606. }
  607. protected override Type Type {
  608. get { return typeof (ArrayList); }
  609. }
  610. }
  611. class HashtableFormatter : ObjectFormatter
  612. {
  613. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  614. {
  615. Hashtable ht = (Hashtable) o;
  616. w.Write (PrimaryId);
  617. Write7BitEncodedInt (w, ht.Count);
  618. foreach (DictionaryEntry de in ht) {
  619. WriteObject (w, de.Key, ctx);
  620. WriteObject (w, de.Value, ctx);
  621. }
  622. }
  623. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  624. {
  625. int len = Read7BitEncodedInt (r);
  626. Hashtable ht = new Hashtable (len);
  627. for (int i = 0; i < len; i++) {
  628. object key = ReadObject (r, ctx);
  629. object val = ReadObject (r, ctx);
  630. ht.Add (key, val);
  631. }
  632. return ht;
  633. }
  634. protected override Type Type {
  635. get { return typeof (Hashtable); }
  636. }
  637. }
  638. class ObjectArrayFormatter : ObjectFormatter
  639. {
  640. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  641. {
  642. object [] val = (object []) o;
  643. w.Write (PrimaryId);
  644. Write7BitEncodedInt (w, val.Length);
  645. for (int i = 0; i < val.Length; i++)
  646. WriteObject (w, val [i], ctx);
  647. }
  648. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  649. {
  650. int len = Read7BitEncodedInt (r);
  651. object [] ret = new object [len];
  652. for (int i = 0; i < len; i++)
  653. ret [i] = ReadObject (r, ctx);
  654. return ret;
  655. }
  656. protected override Type Type {
  657. get { return typeof (object []); }
  658. }
  659. }
  660. #endregion
  661. #region System.Web Optimizations
  662. class ColorFormatter : ObjectFormatter
  663. {
  664. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  665. {
  666. Color c = (Color) o;
  667. if (c.IsEmpty || c.IsKnownColor) {
  668. w.Write (SecondaryId);
  669. if (c.IsEmpty)
  670. w.Write (-1); //isempty marker
  671. else
  672. w.Write ((int) c.ToKnownColor ());
  673. } else {
  674. w.Write (PrimaryId);
  675. w.Write (c.ToArgb ());
  676. }
  677. }
  678. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  679. {
  680. int value = r.ReadInt32 ();
  681. if (token == PrimaryId)
  682. return Color.FromArgb (value);
  683. else {
  684. if (value == -1) //isempty marker
  685. return Color.Empty;
  686. return Color.FromKnownColor ((KnownColor)value);
  687. }
  688. }
  689. protected override Type Type {
  690. get { return typeof (Color); }
  691. }
  692. protected override int NumberOfIds {
  693. get { return 2; }
  694. }
  695. }
  696. #endregion
  697. #region Special Formatters
  698. class EnumFormatter : ObjectFormatter
  699. {
  700. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  701. {
  702. object value = Convert.ChangeType (o, ((Enum) o).GetTypeCode ());
  703. w.Write (PrimaryId);
  704. WriteObject (w, o.GetType (), ctx);
  705. WriteObject (w, value, ctx);
  706. }
  707. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  708. {
  709. Type t = (Type) ReadObject (r, ctx);
  710. object value = ReadObject (r, ctx);
  711. return Enum.ToObject (t, value);
  712. }
  713. protected override Type Type {
  714. get { return typeof (Enum); }
  715. }
  716. }
  717. class TypeFormatter : ObjectFormatter
  718. {
  719. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  720. {
  721. if (ctx.RegisterCache (o)) {
  722. w.Write (SecondaryId);
  723. w.Write (ctx.Key);
  724. } else {
  725. w.Write (PrimaryId);
  726. w.Write (((Type) o).FullName);
  727. // We should cache the name of the assembly
  728. w.Write (((Type) o).Assembly.FullName);
  729. }
  730. }
  731. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  732. {
  733. if (token == PrimaryId) {
  734. string type = r.ReadString ();
  735. string assembly = r.ReadString ();
  736. Type t = Assembly.Load (assembly).GetType (type);
  737. ctx.CacheItem (t);
  738. return t;
  739. } else {
  740. return ctx.GetCache (r.ReadInt16 ());
  741. }
  742. }
  743. protected override Type Type {
  744. get { return typeof (Type); }
  745. }
  746. protected override int NumberOfIds {
  747. get { return 2; }
  748. }
  749. }
  750. class SingleRankArrayFormatter : ObjectFormatter
  751. {
  752. readonly BinaryFormatter _binaryFormatter = new BinaryFormatter ();
  753. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  754. {
  755. Array val = (Array) o;
  756. if (val.GetType ().GetElementType ().IsPrimitive) {
  757. w.Write (SecondaryId);
  758. _binaryFormatter.Serialize (w.BaseStream, o);
  759. return;
  760. }
  761. w.Write (PrimaryId);
  762. WriteObject (w, val.GetType ().GetElementType (), ctx);
  763. Write7BitEncodedInt (w, val.Length);
  764. for (int i = 0; i < val.Length; i++)
  765. WriteObject (w, val.GetValue (i), ctx);
  766. }
  767. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  768. {
  769. if (token == SecondaryId)
  770. return _binaryFormatter.Deserialize (r.BaseStream);
  771. Type t = (Type) ReadObject (r, ctx);
  772. int len = Read7BitEncodedInt (r);
  773. Array val = Array.CreateInstance (t, len);
  774. for (int i = 0; i < len; i++)
  775. val.SetValue (ReadObject (r, ctx), i);
  776. return val;
  777. }
  778. protected override Type Type {
  779. get { return typeof (Array); }
  780. }
  781. protected override int NumberOfIds {
  782. get { return 2; }
  783. }
  784. }
  785. class FontUnitFormatter : StringFormatter
  786. {
  787. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  788. {
  789. base.Write (w, o.ToString (), ctx);
  790. }
  791. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  792. {
  793. return FontUnit.Parse ((string) base.Read (token, r, ctx));
  794. }
  795. protected override Type Type {
  796. get { return typeof (FontUnit); }
  797. }
  798. }
  799. class UnitFormatter : StringFormatter
  800. {
  801. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  802. {
  803. base.Write (w, o.ToString (), ctx);
  804. }
  805. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  806. {
  807. return Unit.Parse ((string) base.Read (token, r, ctx));
  808. }
  809. protected override Type Type {
  810. get { return typeof (Unit); }
  811. }
  812. }
  813. class TypeConverterFormatter : StringFormatter
  814. {
  815. TypeConverter converter;
  816. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  817. {
  818. w.Write (PrimaryId);
  819. ObjectFormatter.WriteObject (w, o.GetType (), ctx);
  820. string v = (string) converter.ConvertTo (null, Helpers.InvariantCulture,
  821. o, typeof (string));
  822. base.Write (w, v, ctx);
  823. }
  824. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  825. {
  826. Type t = (Type) ObjectFormatter.ReadObject (r, ctx);
  827. converter = TypeDescriptor.GetConverter (t);
  828. token = r.ReadByte ();
  829. string v = (string) base.Read (token, r, ctx);
  830. return converter.ConvertFrom (null, Helpers.InvariantCulture, v);
  831. }
  832. protected override Type Type {
  833. get { return typeof (TypeConverter); }
  834. }
  835. public TypeConverter Converter {
  836. set { converter = value; }
  837. }
  838. }
  839. class BinaryObjectFormatter : ObjectFormatter
  840. {
  841. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  842. {
  843. w.Write (PrimaryId);
  844. MemoryStream ms = new MemoryStream (128);
  845. new BinaryFormatter ().Serialize (ms, o);
  846. byte [] buf = ms.GetBuffer ();
  847. Write7BitEncodedInt (w, buf.Length);
  848. w.Write (buf, 0, buf.Length);
  849. }
  850. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  851. {
  852. int len = Read7BitEncodedInt (r);
  853. byte [] buf = r.ReadBytes (len);
  854. if (buf.Length != len)
  855. throw new Exception ();
  856. return new BinaryFormatter ().Deserialize (new MemoryStream (buf));
  857. }
  858. protected override Type Type {
  859. get { return typeof (object); }
  860. }
  861. }
  862. #endregion
  863. #endregion
  864. }
  865. }