321 lines
10 KiB
C#
321 lines
10 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Runtime.InteropServices;
|
||
using ComApi = Autodesk.Navisworks.Api.Interop.ComApi;
|
||
using ComApiBridge = Autodesk.Navisworks.Api.ComApi.ComApiBridge;
|
||
|
||
namespace NavisworksTransport
|
||
{
|
||
/// <summary>
|
||
/// COM API 管理基类 - 提供标准化的COM对象管理模式
|
||
/// 统一COM对象生命周期管理、异常处理和资源释放
|
||
/// </summary>
|
||
public abstract class ComApiBase : IDisposable
|
||
{
|
||
#region 字段和属性
|
||
|
||
/// <summary>
|
||
/// COM状态对象,通过统一管理器获取
|
||
/// </summary>
|
||
protected ComApi.InwOpState10 ComState
|
||
{
|
||
get { return ComStateManager.GetState(); }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 跟踪COM对象的集合,确保正确释放
|
||
/// </summary>
|
||
private readonly List<object> _trackedComObjects = new List<object>();
|
||
|
||
/// <summary>
|
||
/// 对象释放锁
|
||
/// </summary>
|
||
private readonly object _disposeLock = new object();
|
||
|
||
/// <summary>
|
||
/// 是否已释放标志
|
||
/// </summary>
|
||
private bool _disposed = false;
|
||
|
||
#endregion
|
||
|
||
#region COM对象管理方法
|
||
|
||
/// <summary>
|
||
/// 注册COM对象以便跟踪和自动释放
|
||
/// </summary>
|
||
/// <typeparam name="T">COM对象类型</typeparam>
|
||
/// <param name="comObject">要跟踪的COM对象</param>
|
||
/// <returns>注册的COM对象</returns>
|
||
protected T TrackComObject<T>(T comObject) where T : class
|
||
{
|
||
if (comObject == null) return null;
|
||
|
||
lock (_disposeLock)
|
||
{
|
||
if (!_disposed && Marshal.IsComObject(comObject))
|
||
{
|
||
_trackedComObjects.Add(comObject);
|
||
LogManager.Debug($"[COM跟踪] 注册COM对象: {typeof(T).Name},当前跟踪数量: {_trackedComObjects.Count}");
|
||
}
|
||
}
|
||
|
||
return comObject;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 安全释放单个COM对象
|
||
/// </summary>
|
||
/// <param name="comObject">要释放的COM对象</param>
|
||
/// <param name="objectName">对象名称(用于日志)</param>
|
||
protected void SafeReleaseComObject(object comObject, string objectName = "未知COM对象")
|
||
{
|
||
if (comObject == null)
|
||
{
|
||
LogManager.Debug($"[COM释放] {objectName}为null,无需释放");
|
||
return;
|
||
}
|
||
|
||
try
|
||
{
|
||
if (Marshal.IsComObject(comObject))
|
||
{
|
||
Marshal.ReleaseComObject(comObject);
|
||
LogManager.Debug($"[COM释放] 成功释放{objectName}");
|
||
}
|
||
else
|
||
{
|
||
LogManager.Debug($"[COM释放] {objectName}不是COM对象,跳过释放");
|
||
}
|
||
}
|
||
catch (InvalidComObjectException)
|
||
{
|
||
LogManager.Debug($"[COM释放] {objectName}已无效,无需释放");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Warning($"[COM释放] 释放{objectName}失败: {ex.Message}");
|
||
}
|
||
finally
|
||
{
|
||
// 从跟踪列表中移除
|
||
lock (_disposeLock)
|
||
{
|
||
_trackedComObjects.Remove(comObject);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 批量释放跟踪的COM对象
|
||
/// </summary>
|
||
protected void ReleaseAllTrackedComObjects()
|
||
{
|
||
lock (_disposeLock)
|
||
{
|
||
LogManager.Debug($"[COM批量释放] 开始释放 {_trackedComObjects.Count} 个跟踪的COM对象");
|
||
|
||
var objectsToRelease = new List<object>(_trackedComObjects);
|
||
_trackedComObjects.Clear();
|
||
|
||
foreach (var comObject in objectsToRelease)
|
||
{
|
||
try
|
||
{
|
||
if (comObject != null && Marshal.IsComObject(comObject))
|
||
{
|
||
Marshal.ReleaseComObject(comObject);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Warning($"[COM批量释放] 释放跟踪对象失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
LogManager.Debug("[COM批量释放] 完成所有跟踪COM对象的释放");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行COM操作的安全包装方法
|
||
/// </summary>
|
||
/// <typeparam name="T">返回类型</typeparam>
|
||
/// <param name="operation">要执行的操作</param>
|
||
/// <param name="operationName">操作名称(用于日志)</param>
|
||
/// <returns>操作结果</returns>
|
||
/// <exception cref="COMException">COM操作失败时抛出</exception>
|
||
protected T SafeComOperation<T>(Func<T> operation, string operationName = "COM操作")
|
||
{
|
||
try
|
||
{
|
||
LogManager.Debug($"[COM操作] 开始执行: {operationName}");
|
||
var result = operation();
|
||
LogManager.Debug($"[COM操作] 成功完成: {operationName}");
|
||
return result;
|
||
}
|
||
catch (COMException comEx)
|
||
{
|
||
LogManager.Error($"[COM操作] COM异常 - {operationName}: {comEx.Message} (HRESULT: 0x{comEx.ErrorCode:X8})");
|
||
throw;
|
||
}
|
||
catch (InvalidComObjectException)
|
||
{
|
||
LogManager.Error($"[COM操作] COM对象已无效 - {operationName}");
|
||
throw;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"[COM操作] 一般异常 - {operationName}: {ex.Message}");
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行无返回值COM操作的安全包装方法
|
||
/// </summary>
|
||
/// <param name="operation">要执行的操作</param>
|
||
/// <param name="operationName">操作名称(用于日志)</param>
|
||
/// <exception cref="COMException">COM操作失败时抛出</exception>
|
||
protected void SafeComOperation(Action operation, string operationName = "COM操作")
|
||
{
|
||
SafeComOperation(() =>
|
||
{
|
||
operation();
|
||
return true;
|
||
}, operationName);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region IDisposable 实现
|
||
|
||
/// <summary>
|
||
/// 释放资源
|
||
/// </summary>
|
||
public void Dispose()
|
||
{
|
||
Dispose(true);
|
||
GC.SuppressFinalize(this);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 释放资源的实际实现
|
||
/// </summary>
|
||
/// <param name="disposing">是否释放托管资源</param>
|
||
protected virtual void Dispose(bool disposing)
|
||
{
|
||
if (!_disposed)
|
||
{
|
||
if (disposing)
|
||
{
|
||
try
|
||
{
|
||
LogManager.Debug($"[COM基类] 开始释放 {GetType().Name} 的资源");
|
||
|
||
// 释放所有跟踪的COM对象
|
||
ReleaseAllTrackedComObjects();
|
||
|
||
// 调用派生类的清理方法
|
||
OnDisposing();
|
||
|
||
LogManager.Debug($"[COM基类] 完成释放 {GetType().Name} 的资源");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"[COM基类] 释放 {GetType().Name} 资源时发生异常: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
_disposed = true;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 派生类可重写此方法进行特定的清理操作
|
||
/// </summary>
|
||
protected virtual void OnDisposing()
|
||
{
|
||
// 派生类可以重写此方法进行特定清理
|
||
}
|
||
|
||
/// <summary>
|
||
/// 析构函数
|
||
/// </summary>
|
||
~ComApiBase()
|
||
{
|
||
Dispose(false);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查对象是否已释放
|
||
/// </summary>
|
||
protected void ThrowIfDisposed()
|
||
{
|
||
if (_disposed)
|
||
{
|
||
throw new ObjectDisposedException(GetType().Name);
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
|
||
/// <summary>
|
||
/// COM状态对象统一管理器
|
||
/// </summary>
|
||
public static class ComStateManager
|
||
{
|
||
private static ComApi.InwOpState10 _sharedState;
|
||
private static readonly object _stateLock = new object();
|
||
|
||
/// <summary>
|
||
/// 获取COM状态对象(单例模式)
|
||
/// </summary>
|
||
/// <returns>COM状态对象</returns>
|
||
public static ComApi.InwOpState10 GetState()
|
||
{
|
||
lock (_stateLock)
|
||
{
|
||
if (_sharedState == null)
|
||
{
|
||
try
|
||
{
|
||
_sharedState = ComApiBridge.State;
|
||
LogManager.Debug("[COM状态管理] 初始化COM状态对象");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"[COM状态管理] 获取COM状态失败: {ex.Message}");
|
||
throw;
|
||
}
|
||
}
|
||
return _sharedState;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重置COM状态对象(仅在特殊情况下使用)
|
||
/// </summary>
|
||
public static void ResetState()
|
||
{
|
||
lock (_stateLock)
|
||
{
|
||
LogManager.Warning("[COM状态管理] 重置COM状态对象");
|
||
_sharedState = null;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取COM状态管理器状态信息
|
||
/// </summary>
|
||
/// <returns>状态信息</returns>
|
||
public static string GetStatusInfo()
|
||
{
|
||
lock (_stateLock)
|
||
{
|
||
return $"COM状态管理器状态: {(_sharedState != null ? "已初始化" : "未初始化")}";
|
||
}
|
||
}
|
||
}
|
||
} |