我有一个标记为[Serializable]的类,其中包含一个System.Diagnostics.Stopwatch成员;但是由于System.Diagnostics.Stopwatch,我无法使用BinaryFormatter序列化该类。有没有办法标记或使System.Diagnostics.Stopwatch可序列化?
答案 0 :(得分:6)
您可以使用NonSerializedAttribute标记秒表成员。这样它将从序列化过程中排除,并且包含类将被成功序列化。
[NonSerialized]
public Stopwatch watch;
答案 1 :(得分:2)
尝试为秒表创建可序列化的包装器对象。
public class SerializableStopwatch : Stopwatch, ISerializable
{
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Ticks", ElapsedTicks);
// .. etc ..
}
}
答案 2 :(得分:2)
您可以为StopWatch创建SerializationSurrogate和SurrogateSelector。
请注意,StopWatch类可能具有机器特定状态,即刻度频率等。因此,在序列化时,请检查序列化上下文,序列化不是用于跨机器使用(如果您打算复制所有值),或者创建仅包含时序数据的完全新实例。
namespace MaLio.StopWatch {
class Program {
static void Main(string[] args) {
Container container = new Container();
Container copy = null;
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter =
new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
// may be a formatter created elsewhere
if (formatter.SurrogateSelector == null) {
formatter.SurrogateSelector = new StopWatchSelector();
}
else {
formatter.SurrogateSelector.ChainSelector(new StopWatchSelector());
}
using (System.IO.MemoryStream stream = new System.IO.MemoryStream()) {
formatter.Serialize(stream, container);
stream.Flush();
stream.Position = 0;
copy = formatter.Deserialize(stream) as Container;
}
System.Diagnostics.Debug.WriteLine(
"Reference Equals: " + (object.ReferenceEquals(container, copy)).ToString());
System.Console.ReadKey();
}
}
public class StopWatchSelector : System.Runtime.Serialization.SurrogateSelector {
private StopWatchSurrogate _Surrogate;
public StopWatchSelector() {
_Surrogate = new StopWatchSurrogate();
}
public override System.Runtime.Serialization.ISerializationSurrogate GetSurrogate(
System.Type type,
System.Runtime.Serialization.StreamingContext context,
out System.Runtime.Serialization.ISurrogateSelector selector) {
System.Runtime.Serialization.ISerializationSurrogate surrogate;
surrogate = base.GetSurrogate(type, context, out selector);
if (surrogate == null) {
if (type == typeof(System.Diagnostics.Stopwatch)) {
surrogate = _Surrogate;
}
}
return surrogate;
}
}
public class StopWatchSurrogate : System.Runtime.Serialization.ISerializationSurrogate {
private const string NULL_INDICATOR_STRING = @"__StopWatchNull";
// the invalid contexts as an example
private const System.Runtime.Serialization.StreamingContextStates INVALID_CONTEXTS =
System.Runtime.Serialization.StreamingContextStates.CrossMachine |
System.Runtime.Serialization.StreamingContextStates.Remoting;
public void GetObjectData(
object obj,
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) {
System.Diagnostics.Stopwatch stopWatch = obj as System.Diagnostics.Stopwatch;
if (stopWatch == null) {
info.AddValue(NULL_INDICATOR_STRING, true);
}
else {
info.AddValue(NULL_INDICATOR_STRING, false);
// add other values looked up via reflection
}
}
public object SetObjectData (
object obj,
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context,
System.Runtime.Serialization.ISurrogateSelector selector) {
System.Diagnostics.Stopwatch stopWatch = null;
bool isNull = info.GetBoolean(NULL_INDICATOR_STRING);
if (!isNull) {
stopWatch = obj as System.Diagnostics.Stopwatch;
// read other values and set via reflection
}
return stopWatch;
}
private void CheckContext(System.Runtime.Serialization.StreamingContext context) {
if ((context.State & INVALID_CONTEXTS) != 0) {
throw new System.NotSupportedException();
}
}
}
[System.Serializable]
public class Container {
private System.Diagnostics.Stopwatch _Watch = new System.Diagnostics.Stopwatch();
}
}
答案 3 :(得分:0)
你不能使秒表可序列化,但如果真的希望序列化它(不过你可能想这样做),你的包含类可以实现ISerializable。
在这种情况下,您必须提供用于序列化和反序列化秒表的自定义逻辑。
然而,如何设法以有意义的方式序列化正在运行的秒表是不可能的。