c# - 如何序列化System.Diagnostics.Stopwatch

标签 c#

我有一个标记为[Serializable]的类,其中包含System.Diagnostics.Stopwatch成员。但是由于System.Diagnostics.Stopwatch,我无法使用BinaryFormatter来序列化该类。有没有办法标记或使System.Diagnostics.Stopwatch可序列化?

最佳答案

您可以为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();
    }
}

关于c# - 如何序列化System.Diagnostics.Stopwatch,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1866351/

相关文章:

c# - 在 WPF MVVM 中处理大量命令

c# - 如何使用公共(public)列在 C# 中对 2 个或多个数据表进行完全外部联接

c# - 在登录后保护整个网站,即 "Authorize"所有 Controller 中的所有操作

c# - 在 WPF 应用程序中更改默认打印机

c# - 用 lambda 表达式替换字符串作为属性名称

c# - Linq to Sql : How to quickly clear a table

c# - 执行 PowerPoint 自动化时如何避免 RPC_E_CALL_REJECTED 异常?

c# - C# 加密库如何处理小于加密算法所需 key 大小的 key ?

c# - C# Linq 语法-vs- VB Linq 语法比较

javascript - 没有提交的 ASP.NET MVC ActionResult POST