C# 如何序列化System.Diagnostics.Stopwatch

C# 如何序列化System.Diagnostics.Stopwatch,c#,C#,我有一个标记为[Serializable]的类,其中包含System.Diagnostics.Stopwatch成员;但是,由于System.Diagnostics.Stopwatch的原因,我无法使用BinaryFormatter序列化该类。是否有方法标记System.Diagnostics.Stopwatch或使其可序列化?您可以使用标记标记Stopwatch成员。这样,它将被从序列化过程中排除,并且包含的类将被成功序列化 [NonSerialized] public Stopwatch w

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

您可以使用标记标记Stopwatch成员。这样,它将被从序列化过程中排除,并且包含的类将被成功序列化

[NonSerialized]
public Stopwatch watch;

你可以在秒表上画上记号。这样,它将被从序列化过程中排除,并且包含的类将被成功序列化

[NonSerialized]
public Stopwatch watch;

您不能使Stopwatch可序列化,但如果您确实希望序列化它(不管您可能希望这样做),您的包含类可以实现

在这种情况下,必须提供自定义逻辑来序列化和反序列化秒表


但是,我无法理解如何以有意义的方式序列化正在运行的秒表。

您不能使秒表可序列化,但是如果您确实希望序列化它(无论您希望如何),您的包含类可以实现

在这种情况下,必须提供自定义逻辑来序列化和反序列化秒表


但是,我无法理解如何以有意义的方式序列化正在运行的秒表。

尝试为秒表创建一个可序列化的包装器对象

public class SerializableStopwatch : Stopwatch, ISerializable
{
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("Ticks", ElapsedTicks);
        // .. etc ..
    }
}

..

尝试为秒表创建可序列化的包装器对象

public class SerializableStopwatch : Stopwatch, ISerializable
{
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("Ticks", ElapsedTicks);
        // .. etc ..
    }
}

..

您可以为秒表创建序列化代理项和代理项选择器

请注意,秒表类可能具有特定于机器的状态,即滴答频率等。因此,在序列化时,请检查序列化上下文,确保序列化不用于跨计算机使用(如果您打算复制所有值),或者仅使用计时数据创建一个全新的实例

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();
    }
}

您可以为秒表创建SerializationSurrogate和SurrogateSelector

请注意,秒表类可能具有特定于机器的状态,即滴答频率等。因此,在序列化时,请检查序列化上下文,确保序列化不用于跨计算机使用(如果您打算复制所有值),或者仅使用计时数据创建一个全新的实例

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();
    }
}

可能使秒表成为私有成员,然后应用非序列化属性。可能使秒表成为私有成员,然后应用非序列化属性。请记住,这仅适用于字段/成员变量。它不适用于属性。请记住,它只适用于字段/成员变量。这在一处房产上不起作用。我很抱歉说不清楚。我确实想序列化秒表,这是我的问题,我不能序列化它。你可能会认为有一种方法可以做到这一点。谢谢大家的快速回复!在我序列化时,秒表停止了。我现在想,我可能只是序列化一些值,而不是秒表本身。当您需要再次对其进行反序列化时,就会出现问题,因为无法创建已用时间的秒表实例。换句话说:这是不可能的(除非您使用反射来修改秒表的私有字段,但我不建议这样做)。我确实想序列化秒表,这是我的问题,我不能序列化它。你可能会认为有一种方法可以做到这一点。谢谢大家的快速回复!在我序列化时,秒表停止了。我现在想,我可能只是序列化一些值,而不是秒表本身。当您需要再次对其进行反序列化时,就会出现问题,因为无法创建已用时间的秒表实例。换句话说:这是不可能的(除非您使用反射来修改秒表的私有字段,但我不建议这样做)。谢谢大家的帮助。我使用了MaLio的解决方案,因为我将序列化和持久化的附加数据将在同一台机器上反序列化和处理。我正在编写的类包含由我正在编写的应用程序驱动程序创建的统计数据。感谢大家的帮助。我使用了MaLio的解决方案,因为我将序列化和持久化的附加数据将在同一台机器上反序列化和处理。我正在编写的类包含由我正在编写的应用程序驱动程序创建的统计数据。