NavisworksTransport/src/Utils/ComApiBase.cs

321 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 ? "" : "")}";
}
}
}
}