public void ReadObject(Amf3Reader reader, object obj)
        {
            // see if object implements IAmf3Readable, if so, use it instead of reflection
            var serializable = obj as IAmf3Readable;

            if (serializable != null)
            {
                // read using custom method (fast)
                serializable.Serialize(reader);
                return;
            }

            // read using reflection (slow)
            // begin read
            reader.ReadObjectHeader(mClassDef);

            // read all fields using reflection
            foreach (var field in mFieldList)
            {
                // read value
                Variant value = reader.ReadAsVariant();
                if (value.IsDefined)
                {
                    field.SetValue(obj, value.AsType(field.FieldType));
                }
            }

            // read all properties using reflection
            foreach (var property in mPropertyList)
            {
                // read value
                Variant value = reader.ReadAsVariant();
                if (value.IsDefined)
                {
                    property.SetValue(obj, value.AsType(property.PropertyType), null);
                }
            }
        }
        private void WriteVariant(Variant value)
        {
            switch (value.Kind)
            {
                case VariantKind.Null:
                    _writer.Write((byte)EncodingKind.Null);
                    break;

                case VariantKind.Boolean:
                    _writer.Write((byte)(value.AsBoolean() ? EncodingKind.Boolean_True : EncodingKind.Boolean_False));
                    break;

                case VariantKind.Byte:
                    _writer.Write((byte)EncodingKind.UInt8);
                    _writer.Write(value.AsByte());
                    break;

                case VariantKind.SByte:
                    _writer.Write((byte)EncodingKind.Int8);
                    _writer.Write(value.AsSByte());
                    break;

                case VariantKind.Int16:
                    _writer.Write((byte)EncodingKind.Int16);
                    _writer.Write(value.AsInt16());
                    break;

                case VariantKind.UInt16:
                    _writer.Write((byte)EncodingKind.UInt16);
                    _writer.Write(value.AsUInt16());
                    break;

                case VariantKind.Int32:
                    {
                        var v = value.AsInt32();
                        if (v >= 0 && v <= 10)
                        {
                            _writer.Write((byte)((int)EncodingKind.Int32_0 + v));
                        }
                        else if (v >= 0 && v < byte.MaxValue)
                        {
                            _writer.Write((byte)EncodingKind.Int32_1Byte);
                            _writer.Write((byte)v);
                        }
                        else if (v >= 0 && v < ushort.MaxValue)
                        {
                            _writer.Write((byte)EncodingKind.Int32_2Bytes);
                            _writer.Write((ushort)v);
                        }
                        else
                        {
                            _writer.Write((byte)EncodingKind.Int32);
                            _writer.Write(v);
                        }
                    }
                    break;

                case VariantKind.UInt32:
                    {
                        var v = value.AsUInt32();
                        if (v >= 0 && v <= 10)
                        {
                            _writer.Write((byte)((int)EncodingKind.UInt32_0 + v));
                        }
                        else if (v >= 0 && v < byte.MaxValue)
                        {
                            _writer.Write((byte)EncodingKind.UInt32_1Byte);
                            _writer.Write((byte)v);
                        }
                        else if (v >= 0 && v < ushort.MaxValue)
                        {
                            _writer.Write((byte)EncodingKind.UInt32_2Bytes);
                            _writer.Write((ushort)v);
                        }
                        else
                        {
                            _writer.Write((byte)EncodingKind.UInt32);
                            _writer.Write(v);
                        }
                    }
                    break;

                case VariantKind.Int64:
                    _writer.Write((byte)EncodingKind.Int64);
                    _writer.Write(value.AsInt64());
                    break;

                case VariantKind.UInt64:
                    _writer.Write((byte)EncodingKind.UInt64);
                    _writer.Write(value.AsUInt64());
                    break;

                case VariantKind.Decimal:
                    _writer.Write((byte)EncodingKind.Decimal);
                    _writer.Write(value.AsDecimal());
                    break;

                case VariantKind.Float4:
                    _writer.Write((byte)EncodingKind.Float4);
                    _writer.Write(value.AsSingle());
                    break;

                case VariantKind.Float8:
                    _writer.Write((byte)EncodingKind.Float8);
                    _writer.Write(value.AsDouble());
                    break;

                case VariantKind.Char:
                    _writer.Write((byte)EncodingKind.Char);
                    _writer.Write((ushort)value.AsChar());  // written as ushort because BinaryWriter fails on chars that are unicode surrogates
                    break;

                case VariantKind.String:
                    WriteStringValue(value.AsString());
                    break;

                case VariantKind.BoxedEnum:
                    var e = value.AsBoxedEnum();
                    WriteBoxedEnum(e, e.GetType());
                    break;

                case VariantKind.DateTime:
                    _writer.Write((byte)EncodingKind.DateTime);
                    _writer.Write(value.AsDateTime().ToBinary());
                    break;

                case VariantKind.Type:
                    WriteType(value.AsType());
                    break;

                case VariantKind.Array:
                    WriteArray(value.AsArray());
                    break;

                case VariantKind.Object:
                    WriteObject(value.AsObject());
                    break;
            }
        }