c# - 如何将自定义数据传递给反序列化函数

标签 c# .net serialization deserialization

我正在做一些 C# IO 工作,我想从几个类中导入/导出数据。 找了一段时间,好像连载挺接近我想要的。

但是,有一个问题。我有一个 XML 文件,它描述了某个类的成员(我将其称为 ValueWithId),这些成员聚集在一个类中,我将调用 CollectionOfValuesWithId 用于这个问题。

ValueWithId 是一个包含名为 ShortNamestring 成员的类,它是唯一的。每个 ValueWithId 只有一个 ShortName,所有 ValueWithId 都有一个非空的 ShortNameCollectionOfValuesWithId 包含一个函数,用于查找具有给定 ShortNameValueWithId

序列化时,我不想希望在输出文件中存储ValueWithIdCollectionOfValuesWithId。相反,我只想将 ShortName 存储在文件中。 到目前为止,一切都很好。我只需要使用 SerializationInfo.AddValue("ValueWithId", MyValueWIthId.ShortName)

问题来自反序列化。一些谷歌搜索表明,要从文件中读取数据,可以这样做:

public SomeClassThatUsesValueWithId(SerializationInfo info, StreamingContext ctxt)
{
    string name = (string)info.GetValue("ValueWithId", typeof(string));
}

但是,该字符串不足以恢复 ValueWithId 实例。我还需要 CollectionOfValuesWithId。我想要这样的东西:

public SomeClassThatUsesValueWithId(SerializationInfo info,
   StreamingContext ctxt, CollectionOfValuesWithId extraParameter)

换句话说,我需要将额外的数据传递给反序列化构造函数。有谁知道这样做的任何方法或任何替代方法?

最佳答案

我想通了。执行此操作的重要类是 StreamingContext。 此类方便地具有名为 Context 的属性(可以在构造函数参数additional中设置。

来自 MSDN :

additional
Type: System.Object
Any additional information to be associated with the StreamingContext. This information is available to any object that implements ISerializable or any serialization surrogate. Most users do not need to set this parameter.

所以这里有一些关于如何做到这一点的示例代码(在 Mono 上测试过,但我认为它应该在 Windows 上工作):

using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

public class ValueWithId
{
    public string ShortName;
    public string ActualValue;

    public ValueWithId(string shortName, string actualValue)
    {
        ShortName = shortName;
        ActualValue = actualValue;
    }

    public override string ToString()
    {
        return ShortName + "->" + ActualValue;
    }
}

public class CollectionOfValuesWithId
{
    private IList<ValueWithId> Values = new List<ValueWithId>();

    public void AddValue(ValueWithId val)
    {
        Values.Add(val);
    }

    public ValueWithId GetValueFromId(string id)
    {
        foreach (var value in Values)
            if (value.ShortName == id)
                return value;
        return null;
    }
}

[Serializable]
public class SomeClassThatUsesValueWithId : ISerializable
{
    public ValueWithId Val;

    public SomeClassThatUsesValueWithId(ValueWithId val)
    {
        Val = val;
    }

    public SomeClassThatUsesValueWithId(SerializationInfo info, StreamingContext ctxt)
    {
        string valId = (string)info.GetString("Val");
        CollectionOfValuesWithId col = ctxt.Context as CollectionOfValuesWithId;
        if (col != null)
            Val = col.GetValueFromId(valId);
    }

    public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
    {
        //Store Val.ShortName instead of Val because we don't want to store the entire object
        info.AddValue("Val", Val.ShortName);
    }

    public override string ToString()
    {
        return "Content="+Val;
    }
}

class MainClass
{
    public static void Main(string[] args)
    {
        CollectionOfValuesWithId col = new CollectionOfValuesWithId();
        col.AddValue(new ValueWithId("foo", "bar"));

        SomeClassThatUsesValueWithId sc = new SomeClassThatUsesValueWithId(col.GetValueFromId("foo"));

        BinaryFormatter bf = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.File, col));

        using (var stream = new FileStream("foo", FileMode.Create))
        {
            bf.Serialize(stream, sc);
        }

        col.GetValueFromId("foo").ActualValue = "new value";

        using (var stream2 = new FileStream("foo", FileMode.Open))
        {
            Console.WriteLine(bf.Deserialize(stream2));
        }
    }
}

我得到的输出是:

Content=foo->new value

这正是我想要的。

关于c# - 如何将自定义数据传递给反序列化函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7664198/

相关文章:

java - 将 Vector<String> 序列化为 String

jquery - ASP.NET MVC + jQuery - 当我通过 jQuery $.post 表单时,如何保留 .NET 行结尾?

c# - 为什么 InProc session 模式不需要序列化

c# - 检查字符串日期转换为对象内部 DateTime 的空条件

c# - C#中如何实现malloc操作

.net - 只读 DataGridView 和 IEditableObject

c# - 使用 .NET 检索 Windows DHCP 服务器列表和每个 DHCP 服务器的范围信息

c# - 从磁盘上的 .cs 类文件获取属性

c# - 在 ODataController 中添加 WebAPI OData $orderby 选项

c# - 禁用调试输出