//
Copyright (c) 2007-2008 Henrik Schr鰀er, Oliver Kofoed Pedersen
//
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.
#region
文件信息
/*
=================================================================
* 文件:Serializer.cs
* 创建者:<原作者>
* 创建日期:<未知>
* 最后修改:(楼下请注意保持队形)
* ##############################################################
* 时间 修改人 备注
* 2010-04-19 田真 因为TT不支持Memcached的类型存储,这里修改了序列化方式,主要体现在对Serialize和Deserialize方法的修改
* 2010-04-19 田真 增加了MergedBuffer和ParsedBuffer两个方法
* 2010-04-19 田真 修改SerializedType继承自byte,以前是ushort
* 2010-04-19 田真 修改CompressedByteArray = 255, CompressedObject = 256, CompressedString = 257
* 为:CompressedByteArray = 253, CompressedObject = 254, CompressedString = 255
* ##############################################################
* ================================================================
*/
#endregion
using
System;
using
System.IO;
using
System.IO.Compression;
using
System.Runtime.Serialization.Formatters.Binary;
using
System.Text;
namespace
SubCon.Caching.MemCached
{
///
<summary>
///
序列化的对象类型
///
</summary>
internal
enum
SerializedType :
byte
{
ByteArray
=
0
,
Object
=
1
,
String
=
2
,
Datetime
=
3
,
Bool
=
4
,
//
SByte = 5,
//
Makes no sense.
Byte
=
6
,
Short
=
7
,
UShort
=
8
,
Int
=
9
,
UInt
=
10
,
Long
=
11
,
ULong
=
12
,
Float
=
13
,
Double
=
14
,
CompressedByteArray
=
253
,
CompressedObject
=
254
,
CompressedString
=
255
,
}
///
<summary>
///
存储值序列器
///
</summary>
internal
class
Serializer
{
///
<summary>
///
序列化存储值
///
</summary>
///
<param name="value">
要进行序列化的值
</param>
///
<param name="type">
被序列的值是什么类型
</param>
///
<param name="compressionThreshold">
压缩基准,当序列化后的字节数组长度大于该值时进行压缩
</param>
///
<returns></returns>
public
static
byte
[] Serialize(
object
value,
out
SerializedType type,
uint
compressionThreshold) {
byte
[] bytes;
if
(value
is
byte
[]) {
bytes
=
(
byte
[])value;
type
=
SerializedType.ByteArray;
if
(bytes.Length
>
compressionThreshold) {
bytes
=
Compress(bytes);
type
=
SerializedType.CompressedByteArray;
}
}
else
if
(value
is
string
) {
bytes
=
Encoding.UTF8.GetBytes((
string
)value);
type
=
SerializedType.String;
if
(bytes.Length
>
compressionThreshold) {
bytes
=
Compress(bytes);
type
=
SerializedType.CompressedString;
}
}
else
if
(value
is
DateTime) {
bytes
=
BitConverter.GetBytes(((DateTime)value).Ticks);
type
=
SerializedType.Datetime;
}
else
if
(value
is
bool
) {
bytes
=
new
byte
[]{(
byte
)((
bool
)value
?
1
:
0
)};
type
=
SerializedType.Bool;
}
else
if
(value
is
byte
) {
bytes
=
new
byte
[]{(
byte
)value};
type
=
SerializedType.Byte;
}
else
if
(value
is
short
) {
bytes
=
BitConverter.GetBytes((
short
)value);
type
=
SerializedType.Short;
}
else
if
(value
is
ushort
) {
bytes
=
BitConverter.GetBytes((
ushort
)value);
type
=
SerializedType.UShort;
}
else
if
(value
is
int
) {
bytes
=
BitConverter.GetBytes((
int
)value);
type
=
SerializedType.Int;
}
else
if
(value
is
uint
) {
bytes
=
BitConverter.GetBytes((
uint
)value);
type
=
SerializedType.UInt;
}
else
if
(value
is
long
) {
bytes
=
BitConverter.GetBytes((
long
)value);
type
=
SerializedType.Long;
}
else
if
(value
is
ulong
) {
bytes
=
BitConverter.GetBytes((
ulong
)value);
type
=
SerializedType.ULong;
}
else
if
(value
is
float
) {
bytes
=
BitConverter.GetBytes((
float
)value);
type
=
SerializedType.Float;
}
else
if
(value
is
double
) {
bytes
=
BitConverter.GetBytes((
double
)value);
type
=
SerializedType.Double;
}
else
{
//
Object
using
(MemoryStream ms
=
new
MemoryStream()) {
new
BinaryFormatter().Serialize(ms, value);
bytes
=
ms.ToArray();
type
=
SerializedType.Object;
if
(bytes.Length
>
compressionThreshold) {
bytes
=
Compress(bytes);
type
=
SerializedType.CompressedObject;
}
}
}
//
针对TT进行的修改
//
edited by: 2010-4-19
//
田真
return
MergedBuffer(bytes, type);
}
///
<summary>
///
解析缓存字节数组,解析出实际数据和数据类型
///
</summary>
///
<param name="buffer"></param>
///
<param name="type"></param>
///
<returns></returns>
private
static
byte
[] ParsedBuffer(
byte
[] buffer,
out
SerializedType type)
{
//
构造实际数据字节数组
byte
[] bytes
=
new
byte
[buffer.Length
-
1
];
//
提取类型
if
(
!
Enum.IsDefined(
typeof
(SerializedType), buffer[
0
]))
type
=
SerializedType.ByteArray;
else
type
=
(SerializedType)buffer[
0
];
//
提取数据
Buffer.BlockCopy(buffer,
1
, bytes,
0
, bytes.Length);
return
bytes;
}
///
<summary>
///
将序列化类型整合到存储的字节数组中(因为TT不支持Memcached的Type值存储)
///
</summary>
///
<param name="bytes">
字节数组
</param>
///
<param name="type">
字节数组的类型
</param>
///
<returns></returns>
private
static
byte
[] MergedBuffer(
byte
[] bytes, SerializedType type)
{
//
增加一个字节,用于存放字节数组的类型
byte
[] buffer
=
new
byte
[bytes.Length
+
1
];
//
将类型存储到第一个字节中
buffer[
0
]
=
(
byte
)type;
Buffer.BlockCopy(bytes,
0
, buffer,
1
, bytes.Length);
return
buffer;
}
///
<summary>
///
压缩指定的字节数组
///
</summary>
///
<param name="bytes"></param>
///
<returns></returns>
private
static
byte
[] Compress(
byte
[] bytes) {
using
(MemoryStream ms
=
new
MemoryStream()) {
using
(DeflateStream gzs
=
new
DeflateStream(ms, CompressionMode.Compress,
false
)) {
gzs.Write(bytes,
0
, bytes.Length);
}
ms.Close();
return
ms.ToArray();
}
}
///
<summary>
///
解压缩指定的字节数组
///
</summary>
///
<param name="bytes"></param>
///
<returns></returns>
private
static
byte
[] Decompress (
byte
[] bytes) {
using
(MemoryStream ms
=
new
MemoryStream(bytes,
false
)) {
using
(DeflateStream gzs
=
new
DeflateStream(ms, CompressionMode.Decompress,
false
)) {
using
(MemoryStream dest
=
new
MemoryStream()) {
byte
[] tmp
=
new
byte
[bytes.Length];
int
read;
while
((read
=
gzs.Read(tmp,
0
, tmp.Length))
!=
0
) {
dest.Write(tmp,
0
, read);
}
dest.Close();
return
dest.ToArray();
}
}
}
}
///
<summary>
///
反序列化数据
///
</summary>
///
<param name="bytes"></param>
///
<param name="type"></param>
///
<returns></returns>
public
static
object
Deserialize(
byte
[] bytes, SerializedType type) {
//
针对TT进行的修改
//
edited by: 2010-4-19
//
田真
bytes
=
ParsedBuffer(bytes,
out
type);
switch
(type) {
case
SerializedType.String:
return
Encoding.UTF8.GetString(bytes);
case
SerializedType.Datetime:
return
new
DateTime(BitConverter.ToInt64(bytes,
0
));
case
SerializedType.Bool:
return
bytes[
0
]
==
1
;
case
SerializedType.Byte:
return
bytes[
0
];
case
SerializedType.Short:
return
BitConverter.ToInt16(bytes,
0
);
case
SerializedType.UShort:
return
BitConverter.ToUInt16(bytes,
0
);
case
SerializedType.Int:
return
BitConverter.ToInt32(bytes,
0
);
case
SerializedType.UInt:
return
BitConverter.ToUInt32(bytes,
0
);
case
SerializedType.Long:
return
BitConverter.ToInt64(bytes,
0
);
case
SerializedType.ULong:
return
BitConverter.ToUInt64(bytes,
0
);
case
SerializedType.Float:
return
BitConverter.ToSingle(bytes,
0
);
case
SerializedType.Double:
return
BitConverter.ToDouble(bytes,
0
);
case
SerializedType.Object:
using
(MemoryStream ms
=
new
MemoryStream(bytes)) {
return
new
BinaryFormatter().Deserialize(ms);
}
case
SerializedType.CompressedByteArray:
return
Deserialize(Decompress(bytes), SerializedType.ByteArray);
case
SerializedType.CompressedString:
return
Deserialize(Decompress(bytes), SerializedType.String);
case
SerializedType.CompressedObject:
return
Deserialize(Decompress(bytes), SerializedType.Object);
case
SerializedType.ByteArray:
default
:
return
bytes;
}
}
}
}