168 lines
6.6 KiB
C#
168 lines
6.6 KiB
C#
using System;
|
|
using System.IO;
|
|
using XP.Common.Localization;
|
|
using XP.Common.Logging.Interfaces;
|
|
using XP.Common.PdfViewer.Exceptions;
|
|
using XP.Common.PdfViewer.Interfaces;
|
|
using XP.Common.PdfViewer.ViewModels;
|
|
using XP.Common.PdfViewer.Views;
|
|
|
|
namespace XP.Common.PdfViewer.Implementations
|
|
{
|
|
/// <summary>
|
|
/// PDF 查看服务实现 | PDF viewer service implementation
|
|
/// 基于 Telerik RadPdfViewer 实现 | Based on Telerik RadPdfViewer
|
|
/// </summary>
|
|
public class PdfViewerService : IPdfViewerService
|
|
{
|
|
private readonly ILoggerService _logger;
|
|
private readonly IPdfPrintService _printService;
|
|
private bool _disposed;
|
|
|
|
public PdfViewerService(ILoggerService logger, IPdfPrintService printService)
|
|
{
|
|
_logger = logger?.ForModule<PdfViewerService>()
|
|
?? throw new ArgumentNullException(nameof(logger));
|
|
_printService = printService
|
|
?? throw new ArgumentNullException(nameof(printService));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 通过文件路径打开 PDF 阅读器窗口 | Open PDF viewer window by file path
|
|
/// </summary>
|
|
/// <param name="filePath">PDF 文件路径 | PDF file path</param>
|
|
/// <exception cref="FileNotFoundException">文件不存在 | File not found</exception>
|
|
/// <exception cref="PdfLoadException">PDF 格式无效 | Invalid PDF format</exception>
|
|
public void OpenViewer(string filePath)
|
|
{
|
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
|
|
|
// 1. 验证文件路径存在 | Validate file path exists
|
|
if (string.IsNullOrWhiteSpace(filePath))
|
|
{
|
|
throw new ArgumentNullException(nameof(filePath),
|
|
"文件路径不能为空 | File path cannot be null or empty");
|
|
}
|
|
|
|
if (!File.Exists(filePath))
|
|
{
|
|
_logger.Error(new FileNotFoundException(filePath),
|
|
"文件不存在 | File not found: {FilePath}", filePath);
|
|
throw new FileNotFoundException(
|
|
$"文件不存在 | File not found: {filePath}", filePath);
|
|
}
|
|
|
|
try
|
|
{
|
|
// 2. 创建 PdfViewerWindowViewModel | Create PdfViewerWindowViewModel
|
|
var viewModel = new PdfViewerWindowViewModel(filePath, _printService, _logger);
|
|
|
|
// 3. 创建 PdfViewerWindow 并设置 DataContext | Create PdfViewerWindow and set DataContext
|
|
var window = new PdfViewerWindow
|
|
{
|
|
DataContext = viewModel
|
|
};
|
|
|
|
// 4. 记录 Info 日志 | Log info
|
|
_logger.Info("打开 PDF 阅读器窗口 | Opening PDF viewer window: {FileName}",
|
|
Path.GetFileName(filePath));
|
|
|
|
// 5. 显示窗口(非模态)| Show window (non-modal)
|
|
window.Show();
|
|
}
|
|
catch (Exception ex) when (ex is not FileNotFoundException
|
|
and not ArgumentNullException
|
|
and not PdfLoadException)
|
|
{
|
|
_logger.Error(ex, "PDF 文件加载失败 | PDF file load failed: {FilePath}", filePath);
|
|
throw new PdfLoadException(
|
|
"PDF 文件加载失败 | PDF file load failed", filePath, ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 通过文件流打开 PDF 阅读器窗口 | Open PDF viewer window by stream
|
|
/// </summary>
|
|
/// <param name="stream">PDF 文件流 | PDF file stream</param>
|
|
/// <param name="title">窗口标题(可选)| Window title (optional)</param>
|
|
/// <exception cref="ArgumentNullException">流为 null | Stream is null</exception>
|
|
/// <exception cref="PdfLoadException">PDF 格式无效 | Invalid PDF format</exception>
|
|
public void OpenViewer(Stream stream, string? title = null)
|
|
{
|
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
|
|
|
// 1. 验证 stream 非 null | Validate stream is not null
|
|
ArgumentNullException.ThrowIfNull(stream, nameof(stream));
|
|
|
|
try
|
|
{
|
|
// 2. 创建 ViewModel | Create ViewModel
|
|
var viewModel = new PdfViewerWindowViewModel(stream, title, _printService, _logger);
|
|
|
|
// 3. 创建 PdfViewerWindow 并设置 DataContext | Create PdfViewerWindow and set DataContext
|
|
var window = new PdfViewerWindow
|
|
{
|
|
DataContext = viewModel
|
|
};
|
|
|
|
// 4. 记录 Info 日志 | Log info
|
|
var displayTitle = title ?? LocalizationHelper.Get("PdfViewer_Title");
|
|
_logger.Info("打开 PDF 阅读器窗口(流模式)| Opening PDF viewer window (stream mode): {Title}",
|
|
displayTitle);
|
|
|
|
// 5. 显示窗口(非模态)| Show window (non-modal)
|
|
window.Show();
|
|
}
|
|
catch (Exception ex) when (ex is not ArgumentNullException
|
|
and not PdfLoadException)
|
|
{
|
|
_logger.Error(ex, "PDF 文件加载失败(流模式)| PDF file load failed (stream mode)");
|
|
throw new PdfLoadException(
|
|
"PDF 文件加载失败 | PDF file load failed", null, ex);
|
|
}
|
|
}
|
|
|
|
#region IDisposable 模式 | IDisposable Pattern
|
|
|
|
/// <summary>
|
|
/// 释放资源 | Dispose resources
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
Dispose(disposing: true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 释放资源的核心方法 | Core dispose method
|
|
/// </summary>
|
|
/// <param name="disposing">是否由 Dispose() 调用 | Whether called by Dispose()</param>
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (_disposed)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (disposing)
|
|
{
|
|
// 释放托管资源 | Dispose managed resources
|
|
_logger.Info("PdfViewerService 已释放 | PdfViewerService disposed");
|
|
}
|
|
|
|
_disposed = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 终结器安全网 | Finalizer safety net
|
|
/// 确保未显式释放时仍能清理非托管资源 | Ensures unmanaged resources are cleaned up if not explicitly disposed
|
|
/// </summary>
|
|
~PdfViewerService()
|
|
{
|
|
Dispose(disposing: false);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|