lui*_*bal 4 .net c# serialization deserialization
我正在做一些C#IO工作,我想从几个类导入/导出数据.在寻找一段时间后,似乎序列化非常接近我想要的.
但是,有一个问题.我有一个XML文件,它描述了某个类的成员(我将其称之为ValueWithId),它们聚合在一个类中,我将CollectionOfValuesWithId为此问题调用它.
ValueWithId是一个包含string被调用成员的类ShortName,它是唯一的.只有一个ShortName每ValueWithId和所有ValueWithId具有非空ShortName.CollectionOfValuesWithId包含一个ValueWithId用给定的函数来查找ShortName.
序列化的时候,我做不想要存储ValueWithId也不CollectionOfValuesWithId输出文件.相反,我只想将其存储ShortName在文件中.到现在为止还挺好.我只需要使用SerializationInfo.AddValue("ValueWithId", MyValueWIthId.ShortName).
问题出在反序列化上.一些谷歌搜索表明,要从文件中读取数据,可以这样做:
public SomeClassThatUsesValueWithId(SerializationInfo info, StreamingContext ctxt)
{
string name = (string)info.GetValue("ValueWithId", typeof(string));
}
Run Code Online (Sandbox Code Playgroud)
但是,字符串不足以恢复ValueWithId实例.我也需要CollectionOfValuesWithId.我想要这样的东西:
public SomeClassThatUsesValueWithId(SerializationInfo info,
StreamingContext ctxt, CollectionOfValuesWithId extraParameter)
Run Code Online (Sandbox Code Playgroud)
换句话说,我需要将额外的数据传递给反序列化构造函数.有没有人知道做这个或任何替代方案的方法?
我想到了.这样做的重要方法是StreamingContext.这个类方便地有一个名为的属性Context(可以在构造函数参数中设置)additional.
来自MSDN:
附加
类型:System.Object
与StreamingContext关联的任何其他信息.此信息可用于实现ISerializable或任何序列化代理的任何对象.大多数用户不需要设置此参数.
所以这里有一些关于如何执行此操作的示例代码(在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));
}
}
}
Run Code Online (Sandbox Code Playgroud)
我得到的输出是:
Content=foo->new value
Run Code Online (Sandbox Code Playgroud)
这正是我想要的.
| 归档时间: |
|
| 查看次数: |
3863 次 |
| 最近记录: |