| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060 |
- //
- // System.Web.UI.ObjectStateFormatter
- //
- // Authors:
- // Ben Maurer ([email protected])
- // Gonzalo Paniagua ([email protected])
- //
- // (C) 2003 Ben Maurer
- // (c) Copyright 2004-2008 Novell, Inc. (http://www.novell.com)
- //
- //
- // 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.
- //
- //#define TRACE
- using System.Collections;
- using System.ComponentModel;
- using System.Globalization;
- using System.Drawing;
- using System.IO;
- using System.Reflection;
- using System.Runtime.Serialization.Formatters.Binary;
- using System.Runtime.Serialization;
- using System.Text;
- using System.Web.UI.WebControls;
- using System.Web.Util;
- using System.Diagnostics;
- using System.Security.Cryptography;
- using System.Web.Configuration;
- namespace System.Web.UI {
- #if NET_2_0
- public
- #else
- internal
- #endif
- sealed class ObjectStateFormatter : IFormatter, IStateFormatter
- {
- Page page;
- HashAlgorithm algo;
- byte [] vkey;
- public ObjectStateFormatter ()
- {
- }
-
- internal ObjectStateFormatter (Page page)
- {
- this.page = page;
- }
- internal ObjectStateFormatter (byte [] vkey)
- {
- this.vkey = vkey;
- }
-
- internal bool EnableMac {
- get {
- if (page == null) {
- if (vkey == null)
- return false;
- return true;
- } else {
-
- #if NET_2_0
- return page.EnableViewStateMac;
- #elif NET_1_1
- return page.EnableViewStateMacInternal;
- #else
- return false;
- #endif
- }
- }
- }
- internal HashAlgorithm GetAlgo ()
- {
- if (algo != null)
- return algo;
- if (!EnableMac)
- return null;
-
- byte [] algoKey;
- if (page != null) {
- #if NET_2_0
- MachineKeySection mconfig = (MachineKeySection) WebConfigurationManager.GetSection ("system.web/machineKey");
- algoKey = MachineKeySectionUtils.ValidationKeyBytes (mconfig);
- #else
- MachineKeyConfig mconfig = HttpContext.GetAppConfig ("system.web/machineKey") as MachineKeyConfig;
- algoKey = mconfig.ValidationKey;
- #endif
- } else
- algoKey = vkey;
-
- return new HMACSHA1 (algoKey);
- }
- static int ValidateInput (HashAlgorithm algo, byte [] data, int offset, int size)
- {
- if (algo == null)
- throw new HttpException ("Unable to validate data.");
-
- int hash_size = algo.HashSize / 8;
- if (size != 0 && size < hash_size)
- throw new HttpException ("Unable to validate data.");
- int data_length = size - hash_size;
- MemoryStream data_stream = new MemoryStream (data, offset, data_length, false, false);
- byte [] hash = algo.ComputeHash (data_stream);
- for (int i = 0; i < hash_size; i++) {
- if (hash [i] != data [data_length + i])
- throw new HttpException ("Unable to validate data.");
- }
- return data_length;
- }
-
- public object Deserialize (Stream inputStream)
- {
- if (inputStream == null)
- throw new ArgumentNullException ("inputStream");
- return DeserializeObject (new BinaryReader (inputStream));
- }
-
- public object Deserialize (string inputString)
- {
- if (inputString == null)
- throw new ArgumentNullException ("inputString");
- #if NET_2_0
- if (inputString.Length == 0)
- throw new ArgumentNullException ("inputString");
- #else
- if (inputString == "")
- return "";
- #endif
- byte [] buffer = Convert.FromBase64String (inputString);
- int length;
- if (buffer == null || (length = buffer.Length) == 0)
- throw new ArgumentNullException ("inputString");
- if (page != null && EnableMac)
- length = ValidateInput (GetAlgo (), buffer, 0, length);
- #if NET_2_0
- bool isEncrypted = ((int)buffer [--length] == 1)? true : false;
- #endif
- Stream ms = new MemoryStream (buffer, 0, length, false, false);
- #if NET_2_0
- if (isEncrypted)
- ms = new CryptoStream (ms, page.GetCryptoTransform (CryptoStreamMode.Read), CryptoStreamMode.Read);
- #endif
- return Deserialize (ms);
- }
-
- public string Serialize (object stateGraph)
- {
- if (stateGraph == null)
- return "";
-
- MemoryStream ms = new MemoryStream ();
- Stream output = ms;
- #if NET_2_0
- bool needEncryption = page == null ? false : page.NeedViewStateEncryption;
- if (needEncryption){
- output = new CryptoStream (output, page.GetCryptoTransform (CryptoStreamMode.Write), CryptoStreamMode.Write);
- }
- #endif
- Serialize (output, stateGraph);
- #if NET_2_0
- ms.WriteByte((byte)(needEncryption? 1 : 0));
- #endif
-
- #if TRACE
- ms.WriteTo (File.OpenWrite (Path.GetTempFileName ()));
- #endif
- if (EnableMac && ms.Length > 0) {
- HashAlgorithm algo = GetAlgo ();
- if (algo != null) {
- byte [] hash = algo.ComputeHash (ms.GetBuffer (), 0, (int) ms.Length);
- ms.Write (hash, 0, hash.Length);
- }
-
- }
- return Convert.ToBase64String (ms.GetBuffer (), 0, (int) ms.Length);
- }
-
- public void Serialize (Stream outputStream, object stateGraph)
- {
- if (outputStream == null)
- throw new ArgumentNullException ("outputStream");
- if (stateGraph == null)
- throw new ArgumentNullException ("stateGraph");
- SerializeValue (new BinaryWriter (outputStream), stateGraph);
- }
-
- void SerializeValue (BinaryWriter w, object o)
- {
- ObjectFormatter.WriteObject (w, o, new WriterContext ());
- }
-
- object DeserializeObject (BinaryReader r)
- {
- return ObjectFormatter.ReadObject (r, new ReaderContext ());
- }
-
- #region IFormatter
-
- object IFormatter.Deserialize (Stream serializationStream)
- {
- return Deserialize (serializationStream);
- }
-
- void IFormatter.Serialize (Stream serializationStream, object stateGraph)
- {
- Serialize (serializationStream, stateGraph);
- }
-
- SerializationBinder IFormatter.Binder {
- get { return null; }
- set { }
- }
-
- StreamingContext IFormatter.Context {
- get { return new StreamingContext (StreamingContextStates.All); }
- set { }
- }
-
- ISurrogateSelector IFormatter.SurrogateSelector {
- get { return null; }
- set { }
- }
-
- #endregion
- #region Object Readers/Writers
-
- class WriterContext
- {
- Hashtable cache;
- short nextKey = 0;
- short key = 0;
- public short Key {
- get { return key; }
- }
- public bool RegisterCache (object o)
- {
- if (nextKey == short.MaxValue)
- return false;
- if (cache == null) {
- cache = new Hashtable ();
- cache.Add (o, key = nextKey++);
- return false;
- }
-
- object posKey = cache [o];
- if (posKey == null) {
- cache.Add (o, key = nextKey++);
- return false;
- }
-
- key = (short) posKey;
- return true;
- }
- }
-
- class ReaderContext
- {
- ArrayList cache;
-
- public void CacheItem (object o)
- {
- if (cache == null)
- cache = new ArrayList ();
-
- cache.Add (o);
- }
-
- public object GetCache (short key)
- {
- return cache [key];
- }
- }
-
- abstract class ObjectFormatter
- {
- static readonly Hashtable writeMap = new Hashtable ();
- static ObjectFormatter [] readMap = new ObjectFormatter [256];
- static BinaryObjectFormatter binaryObjectFormatter;
- static TypeFormatter typeFormatter;
- static EnumFormatter enumFormatter;
- static SingleRankArrayFormatter singleRankArrayFormatter;
- static TypeConverterFormatter typeConverterFormatter;
-
- static ObjectFormatter ()
- {
- new StringFormatter ().Register ();
- new Int64Formatter ().Register ();
- new Int32Formatter ().Register ();
- new Int16Formatter ().Register ();
- new ByteFormatter ().Register ();
- new BooleanFormatter ().Register ();
- new CharFormatter ().Register ();
- new DateTimeFormatter ().Register ();
- new PairFormatter ().Register ();
- new TripletFormatter ().Register ();
- new ArrayListFormatter ().Register ();
- new HashtableFormatter ().Register ();
- new ObjectArrayFormatter ().Register ();
- new UnitFormatter ().Register ();
- new FontUnitFormatter ().Register ();
-
- new ColorFormatter ().Register ();
- enumFormatter = new EnumFormatter ();
- enumFormatter.Register ();
- typeFormatter = new TypeFormatter ();
- typeFormatter.Register ();
- singleRankArrayFormatter = new SingleRankArrayFormatter ();
- singleRankArrayFormatter.Register ();
- typeConverterFormatter = new TypeConverterFormatter ();
- typeConverterFormatter.Register ();
- binaryObjectFormatter = new BinaryObjectFormatter ();
- binaryObjectFormatter.Register ();
- }
-
- // 0 == null
- static byte nextId = 1;
-
- public ObjectFormatter ()
- {
- PrimaryId = nextId ++;
- if (NumberOfIds == 1)
- return;
-
- SecondaryId = nextId ++;
- if (NumberOfIds == 2)
- return;
-
- TertiaryId = nextId ++;
- if (NumberOfIds == 3)
- return;
-
- throw new Exception ();
- }
-
- protected readonly byte PrimaryId, SecondaryId = 255, TertiaryId = 255;
-
- protected abstract void Write (BinaryWriter w, object o, WriterContext ctx);
- protected abstract object Read (byte token, BinaryReader r, ReaderContext ctx);
- protected abstract Type Type { get; }
- protected virtual int NumberOfIds { get { return 1; } }
-
- public virtual void Register ()
- {
- writeMap [Type] = this;
- readMap [PrimaryId] = this;
- if (SecondaryId != 255) {
- readMap [SecondaryId] = this;
- if (TertiaryId != 255)
- readMap [TertiaryId] = this;
- }
- }
-
- public static void WriteObject (BinaryWriter w, object o, WriterContext ctx)
- {
- #if TRACE
- if (o != null) {
- Trace.WriteLine (String.Format ("Writing {0} (type: {1})", o, o.GetType ()));
- Trace.Indent ();
- } else {
- Trace.WriteLine ("Writing null");
- }
- long pos = w.BaseStream.Position;
- #endif
-
- if (o == null) {
- w.Write ((byte) 0);
- return;
- }
-
- Type t = o.GetType ();
- #if TRACE
- Trace.WriteLine (String.Format ("Looking up formatter for type {0}", t));
- #endif
- ObjectFormatter fmt = writeMap [t] as ObjectFormatter;
- #if TRACE
- Trace.WriteLine (String.Format ("Formatter from writeMap: '{0}'", fmt));
- #endif
- if (fmt == null) {
- // Handle abstract types here
-
- if (o is Type)
- fmt = typeFormatter;
- else if (t.IsEnum)
- fmt = enumFormatter;
- else if (t.IsArray && ((Array) o).Rank == 1)
- fmt = singleRankArrayFormatter;
- else {
- TypeConverter converter;
- converter = TypeDescriptor.GetConverter (o);
- #if TRACE
- Trace.WriteLine (String.Format ("Type converter: '{0}' (to string: {1}; from {2}: {3})",
- converter,
- converter != null ? converter.CanConvertTo (typeof (string)) : false,
- t,
- converter != null ? converter.CanConvertFrom (t) : false));
- #endif
- if (converter == null ||
- !converter.CanConvertTo (typeof (string)) ||
- !converter.CanConvertFrom (t)) {
- fmt = binaryObjectFormatter;
- } else {
- typeConverterFormatter.Converter = converter;
- fmt = typeConverterFormatter;
- }
- }
- }
- #if TRACE
- Trace.WriteLine (String.Format ("Writing with formatter '{0}'", fmt.GetType ()));
- #endif
- fmt.Write (w, o, ctx);
- #if TRACE
- Trace.Unindent ();
- Trace.WriteLine (String.Format ("Wrote {0} (type: {1}) {2} bytes", o, o.GetType (), w.BaseStream.Position - pos));
- #endif
- }
-
- public static object ReadObject (BinaryReader r, ReaderContext ctx)
- {
- byte sig = r.ReadByte ();
-
- if (sig == 0)
- return null;
-
- return readMap [sig].Read (sig, r, ctx);
- }
-
- protected void Write7BitEncodedInt (BinaryWriter w, int value)
- {
- do {
- int high = (value >> 7) & 0x01ffffff;
- byte b = (byte)(value & 0x7f);
-
- if (high != 0)
- b = (byte)(b | 0x80);
-
- w.Write(b);
- value = high;
- } while(value != 0);
- }
-
- protected int Read7BitEncodedInt (BinaryReader r)
- {
- int ret = 0;
- int shift = 0;
- byte b;
-
- do {
- b = r.ReadByte();
-
- ret = ret | ((b & 0x7f) << shift);
- shift += 7;
- } while ((b & 0x80) == 0x80);
-
- return ret;
- }
- }
-
- #region Primitive Formatters
- class StringFormatter : ObjectFormatter
- {
- protected override void Write (BinaryWriter w, object o, WriterContext ctx)
- {
- if (ctx.RegisterCache (o)) {
- w.Write (SecondaryId);
- w.Write (ctx.Key);
- } else {
- w.Write (PrimaryId);
- w.Write ((string)o);
- }
- }
-
- protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
- {
- if (token == PrimaryId) {
- string s = r.ReadString ();
- ctx.CacheItem (s);
- return s;
- } else {
- return ctx.GetCache (r.ReadInt16 ());
- }
- }
- protected override Type Type {
- get { return typeof (string); }
- }
-
- protected override int NumberOfIds {
- get { return 2; }
- }
- }
-
- class Int64Formatter : ObjectFormatter
- {
- protected override void Write (BinaryWriter w, object o, WriterContext ctx)
- {
- w.Write (PrimaryId);
- w.Write ((long)o);
- }
-
- protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
- {
- return r.ReadInt64 ();
- }
- protected override Type Type {
- get { return typeof (long); }
- }
- }
-
- class Int32Formatter : ObjectFormatter
- {
- protected override void Write (BinaryWriter w, object o, WriterContext ctx)
- {
- int i = (int) o;
- if ((int)(byte) i == i) {
- w.Write (SecondaryId);
- w.Write ((byte) i);
- } else {
- w.Write (PrimaryId);
- w.Write (i);
- }
- }
-
- protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
- {
- if (token == PrimaryId)
- return r.ReadInt32 ();
- else
- return (int) r.ReadByte ();
- }
-
- protected override Type Type {
- get { return typeof (int); }
- }
-
- protected override int NumberOfIds {
- get { return 2; }
- }
- }
-
- class Int16Formatter : ObjectFormatter
- {
- protected override void Write (BinaryWriter w, object o, WriterContext ctx)
- {
- w.Write (PrimaryId);
- w.Write ((short)o);
- }
-
- protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
- {
- return r.ReadInt16 ();
- }
- protected override Type Type {
- get { return typeof (short); }
- }
- }
-
- class ByteFormatter : ObjectFormatter
- {
- protected override void Write (BinaryWriter w, object o, WriterContext ctx)
- {
- w.Write (PrimaryId);
- w.Write ((byte)o);
- }
-
- protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
- {
- return r.ReadByte ();
- }
- protected override Type Type {
- get { return typeof (byte); }
- }
- }
-
- class BooleanFormatter : ObjectFormatter
- {
- protected override void Write (BinaryWriter w, object o, WriterContext ctx)
- {
- if ((bool)o == true)
- w.Write (PrimaryId);
- else
- w.Write (SecondaryId);
- }
-
- protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
- {
- return token == PrimaryId;
- }
-
- protected override Type Type {
- get { return typeof (bool); }
- }
-
- protected override int NumberOfIds {
- get { return 2; }
- }
- }
-
- class CharFormatter : ObjectFormatter
- {
- protected override void Write (BinaryWriter w, object o, WriterContext ctx)
- {
- w.Write (PrimaryId);
- w.Write ((char) o);
- }
-
- protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
- {
- return r.ReadChar ();
- }
-
- protected override Type Type {
- get { return typeof (char); }
- }
- }
-
- class DateTimeFormatter : ObjectFormatter
- {
- protected override void Write (BinaryWriter w, object o, WriterContext ctx)
- {
- w.Write (PrimaryId);
- w.Write (((DateTime) o).Ticks);
- }
-
- protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
- {
- return new DateTime (r.ReadInt64 ());
- }
-
- protected override Type Type {
- get { return typeof (DateTime); }
- }
- }
-
- class PairFormatter : ObjectFormatter
- {
- protected override void Write (BinaryWriter w, object o, WriterContext ctx)
- {
- Pair p = (Pair) o;
- w.Write (PrimaryId);
- WriteObject (w, p.First, ctx);
- WriteObject (w, p.Second, ctx);
- }
-
- protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
- {
- Pair p = new Pair ();
- p.First = ReadObject (r, ctx);
- p.Second = ReadObject (r, ctx);
- return p;
- }
-
- protected override Type Type {
- get { return typeof (Pair); }
- }
- }
-
- class TripletFormatter : ObjectFormatter
- {
- protected override void Write (BinaryWriter w, object o, WriterContext ctx)
- {
- Triplet t = (Triplet) o;
- w.Write (PrimaryId);
- WriteObject (w, t.First, ctx);
- WriteObject (w, t.Second, ctx);
- WriteObject (w, t.Third, ctx);
- }
-
- protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
- {
- Triplet t = new Triplet ();
- t.First = ReadObject (r, ctx);
- t.Second = ReadObject (r, ctx);
- t.Third = ReadObject (r, ctx);
- return t;
- }
-
- protected override Type Type {
- get { return typeof (Triplet); }
- }
- }
-
- class ArrayListFormatter : ObjectFormatter
- {
- protected override void Write (BinaryWriter w, object o, WriterContext ctx)
- {
- ArrayList l = (ArrayList) o;
-
- w.Write (PrimaryId);
- Write7BitEncodedInt (w, l.Count);
- for (int i = 0; i < l.Count; i++)
- WriteObject (w, l [i], ctx);
- }
-
- protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
- {
- int len = Read7BitEncodedInt (r);
- ArrayList l = new ArrayList (len);
-
- for (int i = 0; i < len; i++)
- l.Add (ReadObject (r, ctx));
-
- return l;
- }
-
- protected override Type Type {
- get { return typeof (ArrayList); }
- }
- }
-
- class HashtableFormatter : ObjectFormatter
- {
- protected override void Write (BinaryWriter w, object o, WriterContext ctx)
- {
- Hashtable ht = (Hashtable) o;
-
- w.Write (PrimaryId);
- Write7BitEncodedInt (w, ht.Count);
- foreach (DictionaryEntry de in ht) {
- WriteObject (w, de.Key, ctx);
- WriteObject (w, de.Value, ctx);
- }
- }
-
- protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
- {
- int len = Read7BitEncodedInt (r);
- Hashtable ht = new Hashtable (len);
-
- for (int i = 0; i < len; i++) {
- object key = ReadObject (r, ctx);
- object val = ReadObject (r, ctx);
-
- ht.Add (key, val);
- }
-
- return ht;
- }
-
- protected override Type Type {
- get { return typeof (Hashtable); }
- }
- }
-
- class ObjectArrayFormatter : ObjectFormatter
- {
- protected override void Write (BinaryWriter w, object o, WriterContext ctx)
- {
- object [] val = (object []) o;
-
- w.Write (PrimaryId);
- Write7BitEncodedInt (w, val.Length);
- for (int i = 0; i < val.Length; i++)
- WriteObject (w, val [i], ctx);
- }
-
- protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
- {
- int len = Read7BitEncodedInt (r);
- object [] ret = new object [len];
-
- for (int i = 0; i < len; i++)
- ret [i] = ReadObject (r, ctx);
-
- return ret;
- }
-
- protected override Type Type {
- get { return typeof (object []); }
- }
- }
-
- #endregion
-
- #region System.Web Optimizations
- class ColorFormatter : ObjectFormatter
- {
- protected override void Write (BinaryWriter w, object o, WriterContext ctx)
- {
- Color c = (Color) o;
-
- if (c.IsEmpty || c.IsKnownColor) {
- w.Write (SecondaryId);
- if (c.IsEmpty)
- w.Write (-1); //isempty marker
- else
- w.Write ((int) c.ToKnownColor ());
- } else {
- w.Write (PrimaryId);
- w.Write (c.ToArgb ());
- }
- }
-
- protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
- {
- int value = r.ReadInt32 ();
- if (token == PrimaryId)
- return Color.FromArgb (value);
- else {
- if (value == -1) //isempty marker
- return Color.Empty;
- return Color.FromKnownColor ((KnownColor)value);
- }
- }
-
- protected override Type Type {
- get { return typeof (Color); }
- }
-
- protected override int NumberOfIds {
- get { return 2; }
- }
- }
-
- #endregion
-
- #region Special Formatters
- class EnumFormatter : ObjectFormatter
- {
- protected override void Write (BinaryWriter w, object o, WriterContext ctx)
- {
- object value = Convert.ChangeType (o, ((Enum) o).GetTypeCode ());
- w.Write (PrimaryId);
- WriteObject (w, o.GetType (), ctx);
- WriteObject (w, value, ctx);
- }
-
- protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
- {
- Type t = (Type) ReadObject (r, ctx);
- object value = ReadObject (r, ctx);
-
- return Enum.ToObject (t, value);
- }
- protected override Type Type {
- get { return typeof (Enum); }
- }
- }
-
- class TypeFormatter : ObjectFormatter
- {
- protected override void Write (BinaryWriter w, object o, WriterContext ctx)
- {
- if (ctx.RegisterCache (o)) {
- w.Write (SecondaryId);
- w.Write (ctx.Key);
- } else {
- w.Write (PrimaryId);
- w.Write (((Type) o).FullName);
- // We should cache the name of the assembly
- w.Write (((Type) o).Assembly.FullName);
- }
- }
-
- protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
- {
- if (token == PrimaryId) {
- string type = r.ReadString ();
- string assembly = r.ReadString ();
- Type t = Assembly.Load (assembly).GetType (type);
- ctx.CacheItem (t);
- return t;
- } else {
- return ctx.GetCache (r.ReadInt16 ());
- }
- }
-
- protected override Type Type {
- get { return typeof (Type); }
- }
-
- protected override int NumberOfIds {
- get { return 2; }
- }
- }
-
- class SingleRankArrayFormatter : ObjectFormatter
- {
- readonly BinaryFormatter _binaryFormatter = new BinaryFormatter ();
- protected override void Write (BinaryWriter w, object o, WriterContext ctx)
- {
- Array val = (Array) o;
- if (val.GetType ().GetElementType ().IsPrimitive) {
- w.Write (SecondaryId);
- _binaryFormatter.Serialize (w.BaseStream, o);
- return;
- }
-
- w.Write (PrimaryId);
- WriteObject (w, val.GetType ().GetElementType (), ctx);
-
- Write7BitEncodedInt (w, val.Length);
- for (int i = 0; i < val.Length; i++)
- WriteObject (w, val.GetValue (i), ctx);
- }
-
- protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
- {
- if (token == SecondaryId)
- return _binaryFormatter.Deserialize (r.BaseStream);
- Type t = (Type) ReadObject (r, ctx);
- int len = Read7BitEncodedInt (r);
- Array val = Array.CreateInstance (t, len);
-
- for (int i = 0; i < len; i++)
- val.SetValue (ReadObject (r, ctx), i);
-
- return val;
- }
-
- protected override Type Type {
- get { return typeof (Array); }
- }
- protected override int NumberOfIds {
- get { return 2; }
- }
- }
-
- class FontUnitFormatter : StringFormatter
- {
- protected override void Write (BinaryWriter w, object o, WriterContext ctx)
- {
- base.Write (w, o.ToString (), ctx);
- }
-
- protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
- {
- return FontUnit.Parse ((string) base.Read (token, r, ctx));
- }
-
- protected override Type Type {
- get { return typeof (FontUnit); }
- }
- }
- class UnitFormatter : StringFormatter
- {
- protected override void Write (BinaryWriter w, object o, WriterContext ctx)
- {
- base.Write (w, o.ToString (), ctx);
- }
-
- protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
- {
- return Unit.Parse ((string) base.Read (token, r, ctx));
- }
-
- protected override Type Type {
- get { return typeof (Unit); }
- }
- }
- class TypeConverterFormatter : StringFormatter
- {
- TypeConverter converter;
- protected override void Write (BinaryWriter w, object o, WriterContext ctx)
- {
- w.Write (PrimaryId);
- ObjectFormatter.WriteObject (w, o.GetType (), ctx);
- string v = (string) converter.ConvertTo (null, CultureInfo.InvariantCulture,
- o, typeof (string));
- base.Write (w, v, ctx);
- }
-
- protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
- {
- Type t = (Type) ObjectFormatter.ReadObject (r, ctx);
- converter = TypeDescriptor.GetConverter (t);
- token = r.ReadByte ();
- string v = (string) base.Read (token, r, ctx);
- return converter.ConvertFrom (null, CultureInfo.InvariantCulture, v);
- }
-
- protected override Type Type {
- get { return typeof (TypeConverter); }
- }
- public TypeConverter Converter {
- set { converter = value; }
- }
- }
- class BinaryObjectFormatter : ObjectFormatter
- {
- protected override void Write (BinaryWriter w, object o, WriterContext ctx)
- {
- w.Write (PrimaryId);
-
- MemoryStream ms = new MemoryStream (128);
- new BinaryFormatter ().Serialize (ms, o);
-
- byte [] buf = ms.GetBuffer ();
- Write7BitEncodedInt (w, buf.Length);
- w.Write (buf, 0, buf.Length);
- }
-
- protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
- {
- int len = Read7BitEncodedInt (r);
- byte [] buf = r.ReadBytes (len);
- if (buf.Length != len)
- throw new Exception ();
-
- return new BinaryFormatter ().Deserialize (new MemoryStream (buf));
- }
-
- protected override Type Type {
- get { return typeof (object); }
- }
- }
-
- #endregion
-
- #endregion
- }
- }
|