在C#中保存字典<int,object =“”> - 序列化?

时间:2016-03-31 12:30:09

标签: c# dictionary serialization binary-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
}

任何人都可以帮我吗?

5 个答案:

答案 0 :(得分:3)

试试这个......

    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#中的通用对象

答案 1 :(得分:1)

  

二进制序列化

有关详细信息,请查看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()转换器;

  

XML 序列化

创建示例类Session

public class Session
{
    [XmlAttribute]
    public int SessionID;
    [XmlAttribute]
    public UserSessionInfo SessionInfo;
}

如果要将其序列化为 XML

,则可以创建 XmlSerializer
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>

希望这有帮助。

答案 2 :(得分:1)

除非您不想创建文件,否则可以使用MemoryStream。但是对于序列化方法,如果您不想返回值,则应该将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);
}

这将执行二进制序列化。

修改

要将其作为字节数组获取,您只需将从Serialize()方法返回的流转换为MemoryStream,然后在其上调用.ToArray()

这是一个例子:

MemoryStream outputStream;
Serialize(your dictionary here, outputStream);
byte[] bytes = outputStream.ToArray();

答案 3 :(得分:1)

回答可能有点迟,但根据我的经验,这是一个实用且更通用的答案:如果您想快速简便地使用简单的JSON序列化,或者对数据大小或性能的要求不高,请使用简单的JSON序列化。如果您想要高效,快速和跨平台的东西,请使用Google Protocol Buffers。

JSON

<div className="intent" id="intent1" style={{border:'1px solid #eee'}}>
                <div className="form-group row">
                    <label htmlFor="intent" className="col-sm-1 col-form-label">Intent</label>
                    <div className="col-sm-5">
                    <input type="text" className="form-control" name="indent[]" id="intent1" placeholder="Enter intent"/>
                    </div>
                </div>
            </div>

有很多方法可以control the serialisation and use streams and so on

Json.Net also supports dictionaries too

的Protobuf

在c#中有两种使用protobuf的方法:Using .proto message definitions and generate codereflection based approach using your class definitions and attributes。这取决于您的项目,但我个人更喜欢消息定义。

请注意,您可能必须在序列化和反序列化之前和之后进行自己的调整以与string output = JsonConvert.SerializeObject(myObject); var copyOfMyObject = JsonConvert.DeserializeObject<MyObject>(output); 一起使用。

基于消息定义:使用proto3

.proto文件:

Dictionary

使用Google Protobuf生成代码:

message Person {
  int32 id = 1;
  string name = 2;
}

Serialise / deserialise using generated classes

protoc --csharp_out=$DST_DIR $SRC_DIR/person.proto

另外,请您快速了解proto3 is the capability of using JSON可能鲜为人知的功能。

基于反射:Protobuf-net

以下是一个快速示例(从protobuf-net page复制)

Person john = ...;
john.WriteTo(stream);
var copyOfJohn = Person.Parser.ParseFrom(stream);

二进制文本,文本,流,哦,我的!

道歉,我有点忽略了关于'二进制'序列化的问题(而不是特定的[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); 问题),因为有很多方法可以使用流来处理流入和流出流程的数据。 C#stream,reader和writer以及其他System.IO APIs都有很好的文档记录。

答案 4 :(得分:0)

除非您想构建自己的完全自定义序列化程序,否则您需要使用内置的serialization structure

字典和所有引用的类型必须实现内置的序列化结构,该结构要求使用正确的属性(即[Serializable][DataContact]来装饰类,并且对象无法实现它您无法直接将其序列化,您需要将其更改为可序列化类型