在 C# 中保存字典 <int, object> - 序列化?
Saving a Dictionary<int, object> in C# - Serialization?
我有一个 c# 字典
private Dictionary<int, UserSessionInfo> userSessionLookupTable = new Dictionary<int, UserSessionInfo>();
现在我已经创建了一个字典对象
this.userSessionLookupTable.Add(userSessionInfoLogin.SessionId, userSessionInfoLogin);
现在我想要一个通用方法来将字典序列化和反序列化为字节数组。
喜欢
public static void Serialize(Dictionary<int, object> dictionary, Stream stream)
{
//Code here
}
和
public static static Dictionary<int, object> Deserialize(Stream stream)
{
//Code here
}
谁能帮我解决这个问题?
除非您想构建自己的完全自定义序列化程序,否则您需要使用内置 serialization structure
字典和所有引用的类型必须实现内置的序列化结构,这需要 类 用正确的属性装饰,即 [Serializable]
, or [DataContact]
,并且由于对象无法实现它,所以你可以'不能直接序列化,需要改成可序列化的类型
For Binary Serialization
有关详细信息,请查看 BinaryFormatter。
这是一个可能的解决方案:
public void Serialize(Dictionary<int, UserSessionInfo> dictionary, Stream stream)
{
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(dictionary.Count);
foreach (var obj in dictionary)
{
writer.Write(obj.Key);
writer.Write(obj.Value);
}
writer.Flush();
}
public Dictionary<int, UserSessionInfo> Deserialize(Stream stream)
{
BinaryReader reader = new BinaryReader(stream);
int count = reader.ReadInt32();
var dictionary = new Dictionary<int, UserSessionInfo>(count);
for (int n = 0; n < count; n++)
{
var key = reader.ReadInt32();
var value = reader.ReadString();
dictionary.Add(key, value);
}
return dictionary;
}
但您仍然需要 UserSessionInfo ToString() 转换器;
For XML Serialization
创建示例class 会话
public class Session
{
[XmlAttribute]
public int SessionID;
[XmlAttribute]
public UserSessionInfo SessionInfo;
}
然后你可以创建XmlSerializer如果你想把它序列化为XML
XmlSerializer serializer = new XmlSerializer(
typeof(Session[]),
new XmlRootAttribute() { ElementName = "sessions" }
);
现在您可以序列化或反序列化了。
序列化:
serializer.Serialize(
stream,
dict.Select(kv => new Session(){SessionID = kv.Key, SessionInfo = kv.Info}).ToArray()
);
反序列化:
var deserialized = (
(Session[])serializer.Deserialize(stream)
).ToDictionary(i => i.id, i => i.info);
但是您需要在 UserSessionInfo 中使用 ToString() 方法才能将其存储在 XML.
而 XML 可能如下所示:
<sessions>
<session id='int_goes_here' value='string_goes_here'/>
</sessions>
希望这对您有所帮助。
您可以为此目的使用 MemoryStream
,除非您不想创建文件。但是对于序列化方法,如果您不想 return 一个值,您应该将 stream
参数标记为 [Out]
.
public static void Serialize(Dictionary<int, object> dictionary, [Out] Stream stream)
{
stream = new MemoryStream();
new BinaryFormatter().Serialize(stream, dictionary);
}
public static Dictionary<int, object> Deserialize(Stream stream)
{
return (Dictionary<int, object>)new BinaryFormatter().Deserialize(stream);
}
这将执行二进制序列化。
编辑:
要将其作为字节数组获取,您只需将流 returned 从 Serialize()
方法转换为 MemoryStream
,然后对其调用 .ToArray()
.
这是一个例子:
MemoryStream outputStream;
Serialize(your dictionary here, outputStream);
byte[] bytes = outputStream.ToArray();
试试这个....
public static void Serialize<Object>(Object dictionary, Stream stream)
{
try // try to serialize the collection to a file
{
using (stream)
{
// create BinaryFormatter
BinaryFormatter bin = new BinaryFormatter();
// serialize the collection (EmployeeList1) to file (stream)
bin.Serialize(stream, dictionary);
}
}
catch (IOException)
{
}
}
public static Object Deserialize<Object>(Stream stream) where Object : new()
{
Object ret = CreateInstance<Object>();
try
{
using (stream)
{
// create BinaryFormatter
BinaryFormatter bin = new BinaryFormatter();
// deserialize the collection (Employee) from file (stream)
ret = (Object)bin.Deserialize(stream);
}
}
catch (IOException)
{
}
return ret;
}
// function to create instance of T
public static Object CreateInstance<Object>() where Object : new()
{
return (Object)Activator.CreateInstance(typeof(Object));
}
用法...
Serialize(userSessionLookupTable, File.Open("data.bin", FileMode.Create));
Dictionary<int, UserSessionInfo> deserializeObject = Deserialize<Dictionary<int, UserSessionInfo>>(File.Open("data.bin", FileMode.Open));
我在上面的代码中使用了 'Object' 来满足您的要求,但我个人会使用 'T',它通常表示 C# 中的通用对象
也许回答有点晚,但根据我的经验,这是一个实用且更通用的答案:如果您想要快速简单的东西或者对数据大小的需求不多,请使用简单的 JSON 序列化或表现。如果您还想要 space 高效、快速和跨平台的东西,请使用 Google Protocol Buffers。
JSON
string output = JsonConvert.SerializeObject(myObject);
var copyOfMyObject = JsonConvert.DeserializeObject<MyObject>(output);
有很多方法可以control the serialisation and use streams and so on。
Json.Net also supports dictionaries too.
Protobuf
在c#中有两种使用protobuf的方式:Using .proto message definitions and generate code or reflection based approach using your class definitions and attributes。这取决于您的项目,但我个人更喜欢消息定义。
请注意,您可能必须在序列化和反序列化之前和之后进行自己的修改才能与 Dictionary
一起使用。
基于消息定义:使用 proto3
.proto 文件:
message Person {
int32 id = 1;
string name = 2;
}
使用Google Protobuf生成代码:
protoc --csharp_out=$DST_DIR $SRC_DIR/person.proto
Serialise / deserialise using generated classes:
Person john = ...;
john.WriteTo(stream);
var copyOfJohn = Person.Parser.ParseFrom(stream);
另外,一个简短的说明让您知道 proto3 is the capability of using JSON 可能有一个鲜为人知的功能。
基于反射:Protobuf-net
这是一个简单的例子(从protobuf-net page复制)
[ProtoContract]
class Person {
[ProtoMember(1)]
public int Id {get;set;}
[ProtoMember(2)]
public string Name {get;set;}
}
Serializer.Serialize(file, person);
newPerson = Serializer.Deserialize<Person>(file);
二进制、文本、流,天哪!
抱歉,我有点忽略了关于 'Binary' 序列化的问题(并且不是一个特定的 BinaryFormatter
问题),因为有很多方法可以使用流来处理流入和流出的数据出一个过程。 C# 流、reader 和 writer 以及其他 System.IO APIs 都有很好的文档记录。
我有一个 c# 字典
private Dictionary<int, UserSessionInfo> userSessionLookupTable = new Dictionary<int, UserSessionInfo>();
现在我已经创建了一个字典对象
this.userSessionLookupTable.Add(userSessionInfoLogin.SessionId, userSessionInfoLogin);
现在我想要一个通用方法来将字典序列化和反序列化为字节数组。 喜欢
public static void Serialize(Dictionary<int, object> dictionary, Stream stream)
{
//Code here
}
和
public static static Dictionary<int, object> Deserialize(Stream stream)
{
//Code here
}
谁能帮我解决这个问题?
除非您想构建自己的完全自定义序列化程序,否则您需要使用内置 serialization structure
字典和所有引用的类型必须实现内置的序列化结构,这需要 类 用正确的属性装饰,即 [Serializable]
, or [DataContact]
,并且由于对象无法实现它,所以你可以'不能直接序列化,需要改成可序列化的类型
For Binary Serialization
有关详细信息,请查看 BinaryFormatter。
这是一个可能的解决方案:
public void Serialize(Dictionary<int, UserSessionInfo> dictionary, Stream stream)
{
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(dictionary.Count);
foreach (var obj in dictionary)
{
writer.Write(obj.Key);
writer.Write(obj.Value);
}
writer.Flush();
}
public Dictionary<int, UserSessionInfo> Deserialize(Stream stream)
{
BinaryReader reader = new BinaryReader(stream);
int count = reader.ReadInt32();
var dictionary = new Dictionary<int, UserSessionInfo>(count);
for (int n = 0; n < count; n++)
{
var key = reader.ReadInt32();
var value = reader.ReadString();
dictionary.Add(key, value);
}
return dictionary;
}
但您仍然需要 UserSessionInfo ToString() 转换器;
For XML Serialization
创建示例class 会话
public class Session
{
[XmlAttribute]
public int SessionID;
[XmlAttribute]
public UserSessionInfo SessionInfo;
}
然后你可以创建XmlSerializer如果你想把它序列化为XML
XmlSerializer serializer = new XmlSerializer(
typeof(Session[]),
new XmlRootAttribute() { ElementName = "sessions" }
);
现在您可以序列化或反序列化了。
序列化:
serializer.Serialize(
stream,
dict.Select(kv => new Session(){SessionID = kv.Key, SessionInfo = kv.Info}).ToArray()
);
反序列化:
var deserialized = (
(Session[])serializer.Deserialize(stream)
).ToDictionary(i => i.id, i => i.info);
但是您需要在 UserSessionInfo 中使用 ToString() 方法才能将其存储在 XML.
而 XML 可能如下所示:
<sessions>
<session id='int_goes_here' value='string_goes_here'/>
</sessions>
希望这对您有所帮助。
您可以为此目的使用 MemoryStream
,除非您不想创建文件。但是对于序列化方法,如果您不想 return 一个值,您应该将 stream
参数标记为 [Out]
.
public static void Serialize(Dictionary<int, object> dictionary, [Out] Stream stream)
{
stream = new MemoryStream();
new BinaryFormatter().Serialize(stream, dictionary);
}
public static Dictionary<int, object> Deserialize(Stream stream)
{
return (Dictionary<int, object>)new BinaryFormatter().Deserialize(stream);
}
这将执行二进制序列化。
编辑:
要将其作为字节数组获取,您只需将流 returned 从 Serialize()
方法转换为 MemoryStream
,然后对其调用 .ToArray()
.
这是一个例子:
MemoryStream outputStream;
Serialize(your dictionary here, outputStream);
byte[] bytes = outputStream.ToArray();
试试这个....
public static void Serialize<Object>(Object dictionary, Stream stream)
{
try // try to serialize the collection to a file
{
using (stream)
{
// create BinaryFormatter
BinaryFormatter bin = new BinaryFormatter();
// serialize the collection (EmployeeList1) to file (stream)
bin.Serialize(stream, dictionary);
}
}
catch (IOException)
{
}
}
public static Object Deserialize<Object>(Stream stream) where Object : new()
{
Object ret = CreateInstance<Object>();
try
{
using (stream)
{
// create BinaryFormatter
BinaryFormatter bin = new BinaryFormatter();
// deserialize the collection (Employee) from file (stream)
ret = (Object)bin.Deserialize(stream);
}
}
catch (IOException)
{
}
return ret;
}
// function to create instance of T
public static Object CreateInstance<Object>() where Object : new()
{
return (Object)Activator.CreateInstance(typeof(Object));
}
用法...
Serialize(userSessionLookupTable, File.Open("data.bin", FileMode.Create));
Dictionary<int, UserSessionInfo> deserializeObject = Deserialize<Dictionary<int, UserSessionInfo>>(File.Open("data.bin", FileMode.Open));
我在上面的代码中使用了 'Object' 来满足您的要求,但我个人会使用 'T',它通常表示 C# 中的通用对象
也许回答有点晚,但根据我的经验,这是一个实用且更通用的答案:如果您想要快速简单的东西或者对数据大小的需求不多,请使用简单的 JSON 序列化或表现。如果您还想要 space 高效、快速和跨平台的东西,请使用 Google Protocol Buffers。
JSON
string output = JsonConvert.SerializeObject(myObject);
var copyOfMyObject = JsonConvert.DeserializeObject<MyObject>(output);
有很多方法可以control the serialisation and use streams and so on。
Json.Net also supports dictionaries too.
Protobuf
在c#中有两种使用protobuf的方式:Using .proto message definitions and generate code or reflection based approach using your class definitions and attributes。这取决于您的项目,但我个人更喜欢消息定义。
请注意,您可能必须在序列化和反序列化之前和之后进行自己的修改才能与 Dictionary
一起使用。
基于消息定义:使用 proto3
.proto 文件:
message Person {
int32 id = 1;
string name = 2;
}
使用Google Protobuf生成代码:
protoc --csharp_out=$DST_DIR $SRC_DIR/person.proto
Serialise / deserialise using generated classes:
Person john = ...;
john.WriteTo(stream);
var copyOfJohn = Person.Parser.ParseFrom(stream);
另外,一个简短的说明让您知道 proto3 is the capability of using JSON 可能有一个鲜为人知的功能。
基于反射:Protobuf-net
这是一个简单的例子(从protobuf-net page复制)
[ProtoContract]
class Person {
[ProtoMember(1)]
public int Id {get;set;}
[ProtoMember(2)]
public string Name {get;set;}
}
Serializer.Serialize(file, person);
newPerson = Serializer.Deserialize<Person>(file);
二进制、文本、流,天哪!
抱歉,我有点忽略了关于 'Binary' 序列化的问题(并且不是一个特定的 BinaryFormatter
问题),因为有很多方法可以使用流来处理流入和流出的数据出一个过程。 C# 流、reader 和 writer 以及其他 System.IO APIs 都有很好的文档记录。