107 lines
3.9 KiB
C#
107 lines
3.9 KiB
C#
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
|
|||
|
|
namespace SHH.CameraSdk;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 视频 SDK 统一异常类 (V3.3.1 修复版)
|
|||
|
|
/// 核心职责:
|
|||
|
|
/// <para>1. 封装标准化错误码、厂商原始错误码、设备品牌信息</para>
|
|||
|
|
/// <para>2. 记录异常上下文快照,辅助故障定位与复盘</para>
|
|||
|
|
/// 协作关系:
|
|||
|
|
/// <para>1. 与 <see cref="HikErrorMapper"/> 配合:实现厂商错误码→标准错误码的转换</para>
|
|||
|
|
/// <para>2. 与 <see cref="RecoveryPolicy"/> 配合:提供错误码输入,驱动故障自愈决策</para>
|
|||
|
|
/// </summary>
|
|||
|
|
public class CameraException : Exception
|
|||
|
|
{
|
|||
|
|
#region --- 核心异常属性 (Core Exception Properties) ---
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 归一化后的标准错误码
|
|||
|
|
/// 业务用途:作为 RecoveryPolicy 的决策输入,屏蔽厂商差异
|
|||
|
|
/// </summary>
|
|||
|
|
public CameraErrorCode ErrorCode { get; }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 厂商原始错误码(如海康 NET_DVR_GetLastError、大华 SDK 原生错误码)
|
|||
|
|
/// 业务用途:厂商文档对照、深度问题排查
|
|||
|
|
/// </summary>
|
|||
|
|
public int RawErrorCode { get; }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 发生异常的设备品牌
|
|||
|
|
/// 业务用途:区分不同厂商的错误码规则,辅助错误映射
|
|||
|
|
/// </summary>
|
|||
|
|
public DeviceBrand Brand { get; }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 异常发生时的上下文快照(只读集合,防止外部篡改)
|
|||
|
|
/// 存储内容:设备IP、通道号、操作参数、SDK句柄、时间戳等案发现场信息
|
|||
|
|
/// 业务用途:故障复盘时还原现场,快速定位根因
|
|||
|
|
/// </summary>
|
|||
|
|
public IReadOnlyDictionary<string, object> Context { get; init; } = new Dictionary<string, object>();
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region --- 构造函数 (Constructors) ---
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 初始化 CameraException 实例
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="errorCode">归一化标准错误码</param>
|
|||
|
|
/// <param name="message">异常描述信息</param>
|
|||
|
|
/// <param name="brand">设备品牌</param>
|
|||
|
|
/// <param name="rawErrorCode">厂商原始错误码(默认 0)</param>
|
|||
|
|
/// <param name="innerException">内部异常(默认 null)</param>
|
|||
|
|
public CameraException(
|
|||
|
|
CameraErrorCode errorCode,
|
|||
|
|
string message,
|
|||
|
|
DeviceBrand brand,
|
|||
|
|
int rawErrorCode = 0,
|
|||
|
|
Exception? innerException = null)
|
|||
|
|
: base(message, innerException)
|
|||
|
|
{
|
|||
|
|
ErrorCode = errorCode;
|
|||
|
|
Brand = brand;
|
|||
|
|
RawErrorCode = rawErrorCode;
|
|||
|
|
// 初始化上下文字典为可写的 Dictionary,兼容 WithContext 方法
|
|||
|
|
Context = new Dictionary<string, object>();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region --- 工具方法 (Utility Methods) ---
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 链式添加上下文信息(Builder 模式)
|
|||
|
|
/// 业务用途:在抛出异常前,逐步追加案发现场信息
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="key">上下文键(如 "DeviceIp", "ChannelIndex")</param>
|
|||
|
|
/// <param name="value">上下文值</param>
|
|||
|
|
/// <returns>当前异常实例(支持链式调用)</returns>
|
|||
|
|
public CameraException WithContext(string key, object value)
|
|||
|
|
{
|
|||
|
|
// 强制转换为可写的 Dictionary,保证上下文可追加
|
|||
|
|
if (Context is Dictionary<string, object> contextDict)
|
|||
|
|
{
|
|||
|
|
contextDict[key] = value;
|
|||
|
|
}
|
|||
|
|
return this;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 重写 ToString 方法,输出标准化异常日志
|
|||
|
|
/// 格式:[CameraError] Brand: {品牌} | Code: {标准码}({原始码}) | Message: {描述} | Context: {上下文}
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns>格式化的异常字符串</returns>
|
|||
|
|
public override string ToString()
|
|||
|
|
{
|
|||
|
|
var contextStr = Context.Count > 0
|
|||
|
|
? $" | Context: {string.Join(", ", Context.Select(kvp => $"{kvp.Key}={kvp.Value}"))}"
|
|||
|
|
: string.Empty;
|
|||
|
|
|
|||
|
|
return $"[CameraError] Brand: {Brand} | Code: {ErrorCode}({RawErrorCode}) | Message: {Message}{contextStr}";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
}
|