Esempio n. 1
0
        /// <summary>
        /// Write an object to a target stream using a certain serialiser.
        /// All related objects along the object graph are properly stored using the <see cref="ISerialisationNotifier"/> contract.
        /// </summary>
        /// <param name="obj">The object.</param>
        /// <param name="target">The target stream.</param>
        /// <param name="serialiser">The serialiser.</param>
        /// <param name="autoClose">Optionally indicate if the stream should be automatically closed.</param>
        /// <param name="verbose">Optionally indicate where the log messages should written to (verbose = Info, otherwise Debug).</param>
        /// <returns>The number of bytes written (if exposed by the used target stream).</returns>
        public static long Write(object obj, Stream target, ISerialiser serialiser, bool autoClose = true, bool verbose = true)
        {
            if (obj == null)
            {
                throw new ArgumentNullException(nameof(obj));
            }
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }
            if (serialiser == null)
            {
                throw new ArgumentNullException(nameof(serialiser));
            }

            LoggingUtils.Log(verbose ? Level.Info : Level.Debug, $"Writing {obj.GetType().Name} {obj} of type {obj.GetType()} to target stream {target} using serialiser {serialiser}...", ClazzLogger);

            Stopwatch stopwatch      = Stopwatch.StartNew();
            long      beforePosition = target.Position;

            TraverseObjectGraph(obj, new HashSet <object>(), (p, f, o) => (o as ISerialisationNotifier)?.OnSerialising());
            serialiser.Write(obj, target);
            TraverseObjectGraph(obj, new HashSet <object>(), (p, f, o) => (o as ISerialisationNotifier)?.OnSerialised());

            target.Flush();

            long bytesWritten = target.Position - beforePosition;

            target.Close();

            LoggingUtils.Log(verbose ? Level.Info : Level.Debug, $"Done writing {obj.GetType().Name} {obj} to target stream {target} using serialiser {serialiser}, " +
                             $"wrote {(bytesWritten / 1024.0):#.#}kB, took {stopwatch.ElapsedMilliseconds}ms.", ClazzLogger);

            return(bytesWritten);
        }
Esempio n. 2
0
        /// <summary>
        /// Attempt to read and validate certain object from a binary file, return the original value if unsuccessful.
        /// </summary>
        /// <typeparam name="T">The object type.</typeparam>
        /// <param name="fileName">The file name.</param>
        /// <param name="originalValue">The original value.</param>
        /// <param name="verbose">Optionally indicate where the log messages should written to (verbose = Info, otherwise Debug).</param>
        /// <param name="validationFunction">The optional validation function to validate the read object with (if false, the original value is returned).</param>
        /// <returns>The read (i.e. existing) if successfully read and validated, otherwise the original value.</returns>
        public static T ReadBinaryFileIfExists <T>(string fileName, T originalValue, bool verbose = true, Func <T, bool> validationFunction = null)
        {
            try
            {
                T existing = ReadBinaryFile <T>(fileName, verbose);

                if (validationFunction == null || validationFunction.Invoke(existing))
                {
                    LoggingUtils.Log(verbose ? Level.Info :  Level.Debug, $"Read and validation of type {typeof(T)} successful, returning existing value.", ClazzLogger);

                    return(existing);
                }

                LoggingUtils.Log(verbose ? Level.Info : Level.Debug, $"Read of type {typeof(T)} successful, validation failed, returning default value.", ClazzLogger);
            }
            catch (Exception e)
            {
                LoggingUtils.Log(verbose ? Level.Info : Level.Debug, $"Read of type {typeof(T)} failed with \"{e.GetType()}: {e.Message}\", returning default value.", ClazzLogger);
            }

            return(originalValue);
        }
Esempio n. 3
0
        /// <summary>
        /// Read an object from a target stream using a certain serialiser.
        /// All related objects along the object graph are properly restored using the <see cref="ISerialisationNotifier"/> contract.
        /// </summary>
        /// <param name="target">The target stream.</param>
        /// <param name="serialiser">The serialiser.</param>
        /// <param name="verbose">Optionally indicate where the log messages should written to (verbose = Info, otherwise Debug).</param>
        /// <returns>The read object of the requested type.</returns>
        public static T Read <T>(Stream target, ISerialiser serialiser, bool verbose = true)
        {
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }
            if (serialiser == null)
            {
                throw new ArgumentNullException(nameof(serialiser));
            }

            LoggingUtils.Log(verbose ? Level.Info : Level.Debug, $"Reading {typeof(T).Name} from target stream {target} using serialiser {serialiser}...", ClazzLogger);

            Stopwatch stopwatch      = Stopwatch.StartNew();
            long      beforePosition = target.Position;

            object read = serialiser.Read(target);

            if (!(read is T))
            {
                throw new SerializationException($"Unable to read {typeof(T).Name} from target {target} using serialiser {serialiser}, read object {read} was not of the requested type.");
            }

            TraverseObjectGraph(read, new HashSet <object>(), (parent, field, obj) =>
            {
                // automatically restore all logger instances
                if (field.FieldType == typeof(ILog))
                {
                    field.SetValue(parent, LogManager.GetLogger(Assembly.GetCallingAssembly(), parent.GetType().Namespace + "." + parent.GetType().Name));
                }

                (obj as ISerialisationNotifier)?.OnDeserialised();
            });

            LoggingUtils.Log(verbose ? Level.Info : Level.Debug, $"Done reading {typeof(T).Name} {read} from target stream {target} using serialiser {serialiser}, " +
                             $"read {((target.Position - beforePosition) / 1024.0):#.#}kB, took {stopwatch.ElapsedMilliseconds}ms.", ClazzLogger);

            return((T)read);
        }