/// <summary>
        /// Creates a <see cref="FilePrinter" /> for the file represented by the specified <see cref="FileInfo" />.
        /// </summary>
        /// <param name="file">The <see cref="FileInfo" />.</param>
        /// <returns>A <see cref="FilePrinter" /> for the specified file.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="file" /> is null.</exception>
        public static FilePrinter Create(FileInfo file)
        {
            if (file == null)
            {
                throw new ArgumentNullException(nameof(file));
            }

            LogDebug($"Creating file printer for {file.FullName}");
            string fileExtension = file.Extension.ToUpperInvariant().Trim('.');

            try
            {
                FilePrinter filePrinter = ObjectFactory.Create <FilePrinter>(fileExtension, file);
                LogTrace($"Created {filePrinter.GetType().Name}.");
                return(filePrinter);
            }
            catch (InvalidOperationException)
            {
                LogTrace($"No match for file type {fileExtension}. Created generic file printer.");
                return(new GenericFilePrinter(file));
            }
        }
        /// <summary>
        /// Prints the specified file to the specified <see cref="PrintQueue" />.
        /// </summary>
        /// <param name="file">The file to print.</param>
        /// <param name="printQueue">The <see cref="PrintQueue" /> to print the file to.</param>
        /// <param name="fileId">The <see cref="Guid" /> to use for the unique file name.</param>
        /// <returns>A <see cref="PrintingEngineResult" /> object representing the outcome of the print operation.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="file" /> is null.
        /// <para>or</para>
        /// <paramref name="printQueue" /> is null.
        /// </exception>
        public PrintingEngineResult Print(FileInfo file, PrintQueue printQueue, Guid fileId)
        {
            if (file == null)
            {
                throw new ArgumentNullException(nameof(file));
            }

            if (printQueue == null)
            {
                throw new ArgumentNullException(nameof(printQueue));
            }

            UniqueFile uniqueFile = null;

            try
            {
                LogStatus($"Printing {file.Name} to {printQueue.FullName}");

                // Create a uniquely named file to identify the print job
                uniqueFile = UniqueFile.Create(file, fileId);

                // Create the file printer
                FilePrinter filePrinter = FilePrinterFactory.Create(uniqueFile);
                filePrinter.StatusChanged += (s, e) => StatusChanged?.Invoke(s, e);

                // Print the file and return the result
                DateTimeOffset  jobStart    = DateTimeOffset.Now;
                FilePrintResult printResult = filePrinter.Print(printQueue, PrintOptions);
                DateTimeOffset  jobEnd      = DateTimeOffset.Now;

                LogStatus($"Finished printing {file.Name}");
                return(new PrintingEngineResult(uniqueFile, printResult, jobStart, jobEnd));
            }
            finally
            {
                Task.Factory.StartNew(() => DeleteTemporaryFile(uniqueFile));
            }
        }