diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 848666d..110cc46 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -154,7 +154,8 @@ "Bash(\"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\MSBuild.exe\" AStarTestRunner.csproj /p:Configuration=Debug /p:Platform=AnyCPU)", "Bash(\"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\MSBuild.exe\" AStarTestRunner.csproj)", "Bash(\"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\MSBuild.exe\" NavisworksTransport.UnitTests.csproj)", - "Bash(\"bin\\Debug\\AStarTestRunner.exe\")" + "Bash(\"bin\\Debug\\AStarTestRunner.exe\")", + "Bash(git restore:*)" ], "deny": [], "additionalDirectories": [ diff --git a/NavisworksTransportPlugin.csproj b/NavisworksTransportPlugin.csproj index 04cb8b4..1aed6ee 100644 --- a/NavisworksTransportPlugin.csproj +++ b/NavisworksTransportPlugin.csproj @@ -227,15 +227,12 @@ - - - diff --git a/src/UI/WPF/Collections/VirtualizedObservableCollection.cs b/src/UI/WPF/Collections/VirtualizedObservableCollection.cs deleted file mode 100644 index 65f6a3b..0000000 --- a/src/UI/WPF/Collections/VirtualizedObservableCollection.cs +++ /dev/null @@ -1,982 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.ComponentModel; -using System.Linq; -using System.Threading.Tasks; -using System.Windows.Data; -using NavisworksTransport.UI.WPF.Services; -using NavisworksTransport.Utils; - -namespace NavisworksTransport.UI.WPF.Collections -{ - /// - /// 虚拟化的可观察集合 - 为大数据集合提供高性能的WPF绑定支持 - /// 只在内存中保存可见项目,按需加载数据,支持智能预加载和缓存 - /// - /// 集合元素类型 - public class VirtualizedObservableCollection : IList, INotifyCollectionChanged, INotifyPropertyChanged - { - #region 字段和属性 - - // 数据提供器 - private readonly IVirtualDataProvider _dataProvider; - private readonly DataBindingPerformanceMonitor _performanceMonitor; - - // 虚拟化设置 - private int _pageSize = 100; - private int _cacheSize = 500; - private int _preloadDistance = 50; - - // 缓存管理 - private readonly Dictionary _itemCache = new Dictionary(); - private readonly Dictionary _cacheTimestamps = new Dictionary(); - private readonly object _cacheLock = new object(); - - // 状态管理 - private int _totalCount = 0; - private bool _isLoading = false; - private readonly object _loadingLock = new object(); - - // 视口管理 - private int _viewportStart = 0; - private int _viewportSize = 20; - - /// - /// 集合变更事件 - /// - public event NotifyCollectionChangedEventHandler CollectionChanged; - - /// - /// 属性变更事件 - /// - public event PropertyChangedEventHandler PropertyChanged; - - /// - /// 总项目数量 - /// - public int Count - { - get => _totalCount; - private set - { - if (_totalCount != value) - { - _totalCount = value; - OnPropertyChanged(nameof(Count)); - } - } - } - - /// - /// 页面大小 - 每次从数据提供器加载的项目数量 - /// - public int PageSize - { - get => _pageSize; - set - { - if (value > 0 && _pageSize != value) - { - _pageSize = value; - OnPropertyChanged(nameof(PageSize)); - InvalidateCache(); - } - } - } - - /// - /// 缓存大小 - 内存中保存的最大项目数量 - /// - public int CacheSize - { - get => _cacheSize; - set - { - if (value > 0 && _cacheSize != value) - { - _cacheSize = value; - OnPropertyChanged(nameof(CacheSize)); - CleanupCache(); - } - } - } - - /// - /// 预加载距离 - 距离视口边缘多远开始预加载 - /// - public int PreloadDistance - { - get => _preloadDistance; - set - { - if (value >= 0 && _preloadDistance != value) - { - _preloadDistance = value; - OnPropertyChanged(nameof(PreloadDistance)); - } - } - } - - /// - /// 当前视口起始位置 - /// - public int ViewportStart - { - get => _viewportStart; - set - { - if (_viewportStart != value) - { - _viewportStart = Math.Max(0, Math.Min(value, Math.Max(0, Count - _viewportSize))); - OnPropertyChanged(nameof(ViewportStart)); - TriggerPreload(); - } - } - } - - /// - /// 视口大小 - 可见区域的项目数量 - /// - public int ViewportSize - { - get => _viewportSize; - set - { - if (value > 0 && _viewportSize != value) - { - _viewportSize = value; - OnPropertyChanged(nameof(ViewportSize)); - TriggerPreload(); - } - } - } - - /// - /// 是否正在加载数据 - /// - public bool IsLoading => _isLoading; - - /// - /// 缓存命中率 - /// - public double CacheHitRatio { get; private set; } - - /// - /// 是否为只读集合 - /// - public bool IsReadOnly => false; - - #endregion - - #region 构造函数 - - /// - /// 初始化虚拟化集合 - /// - /// 数据提供器 - public VirtualizedObservableCollection(IVirtualDataProvider dataProvider) - { - _dataProvider = dataProvider ?? throw new ArgumentNullException(nameof(dataProvider)); - _performanceMonitor = DataBindingPerformanceMonitor.Instance; - - // 订阅数据提供器事件 - if (dataProvider is INotifyPropertyChanged notifyProvider) - { - notifyProvider.PropertyChanged += DataProvider_PropertyChanged; - } - - // 初始化总数量 - InitializeTotalCountAsync(); - - LogManager.Info($"VirtualizedObservableCollection<{typeof(T).Name}>已初始化"); - } - - #endregion - - #region 索引器和基本访问 - - /// - /// 获取或设置指定索引处的元素 - /// - /// 元素索引 - /// 指定位置的元素 - public T this[int index] - { - get - { - if (index < 0 || index >= Count) - throw new ArgumentOutOfRangeException(nameof(index)); - - return GetItemAsync(index).Result; - } - set - { - if (index < 0 || index >= Count) - throw new ArgumentOutOfRangeException(nameof(index)); - - _ = SetItemAsync(index, value); - } - } - - /// - /// 异步获取指定索引的项目 - /// - /// 项目索引 - /// 项目或null - public async Task GetItemAsync(int index) - { - if (index < 0 || index >= Count) - return default(T); - - using (_performanceMonitor.BeginCollectionUpdate(typeof(VirtualizedObservableCollection), "GetItem", 1)) - { - // 检查缓存 - lock (_cacheLock) - { - if (_itemCache.TryGetValue(index, out var cachedItem)) - { - _cacheTimestamps[index] = DateTime.UtcNow; - UpdateCacheHitRatio(true); - return cachedItem; - } - } - - UpdateCacheHitRatio(false); - - // 异步加载项目 - var item = await LoadItemAsync(index); - - // 缓存项目 - lock (_cacheLock) - { - _itemCache[index] = item; - _cacheTimestamps[index] = DateTime.UtcNow; - - // 清理过期缓存 - if (_itemCache.Count > _cacheSize) - { - CleanupCache(); - } - } - - // 触发预加载 - TriggerPreload(index); - - return item; - } - } - - /// - /// 异步设置指定索引的项目 - /// - /// 项目索引 - /// 新项目 - public async Task SetItemAsync(int index, T item) - { - if (index < 0 || index >= Count) - return; - - using (_performanceMonitor.BeginCollectionUpdate(typeof(VirtualizedObservableCollection), "SetItem", 1)) - { - // 更新数据提供器 - await _dataProvider.SetItemAsync(index, item); - - // 更新缓存 - lock (_cacheLock) - { - _itemCache[index] = item; - _cacheTimestamps[index] = DateTime.UtcNow; - } - - // 触发变更通知 - OnCollectionChanged(new NotifyCollectionChangedEventArgs( - NotifyCollectionChangedAction.Replace, item, default(T), index)); - } - } - - #endregion - - #region 数据加载和缓存管理 - - /// - /// 异步加载单个项目 - /// - /// 项目索引 - /// 加载的项目 - private async Task LoadItemAsync(int index) - { - try - { - lock (_loadingLock) - { - _isLoading = true; - } - OnPropertyChanged(nameof(IsLoading)); - - return await _dataProvider.GetItemAsync(index); - } - catch (Exception ex) - { - LogManager.Error($"加载项目失败 [索引: {index}]: {ex.Message}"); - return default(T); - } - finally - { - lock (_loadingLock) - { - _isLoading = false; - } - OnPropertyChanged(nameof(IsLoading)); - } - } - - /// - /// 异步批量加载项目 - /// - /// 起始索引 - /// 加载数量 - /// 加载的项目列表 - private async Task> LoadRangeAsync(int startIndex, int count) - { - try - { - lock (_loadingLock) - { - _isLoading = true; - } - OnPropertyChanged(nameof(IsLoading)); - - var endIndex = Math.Min(startIndex + count, Count); - var actualCount = endIndex - startIndex; - - if (actualCount <= 0) - return Enumerable.Empty(); - - return await _dataProvider.GetRangeAsync(startIndex, actualCount); - } - catch (Exception ex) - { - LogManager.Error($"批量加载项目失败 [范围: {startIndex}-{startIndex + count}]: {ex.Message}"); - return Enumerable.Empty(); - } - finally - { - lock (_loadingLock) - { - _isLoading = false; - } - OnPropertyChanged(nameof(IsLoading)); - } - } - - /// - /// 触发智能预加载 - /// - /// 最近访问的索引 - private void TriggerPreload(int? accessedIndex = null) - { - if (_preloadDistance <= 0) - return; - - Task.Run(async () => - { - try - { - // 确定预加载范围 - var centerIndex = accessedIndex ?? (_viewportStart + _viewportSize / 2); - var preloadStart = Math.Max(0, centerIndex - _preloadDistance); - var preloadEnd = Math.Min(Count - 1, centerIndex + _preloadDistance); - - // 找出需要预加载的索引 - var indexesToPreload = new List(); - lock (_cacheLock) - { - for (int i = preloadStart; i <= preloadEnd; i++) - { - if (!_itemCache.ContainsKey(i)) - { - indexesToPreload.Add(i); - } - } - } - - if (indexesToPreload.Count == 0) - return; - - // 按页面分组预加载 - var pages = indexesToPreload.GroupBy(i => i / _pageSize); - foreach (var page in pages) - { - var pageStart = page.Key * _pageSize; - var pageItems = await LoadRangeAsync(pageStart, _pageSize); - - // 缓存加载的项目 - lock (_cacheLock) - { - var itemArray = pageItems.ToArray(); - for (int i = 0; i < itemArray.Length; i++) - { - var index = pageStart + i; - if (index < Count && !_itemCache.ContainsKey(index)) - { - _itemCache[index] = itemArray[i]; - _cacheTimestamps[index] = DateTime.UtcNow; - } - } - } - } - - LogManager.Debug($"预加载完成: {indexesToPreload.Count}个项目"); - } - catch (Exception ex) - { - LogManager.Error($"预加载失败: {ex.Message}"); - } - }); - } - - /// - /// 清理过期缓存 - /// - private void CleanupCache() - { - lock (_cacheLock) - { - if (_itemCache.Count <= _cacheSize) - return; - - // 按访问时间排序,移除最久未访问的项目 - var itemsToRemove = _cacheTimestamps - .OrderBy(kvp => kvp.Value) - .Take(_itemCache.Count - _cacheSize) - .Select(kvp => kvp.Key) - .ToList(); - - foreach (var index in itemsToRemove) - { - _itemCache.Remove(index); - _cacheTimestamps.Remove(index); - } - - LogManager.Debug($"缓存清理完成: 移除{itemsToRemove.Count}个项目"); - } - } - - /// - /// 清空所有缓存 - /// - private void InvalidateCache() - { - lock (_cacheLock) - { - _itemCache.Clear(); - _cacheTimestamps.Clear(); - CacheHitRatio = 0; - } - - LogManager.Debug("缓存已清空"); - } - - /// - /// 更新缓存命中率 - /// - /// 是否命中缓存 - private void UpdateCacheHitRatio(bool isHit) - { - // 使用简单的移动平均计算命中率 - const double alpha = 0.1; // 平滑因子 - var hitValue = isHit ? 1.0 : 0.0; - CacheHitRatio = CacheHitRatio * (1 - alpha) + hitValue * alpha; - } - - #endregion - - #region 集合操作实现 - - /// - /// 添加项目到集合末尾 - /// - /// 要添加的项目 - public void Add(T item) - { - InsertAsync(Count, item).Wait(); - } - - /// - /// 异步添加项目 - /// - /// 要添加的项目 - public async Task AddAsync(T item) - { - await InsertAsync(Count, item); - } - - /// - /// 在指定位置插入项目 - /// - /// 插入位置 - /// 要插入的项目 - public void Insert(int index, T item) - { - InsertAsync(index, item).Wait(); - } - - /// - /// 异步在指定位置插入项目 - /// - /// 插入位置 - /// 要插入的项目 - public async Task InsertAsync(int index, T item) - { - if (index < 0 || index > Count) - throw new ArgumentOutOfRangeException(nameof(index)); - - using (_performanceMonitor.BeginCollectionUpdate(typeof(VirtualizedObservableCollection), "Insert", 1)) - { - // 在数据提供器中插入 - await _dataProvider.InsertAsync(index, item); - - // 更新总数量 - Count++; - - // 调整缓存索引 - lock (_cacheLock) - { - var itemsToReindex = _itemCache.Where(kvp => kvp.Key >= index).ToList(); - foreach (var kvp in itemsToReindex) - { - _itemCache.Remove(kvp.Key); - _itemCache[kvp.Key + 1] = kvp.Value; - - if (_cacheTimestamps.TryGetValue(kvp.Key, out var timestamp)) - { - _cacheTimestamps.Remove(kvp.Key); - _cacheTimestamps[kvp.Key + 1] = timestamp; - } - } - - // 缓存新插入的项目 - _itemCache[index] = item; - _cacheTimestamps[index] = DateTime.UtcNow; - } - - // 触发变更通知 - OnCollectionChanged(new NotifyCollectionChangedEventArgs( - NotifyCollectionChangedAction.Add, item, index)); - } - } - - /// - /// 移除指定项目 - /// - /// 要移除的项目 - /// 是否成功移除 - public bool Remove(T item) - { - var index = IndexOf(item); - if (index >= 0) - { - RemoveAt(index); - return true; - } - return false; - } - - /// - /// 移除指定位置的项目 - /// - /// 要移除的项目位置 - public void RemoveAt(int index) - { - RemoveAtAsync(index).Wait(); - } - - /// - /// 异步移除指定位置的项目 - /// - /// 要移除的项目位置 - public async Task RemoveAtAsync(int index) - { - if (index < 0 || index >= Count) - throw new ArgumentOutOfRangeException(nameof(index)); - - using (_performanceMonitor.BeginCollectionUpdate(typeof(VirtualizedObservableCollection), "RemoveAt", 1)) - { - // 获取要移除的项目 - var removedItem = await GetItemAsync(index); - - // 从数据提供器中移除 - await _dataProvider.RemoveAtAsync(index); - - // 更新总数量 - Count--; - - // 调整缓存索引 - lock (_cacheLock) - { - _itemCache.Remove(index); - _cacheTimestamps.Remove(index); - - var itemsToReindex = _itemCache.Where(kvp => kvp.Key > index).ToList(); - foreach (var kvp in itemsToReindex) - { - _itemCache.Remove(kvp.Key); - _itemCache[kvp.Key - 1] = kvp.Value; - - if (_cacheTimestamps.TryGetValue(kvp.Key, out var timestamp)) - { - _cacheTimestamps.Remove(kvp.Key); - _cacheTimestamps[kvp.Key - 1] = timestamp; - } - } - } - - // 触发变更通知 - OnCollectionChanged(new NotifyCollectionChangedEventArgs( - NotifyCollectionChangedAction.Remove, removedItem, index)); - } - } - - /// - /// 清空集合 - /// - public void Clear() - { - ClearAsync().Wait(); - } - - /// - /// 异步清空集合 - /// - public async Task ClearAsync() - { - using (_performanceMonitor.BeginCollectionUpdate(typeof(VirtualizedObservableCollection), "Clear", Count)) - { - // 清空数据提供器 - await _dataProvider.ClearAsync(); - - // 更新状态 - Count = 0; - InvalidateCache(); - - // 触发变更通知 - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); - } - } - - /// - /// 检查集合是否包含指定项目 - /// - /// 要检查的项目 - /// 是否包含 - public bool Contains(T item) - { - return IndexOf(item) >= 0; - } - - /// - /// 查找项目的索引 - /// - /// 要查找的项目 - /// 项目索引,如果不存在返回-1 - public int IndexOf(T item) - { - // 首先在缓存中查找 - lock (_cacheLock) - { - foreach (var kvp in _itemCache) - { - if (EqualityComparer.Default.Equals(kvp.Value, item)) - { - return kvp.Key; - } - } - } - - // 如果缓存中没有,使用数据提供器查找 - return _dataProvider.IndexOfAsync(item).Result; - } - - /// - /// 复制集合项目到数组 - /// - /// 目标数组 - /// 起始索引 - public void CopyTo(T[] array, int arrayIndex) - { - if (array == null) - throw new ArgumentNullException(nameof(array)); - - if (arrayIndex < 0 || arrayIndex + Count > array.Length) - throw new ArgumentOutOfRangeException(nameof(arrayIndex)); - - for (int i = 0; i < Count; i++) - { - array[arrayIndex + i] = this[i]; - } - } - - #endregion - - #region 枚举器实现 - - /// - /// 获取枚举器 - /// - /// 枚举器 - public IEnumerator GetEnumerator() - { - return new VirtualizedEnumerator(this); - } - - /// - /// 获取非泛型枚举器 - /// - /// 枚举器 - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - /// - /// 虚拟化枚举器 - 按需加载数据 - /// - private class VirtualizedEnumerator : IEnumerator - { - private readonly VirtualizedObservableCollection _collection; - private int _currentIndex = -1; - - public VirtualizedEnumerator(VirtualizedObservableCollection collection) - { - _collection = collection; - } - - public T Current { get; private set; } - - object IEnumerator.Current => Current; - - public bool MoveNext() - { - if (_currentIndex + 1 < _collection.Count) - { - _currentIndex++; - Current = _collection.GetItemAsync(_currentIndex).Result; - return true; - } - return false; - } - - public void Reset() - { - _currentIndex = -1; - Current = default(T); - } - - public void Dispose() - { - Current = default(T); - } - } - - #endregion - - #region 事件处理 - - /// - /// 初始化总数量 - /// - private async void InitializeTotalCountAsync() - { - try - { - var totalCount = await _dataProvider.GetTotalCountAsync(); - Count = totalCount; - LogManager.Info($"虚拟化集合初始化完成,总数量: {totalCount}"); - } - catch (Exception ex) - { - LogManager.Error($"获取总数量失败: {ex.Message}"); - Count = 0; - } - } - - /// - /// 数据提供器属性变更处理 - /// - private async void DataProvider_PropertyChanged(object sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == "TotalCount") - { - try - { - var newCount = await _dataProvider.GetTotalCountAsync(); - if (newCount != Count) - { - Count = newCount; - InvalidateCache(); - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); - } - } - catch (Exception ex) - { - LogManager.Error($"更新总数量失败: {ex.Message}"); - } - } - } - - /// - /// 触发集合变更事件 - /// - /// 事件参数 - protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e) - { - CollectionChanged?.Invoke(this, e); - } - - /// - /// 触发属性变更事件 - /// - /// 属性名称 - protected virtual void OnPropertyChanged(string propertyName) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - - #endregion - - #region 诊断和统计 - - /// - /// 获取虚拟化统计信息 - /// - /// 统计信息 - public VirtualizationStatistics GetStatistics() - { - lock (_cacheLock) - { - return new VirtualizationStatistics - { - TotalCount = Count, - CachedItemsCount = _itemCache.Count, - CacheHitRatio = CacheHitRatio, - PageSize = PageSize, - CacheSize = CacheSize, - PreloadDistance = PreloadDistance, - ViewportStart = ViewportStart, - ViewportSize = ViewportSize, - IsLoading = IsLoading - }; - } - } - - /// - /// 生成诊断报告 - /// - /// 诊断报告 - public string GenerateDiagnosticReport() - { - var stats = GetStatistics(); - var report = new System.Text.StringBuilder(); - - report.AppendLine("=== 虚拟化集合诊断报告 ==="); - report.AppendLine($"集合类型: {typeof(T).Name}"); - report.AppendLine($"总项目数: {stats.TotalCount:N0}"); - report.AppendLine($"缓存项目数: {stats.CachedItemsCount:N0}"); - report.AppendLine($"缓存命中率: {stats.CacheHitRatio:P2}"); - report.AppendLine($"页面大小: {stats.PageSize}"); - report.AppendLine($"缓存大小: {stats.CacheSize}"); - report.AppendLine($"预加载距离: {stats.PreloadDistance}"); - report.AppendLine($"视口位置: {stats.ViewportStart}-{stats.ViewportStart + stats.ViewportSize}"); - report.AppendLine($"加载状态: {(stats.IsLoading ? "加载中" : "空闲")}"); - - var memoryEfficiency = stats.TotalCount > 0 ? (double)stats.CachedItemsCount / stats.TotalCount : 0; - report.AppendLine($"内存效率: {memoryEfficiency:P2} ({stats.CachedItemsCount}/{stats.TotalCount})"); - - return report.ToString(); - } - - #endregion - } - - #region 虚拟数据提供器接口 - - /// - /// 虚拟数据提供器接口 - 为虚拟化集合提供数据访问抽象 - /// - /// 数据类型 - public interface IVirtualDataProvider - { - /// - /// 获取总项目数量 - /// - /// 总数量 - Task GetTotalCountAsync(); - - /// - /// 获取指定索引的项目 - /// - /// 索引 - /// 项目 - Task GetItemAsync(int index); - - /// - /// 获取指定范围的项目 - /// - /// 起始索引 - /// 数量 - /// 项目列表 - Task> GetRangeAsync(int startIndex, int count); - - /// - /// 设置指定索引的项目 - /// - /// 索引 - /// 新项目 - Task SetItemAsync(int index, T item); - - /// - /// 在指定位置插入项目 - /// - /// 插入位置 - /// 要插入的项目 - Task InsertAsync(int index, T item); - - /// - /// 移除指定位置的项目 - /// - /// 位置 - Task RemoveAtAsync(int index); - - /// - /// 清空所有项目 - /// - Task ClearAsync(); - - /// - /// 查找项目索引 - /// - /// 要查找的项目 - /// 索引,如果不存在返回-1 - Task IndexOfAsync(T item); - } - - /// - /// 虚拟化统计信息 - /// - public class VirtualizationStatistics - { - public int TotalCount { get; set; } - public int CachedItemsCount { get; set; } - public double CacheHitRatio { get; set; } - public int PageSize { get; set; } - public int CacheSize { get; set; } - public int PreloadDistance { get; set; } - public int ViewportStart { get; set; } - public int ViewportSize { get; set; } - public bool IsLoading { get; set; } - } - - #endregion -} \ No newline at end of file diff --git a/src/UI/WPF/Services/CrossViewModelSynchronizer.cs b/src/UI/WPF/Services/CrossViewModelSynchronizer.cs deleted file mode 100644 index 4ea3b0a..0000000 --- a/src/UI/WPF/Services/CrossViewModelSynchronizer.cs +++ /dev/null @@ -1,1029 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Threading.Tasks; -using System.Threading; -using NavisworksTransport.UI.WPF.ViewModels; -using NavisworksTransport.Utils; - -namespace NavisworksTransport.UI.WPF.Services -{ - /// - /// 跨ViewModel数据同步优化器 - 确保数据一致性和高效的同步性能 - /// 支持发布-订阅模式、依赖追踪和智能批量同步 - /// - public class CrossViewModelSynchronizer : IDisposable - { - #region 字段和属性 - - private static CrossViewModelSynchronizer _instance; - private static readonly object _instanceLock = new object(); - - // 订阅管理 - private readonly ConcurrentDictionary> _subscriptions; - private readonly ConcurrentDictionary _viewModelRegistry; - - // 依赖追踪 - private readonly ConcurrentDictionary> _propertyDependencies; - private readonly ConcurrentDictionary> _viewModelDependencies; - - // 同步队列和批量处理 - private readonly ConcurrentQueue _synchronizationQueue; - private readonly Timer _batchProcessingTimer; - private readonly object _processingLock = new object(); - private volatile bool _isProcessing = false; - private volatile bool _isDisposed = false; - - // 性能监控 - private readonly DataBindingPerformanceMonitor _performanceMonitor; - - // 配置选项 - private TimeSpan _batchProcessingInterval = TimeSpan.FromMilliseconds(50); - private int _maxBatchSize = 100; - private bool _enableSmartBatching = true; - private bool _enableDependencyTracking = true; - - /// - /// 获取跨ViewModel同步器的单例实例 - /// - public static CrossViewModelSynchronizer Instance - { - get - { - if (_instance == null) - { - lock (_instanceLock) - { - if (_instance == null) - { - _instance = new CrossViewModelSynchronizer(); - } - } - } - return _instance; - } - } - - /// - /// 批量处理间隔 - /// - public TimeSpan BatchProcessingInterval - { - get => _batchProcessingInterval; - set - { - _batchProcessingInterval = value; - _batchProcessingTimer?.Change(value, value); - } - } - - /// - /// 最大批量处理大小 - /// - public int MaxBatchSize - { - get => _maxBatchSize; - set => _maxBatchSize = Math.Max(1, value); - } - - /// - /// 是否启用智能批量处理 - /// - public bool EnableSmartBatching - { - get => _enableSmartBatching; - set => _enableSmartBatching = value; - } - - /// - /// 是否启用依赖追踪 - /// - public bool EnableDependencyTracking - { - get => _enableDependencyTracking; - set => _enableDependencyTracking = value; - } - - /// - /// 当前注册的ViewModel数量 - /// - public int RegisteredViewModelsCount => _viewModelRegistry.Count; - - /// - /// 当前订阅总数 - /// - public int TotalSubscriptionsCount => _subscriptions.Values.Sum(bag => bag.Count); - - /// - /// 等待同步的事件数量 - /// - public int PendingSynchronizationCount => _synchronizationQueue.Count; - - #endregion - - #region 构造函数 - - private CrossViewModelSynchronizer() - { - _subscriptions = new ConcurrentDictionary>(); - _viewModelRegistry = new ConcurrentDictionary(); - _propertyDependencies = new ConcurrentDictionary>(); - _viewModelDependencies = new ConcurrentDictionary>(); - _synchronizationQueue = new ConcurrentQueue(); - _performanceMonitor = DataBindingPerformanceMonitor.Instance; - - // 初始化批量处理定时器 - _batchProcessingTimer = new Timer(ProcessSynchronizationBatch, null, _batchProcessingInterval, _batchProcessingInterval); - - LogManager.Info("跨ViewModel数据同步器已初始化"); - } - - #endregion - - #region ViewModel注册和管理 - - /// - /// 注册ViewModel以启用同步功能 - /// - /// 要注册的ViewModel - /// 同步选项 - public void RegisterViewModel(ViewModelBase viewModel, ViewModelSyncOptions options = null) - { - if (_isDisposed || viewModel == null) - return; - - options = options ?? ViewModelSyncOptions.Default; - - var metadata = new ViewModelMetadata - { - ViewModel = viewModel, - Options = options, - RegistrationTime = DateTime.UtcNow, - LastSyncTime = DateTime.UtcNow, - SyncEventCount = 0 - }; - - _viewModelRegistry.TryAdd(viewModel, metadata); - - // 订阅PropertyChanged事件 - viewModel.PropertyChanged += ViewModel_PropertyChanged; - - // 初始化依赖追踪 - if (_enableDependencyTracking && options.TrackedProperties?.Length > 0) - { - InitializeDependencyTracking(viewModel, options.TrackedProperties); - } - - LogManager.Debug($"ViewModel已注册同步: {viewModel.GetType().Name}"); - } - - /// - /// 注销ViewModel - /// - /// 要注销的ViewModel - public void UnregisterViewModel(ViewModelBase viewModel) - { - if (_isDisposed || viewModel == null) - return; - - // 移除订阅 - viewModel.PropertyChanged -= ViewModel_PropertyChanged; - - // 清理注册信息 - _viewModelRegistry.TryRemove(viewModel, out _); - - // 清理相关订阅 - RemoveViewModelSubscriptions(viewModel); - - // 清理依赖追踪 - _viewModelDependencies.TryRemove(viewModel, out _); - - LogManager.Debug($"ViewModel已注销同步: {viewModel.GetType().Name}"); - } - - /// - /// 初始化依赖追踪 - /// - /// ViewModel - /// 需要追踪的属性 - private void InitializeDependencyTracking(ViewModelBase viewModel, string[] trackedProperties) - { - var dependencies = new HashSet(trackedProperties); - _viewModelDependencies.TryAdd(viewModel, dependencies); - - foreach (var property in trackedProperties) - { - var key = CreatePropertyKey(viewModel, property); - _propertyDependencies.GetOrAdd(key, _ => new HashSet()); - } - } - - #endregion - - #region 订阅管理 - - /// - /// 订阅属性变更事件 - /// - /// 源ViewModel - /// 源属性名 - /// 目标ViewModel - /// 目标属性名 - /// 值转换器(可选) - /// 订阅选项 - /// 订阅ID - public string Subscribe(ViewModelBase sourceViewModel, string sourceProperty, - ViewModelBase targetViewModel, string targetProperty, - Func converter = null, SubscriptionOptions options = null) - { - if (_isDisposed || sourceViewModel == null || targetViewModel == null) - return null; - - options = options ?? SubscriptionOptions.Default; - - var subscription = new SynchronizationSubscription - { - Id = Guid.NewGuid().ToString(), - SourceViewModel = new WeakReference(sourceViewModel), - SourceProperty = sourceProperty, - TargetViewModel = new WeakReference(targetViewModel), - TargetProperty = targetProperty, - Converter = converter, - Options = options, - CreatedTime = DateTime.UtcNow, - LastSyncTime = DateTime.UtcNow, - SyncCount = 0 - }; - - var key = CreatePropertyKey(sourceViewModel, sourceProperty); - var subscriptionBag = _subscriptions.GetOrAdd(key, _ => new ConcurrentBag()); - subscriptionBag.Add(subscription); - - // 添加依赖关系 - if (_enableDependencyTracking) - { - AddPropertyDependency(sourceViewModel, sourceProperty, targetViewModel, targetProperty); - } - - LogManager.Debug($"属性同步订阅已创建: {sourceViewModel.GetType().Name}.{sourceProperty} -> {targetViewModel.GetType().Name}.{targetProperty}"); - - return subscription.Id; - } - - /// - /// 取消订阅 - /// - /// 订阅ID - public void Unsubscribe(string subscriptionId) - { - if (_isDisposed || string.IsNullOrEmpty(subscriptionId)) - return; - - foreach (var kvp in _subscriptions) - { - var subscriptionsToKeep = new List(); - var found = false; - - foreach (var subscription in kvp.Value) - { - if (subscription.Id == subscriptionId) - { - found = true; - LogManager.Debug($"订阅已取消: {subscriptionId}"); - } - else - { - subscriptionsToKeep.Add(subscription); - } - } - - if (found) - { - // 重建订阅袋,移除已取消的订阅 - var newBag = new ConcurrentBag(); - foreach (var subscription in subscriptionsToKeep) - { - newBag.Add(subscription); - } - _subscriptions.TryUpdate(kvp.Key, newBag, kvp.Value); - break; - } - } - } - - /// - /// 订阅表达式形式的属性绑定 - /// - /// 源类型 - /// 目标类型 - /// 源ViewModel - /// 源属性表达式 - /// 目标ViewModel - /// 目标属性表达式 - /// 值转换器 - /// 订阅选项 - /// 订阅ID - public string Subscribe(TSource sourceViewModel, System.Linq.Expressions.Expression> sourceExpression, - TTarget targetViewModel, System.Linq.Expressions.Expression> targetExpression, - Func converter = null, SubscriptionOptions options = null) - where TSource : ViewModelBase - where TTarget : ViewModelBase - { - var sourceProperty = GetPropertyName(sourceExpression); - var targetProperty = GetPropertyName(targetExpression); - - return Subscribe(sourceViewModel, sourceProperty, targetViewModel, targetProperty, converter, options); - } - - /// - /// 移除特定ViewModel的所有订阅 - /// - /// ViewModel - private void RemoveViewModelSubscriptions(ViewModelBase viewModel) - { - var keysToUpdate = new List(); - - foreach (var kvp in _subscriptions) - { - var subscriptionsToKeep = new List(); - var hasChanges = false; - - foreach (var subscription in kvp.Value) - { - var sourceAlive = subscription.SourceViewModel.IsAlive; - var targetAlive = subscription.TargetViewModel.IsAlive; - var sourceMatch = sourceAlive && subscription.SourceViewModel.Target == viewModel; - var targetMatch = targetAlive && subscription.TargetViewModel.Target == viewModel; - - if (!sourceMatch && !targetMatch && sourceAlive && targetAlive) - { - subscriptionsToKeep.Add(subscription); - } - else - { - hasChanges = true; - } - } - - if (hasChanges) - { - keysToUpdate.Add(kvp.Key); - var newBag = new ConcurrentBag(); - foreach (var subscription in subscriptionsToKeep) - { - newBag.Add(subscription); - } - _subscriptions.TryUpdate(kvp.Key, newBag, kvp.Value); - } - } - } - - #endregion - - #region 依赖追踪 - - /// - /// 添加属性依赖关系 - /// - /// 源ViewModel - /// 源属性 - /// 目标ViewModel - /// 目标属性 - private void AddPropertyDependency(ViewModelBase sourceViewModel, string sourceProperty, - ViewModelBase targetViewModel, string targetProperty) - { - var sourceKey = CreatePropertyKey(sourceViewModel, sourceProperty); - var targetKey = CreatePropertyKey(targetViewModel, targetProperty); - - var dependencies = _propertyDependencies.GetOrAdd(sourceKey, _ => new HashSet()); - lock (dependencies) - { - dependencies.Add(targetKey); - } - } - - /// - /// 获取属性的所有依赖项 - /// - /// ViewModel - /// 属性名 - /// 依赖项列表 - public IEnumerable GetPropertyDependencies(ViewModelBase viewModel, string propertyName) - { - var key = CreatePropertyKey(viewModel, propertyName); - if (_propertyDependencies.TryGetValue(key, out var dependencies)) - { - lock (dependencies) - { - return dependencies.ToList(); - } - } - return Enumerable.Empty(); - } - - /// - /// 检测循环依赖 - /// - /// 起始ViewModel - /// 起始属性 - /// 是否存在循环依赖 - public bool DetectCircularDependency(ViewModelBase startViewModel, string startProperty) - { - var visited = new HashSet(); - var recursionStack = new HashSet(); - - return HasCircularDependencyRecursive(CreatePropertyKey(startViewModel, startProperty), visited, recursionStack); - } - - /// - /// 递归检测循环依赖 - /// - /// 属性键 - /// 已访问集合 - /// 递归栈 - /// 是否存在循环依赖 - private bool HasCircularDependencyRecursive(string propertyKey, HashSet visited, HashSet recursionStack) - { - if (recursionStack.Contains(propertyKey)) - return true; - - if (visited.Contains(propertyKey)) - return false; - - visited.Add(propertyKey); - recursionStack.Add(propertyKey); - - if (_propertyDependencies.TryGetValue(propertyKey, out var dependencies)) - { - lock (dependencies) - { - foreach (var dependency in dependencies) - { - if (HasCircularDependencyRecursive(dependency, visited, recursionStack)) - return true; - } - } - } - - recursionStack.Remove(propertyKey); - return false; - } - - #endregion - - #region 同步处理 - - /// - /// ViewModel属性变更事件处理 - /// - /// 发送者 - /// 事件参数 - private void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e) - { - if (_isDisposed || !(sender is ViewModelBase viewModel) || string.IsNullOrEmpty(e.PropertyName)) - return; - - // 检查是否需要同步 - var key = CreatePropertyKey(viewModel, e.PropertyName); - if (!_subscriptions.ContainsKey(key)) - return; - - // 创建同步事件 - var syncEvent = new SynchronizationEvent - { - Id = Guid.NewGuid().ToString(), - SourceViewModel = new WeakReference(viewModel), - PropertyName = e.PropertyName, - Timestamp = DateTime.UtcNow, - Priority = GetEventPriority(viewModel, e.PropertyName) - }; - - // 加入同步队列 - _synchronizationQueue.Enqueue(syncEvent); - - // 如果启用智能批量处理,检查是否需要立即处理 - if (_enableSmartBatching && ShouldProcessImmediately(syncEvent)) - { - ProcessSynchronizationBatch(null); - } - } - - /// - /// 处理同步批次 - /// - /// 定时器状态 - private void ProcessSynchronizationBatch(object state) - { - if (_isDisposed || _isProcessing) - return; - - lock (_processingLock) - { - if (_isProcessing) - return; - _isProcessing = true; - } - - try - { - var eventsToProcess = new List(); - var processedCount = 0; - - // 收集要处理的事件 - while (_synchronizationQueue.TryDequeue(out var syncEvent) && processedCount < _maxBatchSize) - { - if (syncEvent.SourceViewModel.IsAlive) - { - eventsToProcess.Add(syncEvent); - processedCount++; - } - } - - if (eventsToProcess.Count == 0) - return; - - using (_performanceMonitor.BeginCollectionUpdate(typeof(CrossViewModelSynchronizer), "BatchSync", eventsToProcess.Count)) - { - // 按优先级和依赖关系排序 - var sortedEvents = SortEventsByPriorityAndDependency(eventsToProcess); - - // 处理同步事件 - foreach (var syncEvent in sortedEvents) - { - ProcessSynchronizationEvent(syncEvent); - } - } - - LogManager.Debug($"批量同步完成: 处理{eventsToProcess.Count}个事件"); - } - catch (Exception ex) - { - LogManager.Error($"批量同步处理失败: {ex.Message}"); - } - finally - { - lock (_processingLock) - { - _isProcessing = false; - } - } - } - - /// - /// 处理单个同步事件 - /// - /// 同步事件 - private void ProcessSynchronizationEvent(SynchronizationEvent syncEvent) - { - try - { - var sourceViewModel = syncEvent.SourceViewModel.Target as ViewModelBase; - if (sourceViewModel == null) - return; - - var key = CreatePropertyKey(sourceViewModel, syncEvent.PropertyName); - if (!_subscriptions.TryGetValue(key, out var subscriptions)) - return; - - // 获取源属性值 - var sourceValue = GetPropertyValue(sourceViewModel, syncEvent.PropertyName); - - // 处理所有相关订阅 - var validSubscriptions = new List(); - - foreach (var subscription in subscriptions) - { - if (subscription.SourceViewModel.IsAlive && subscription.TargetViewModel.IsAlive) - { - validSubscriptions.Add(subscription); - } - } - - // 执行同步 - foreach (var subscription in validSubscriptions) - { - ExecuteSubscriptionSync(subscription, sourceValue); - } - - // 更新统计信息 - if (_viewModelRegistry.TryGetValue(sourceViewModel, out var metadata)) - { - metadata.LastSyncTime = DateTime.UtcNow; - metadata.SyncEventCount++; - } - } - catch (Exception ex) - { - LogManager.Error($"处理同步事件失败: {ex.Message}"); - } - } - - /// - /// 执行订阅同步 - /// - /// 订阅信息 - /// 源值 - private void ExecuteSubscriptionSync(SynchronizationSubscription subscription, object sourceValue) - { - try - { - var targetViewModel = subscription.TargetViewModel.Target as ViewModelBase; - if (targetViewModel == null) - return; - - // 应用转换器 - var targetValue = sourceValue; - if (subscription.Converter != null) - { - targetValue = subscription.Converter(sourceValue); - } - - // 检查是否需要更新 - if (subscription.Options.ValidateBeforeSync) - { - var currentTargetValue = GetPropertyValue(targetViewModel, subscription.TargetProperty); - if (Equals(currentTargetValue, targetValue)) - return; // 值相同,跳过更新 - } - - // 设置目标属性值 - SetPropertyValue(targetViewModel, subscription.TargetProperty, targetValue); - - // 更新订阅统计 - subscription.LastSyncTime = DateTime.UtcNow; - subscription.SyncCount++; - - LogManager.Debug($"属性同步完成: {subscription.SourceProperty} -> {subscription.TargetProperty}"); - } - catch (Exception ex) - { - LogManager.Error($"执行订阅同步失败: {ex.Message}"); - } - } - - #endregion - - #region 辅助方法 - - /// - /// 创建属性键 - /// - /// ViewModel - /// 属性名 - /// 属性键 - private string CreatePropertyKey(ViewModelBase viewModel, string propertyName) - { - return $"{viewModel.GetHashCode()}_{propertyName}"; - } - - /// - /// 获取属性名从表达式 - /// - /// 类型 - /// 属性表达式 - /// 属性名 - private string GetPropertyName(System.Linq.Expressions.Expression> expression) - { - if (expression.Body is System.Linq.Expressions.MemberExpression memberExpression) - { - return memberExpression.Member.Name; - } - if (expression.Body is System.Linq.Expressions.UnaryExpression unaryExpression && - unaryExpression.Operand is System.Linq.Expressions.MemberExpression memberExpr) - { - return memberExpr.Member.Name; - } - throw new ArgumentException("表达式必须是属性访问器"); - } - - /// - /// 获取属性值 - /// - /// ViewModel - /// 属性名 - /// 属性值 - private object GetPropertyValue(ViewModelBase viewModel, string propertyName) - { - try - { - var propertyInfo = viewModel.GetType().GetProperty(propertyName); - return propertyInfo?.GetValue(viewModel); - } - catch (Exception ex) - { - LogManager.Error($"获取属性值失败 {propertyName}: {ex.Message}"); - return null; - } - } - - /// - /// 设置属性值 - /// - /// ViewModel - /// 属性名 - /// 值 - private void SetPropertyValue(ViewModelBase viewModel, string propertyName, object value) - { - try - { - var propertyInfo = viewModel.GetType().GetProperty(propertyName); - if (propertyInfo != null && propertyInfo.CanWrite) - { - propertyInfo.SetValue(viewModel, value); - } - } - catch (Exception ex) - { - LogManager.Error($"设置属性值失败 {propertyName}: {ex.Message}"); - } - } - - /// - /// 获取事件优先级 - /// - /// ViewModel - /// 属性名 - /// 优先级 - private SyncEventPriority GetEventPriority(ViewModelBase viewModel, string propertyName) - { - if (_viewModelRegistry.TryGetValue(viewModel, out var metadata)) - { - if (metadata.Options.HighPriorityProperties?.Contains(propertyName) == true) - return SyncEventPriority.High; - if (metadata.Options.LowPriorityProperties?.Contains(propertyName) == true) - return SyncEventPriority.Low; - } - return SyncEventPriority.Normal; - } - - /// - /// 判断是否应该立即处理事件 - /// - /// 同步事件 - /// 是否立即处理 - private bool ShouldProcessImmediately(SynchronizationEvent syncEvent) - { - return syncEvent.Priority == SyncEventPriority.High || _synchronizationQueue.Count > _maxBatchSize; - } - - /// - /// 按优先级和依赖关系排序事件 - /// - /// 事件列表 - /// 排序后的事件 - private List SortEventsByPriorityAndDependency(List events) - { - // 简单按优先级排序,复杂的依赖排序可以在后续版本中实现 - return events.OrderByDescending(e => e.Priority).ToList(); - } - - #endregion - - #region 统计和诊断 - - /// - /// 获取同步器统计信息 - /// - /// 统计信息 - public SynchronizerStatistics GetStatistics() - { - var totalSyncEvents = _viewModelRegistry.Values.Sum(m => m.SyncEventCount); - var avgSyncEventsPerViewModel = _viewModelRegistry.Count > 0 ? (double)totalSyncEvents / _viewModelRegistry.Count : 0; - - return new SynchronizerStatistics - { - RegisteredViewModelsCount = RegisteredViewModelsCount, - TotalSubscriptionsCount = TotalSubscriptionsCount, - PendingSynchronizationCount = PendingSynchronizationCount, - TotalSyncEvents = totalSyncEvents, - AverageSyncEventsPerViewModel = avgSyncEventsPerViewModel, - BatchProcessingInterval = _batchProcessingInterval, - MaxBatchSize = _maxBatchSize, - EnableSmartBatching = _enableSmartBatching, - EnableDependencyTracking = _enableDependencyTracking - }; - } - - /// - /// 生成同步诊断报告 - /// - /// 诊断报告 - public string GenerateDiagnosticReport() - { - var stats = GetStatistics(); - var report = new System.Text.StringBuilder(); - - report.AppendLine("=== 跨ViewModel数据同步诊断报告 ==="); - report.AppendLine($"报告时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}"); - report.AppendLine(); - - report.AppendLine("注册统计:"); - report.AppendLine($" 注册ViewModel数: {stats.RegisteredViewModelsCount}"); - report.AppendLine($" 总订阅数: {stats.TotalSubscriptionsCount}"); - report.AppendLine($" 等待同步事件: {stats.PendingSynchronizationCount}"); - report.AppendLine(); - - report.AppendLine("性能统计:"); - report.AppendLine($" 总同步事件: {stats.TotalSyncEvents:N0}"); - report.AppendLine($" 平均每ViewModel事件数: {stats.AverageSyncEventsPerViewModel:F2}"); - report.AppendLine(); - - report.AppendLine("配置信息:"); - report.AppendLine($" 批量处理间隔: {stats.BatchProcessingInterval.TotalMilliseconds}ms"); - report.AppendLine($" 最大批量大小: {stats.MaxBatchSize}"); - report.AppendLine($" 智能批量处理: {(stats.EnableSmartBatching ? "启用" : "禁用")}"); - report.AppendLine($" 依赖追踪: {(stats.EnableDependencyTracking ? "启用" : "禁用")}"); - report.AppendLine(); - - // 详细的ViewModel信息 - if (_viewModelRegistry.Count > 0) - { - report.AppendLine("ViewModel详情:"); - foreach (var kvp in _viewModelRegistry) - { - var metadata = kvp.Value; - var timeSinceRegistration = DateTime.UtcNow - metadata.RegistrationTime; - var timeSinceLastSync = DateTime.UtcNow - metadata.LastSyncTime; - - report.AppendLine($" {kvp.Key.GetType().Name}:"); - report.AppendLine($" 注册时间: {timeSinceRegistration.TotalMinutes:F1}分钟前"); - report.AppendLine($" 最后同步: {timeSinceLastSync.TotalSeconds:F1}秒前"); - report.AppendLine($" 同步事件数: {metadata.SyncEventCount}"); - } - } - - return report.ToString(); - } - - /// - /// 强制刷新所有等待的同步事件 - /// - public void FlushPendingSynchronizations() - { - ProcessSynchronizationBatch(null); - } - - #endregion - - #region IDisposable实现 - - public void Dispose() - { - if (_isDisposed) - return; - - _isDisposed = true; - - _batchProcessingTimer?.Dispose(); - - // 清理所有注册的ViewModel - var registeredViewModels = _viewModelRegistry.Keys.ToList(); - foreach (var viewModel in registeredViewModels) - { - UnregisterViewModel(viewModel); - } - - _subscriptions.Clear(); - _viewModelRegistry.Clear(); - _propertyDependencies.Clear(); - _viewModelDependencies.Clear(); - - while (_synchronizationQueue.TryDequeue(out _)) { } - - LogManager.Info("跨ViewModel数据同步器已释放"); - } - - #endregion - } - - #region 辅助类和枚举 - - /// - /// ViewModel同步选项 - /// - public class ViewModelSyncOptions - { - /// - /// 需要追踪的属性 - /// - public string[] TrackedProperties { get; set; } - - /// - /// 高优先级属性 - /// - public string[] HighPriorityProperties { get; set; } - - /// - /// 低优先级属性 - /// - public string[] LowPriorityProperties { get; set; } - - /// - /// 是否启用批量同步 - /// - public bool EnableBatchSync { get; set; } = true; - - /// - /// 默认选项 - /// - public static ViewModelSyncOptions Default => new ViewModelSyncOptions(); - } - - /// - /// 订阅选项 - /// - public class SubscriptionOptions - { - /// - /// 同步前验证值是否相同 - /// - public bool ValidateBeforeSync { get; set; } = true; - - /// - /// 是否启用双向同步 - /// - public bool EnableTwoWaySync { get; set; } = false; - - /// - /// 同步延迟(毫秒) - /// - public int SyncDelayMs { get; set; } = 0; - - /// - /// 默认选项 - /// - public static SubscriptionOptions Default => new SubscriptionOptions(); - } - - /// - /// ViewModel元数据 - /// - internal class ViewModelMetadata - { - public ViewModelBase ViewModel { get; set; } - public ViewModelSyncOptions Options { get; set; } - public DateTime RegistrationTime { get; set; } - public DateTime LastSyncTime { get; set; } - public long SyncEventCount { get; set; } - } - - /// - /// 同步订阅信息 - /// - internal class SynchronizationSubscription - { - public string Id { get; set; } - public WeakReference SourceViewModel { get; set; } - public string SourceProperty { get; set; } - public WeakReference TargetViewModel { get; set; } - public string TargetProperty { get; set; } - public Func Converter { get; set; } - public SubscriptionOptions Options { get; set; } - public DateTime CreatedTime { get; set; } - public DateTime LastSyncTime { get; set; } - public long SyncCount { get; set; } - } - - /// - /// 同步事件 - /// - internal class SynchronizationEvent - { - public string Id { get; set; } - public WeakReference SourceViewModel { get; set; } - public string PropertyName { get; set; } - public DateTime Timestamp { get; set; } - public SyncEventPriority Priority { get; set; } - } - - /// - /// 同步事件优先级 - /// - public enum SyncEventPriority - { - Low = 0, - Normal = 1, - High = 2, - Critical = 3 - } - - /// - /// 同步器统计信息 - /// - public class SynchronizerStatistics - { - public int RegisteredViewModelsCount { get; set; } - public int TotalSubscriptionsCount { get; set; } - public int PendingSynchronizationCount { get; set; } - public long TotalSyncEvents { get; set; } - public double AverageSyncEventsPerViewModel { get; set; } - public TimeSpan BatchProcessingInterval { get; set; } - public int MaxBatchSize { get; set; } - public bool EnableSmartBatching { get; set; } - public bool EnableDependencyTracking { get; set; } - } - - #endregion -} \ No newline at end of file diff --git a/src/UI/WPF/Services/DataBindingBestPractices.cs b/src/UI/WPF/Services/DataBindingBestPractices.cs deleted file mode 100644 index 7b11593..0000000 --- a/src/UI/WPF/Services/DataBindingBestPractices.cs +++ /dev/null @@ -1,964 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Windows.Data; -using NavisworksTransport.UI.WPF.ViewModels; -using NavisworksTransport.UI.WPF.Collections; -using NavisworksTransport.Utils; - -namespace NavisworksTransport.UI.WPF.Services -{ - /// - /// 数据绑定最佳实践指南和验证工具 - /// 提供数据绑定性能优化的最佳实践指导和自动化验证 - /// - public static class DataBindingBestPractices - { - #region 最佳实践规则定义 - - /// - /// 最佳实践规则集合 - /// - public static readonly List Rules = new List - { - // ViewModel相关规则 - new BestPracticeRule - { - Id = "VM01", - Category = BestPracticeCategory.ViewModel, - Title = "继承ViewModelBase基类", - Description = "所有ViewModel应继承ViewModelBase以获得线程安全和性能优化功能", - Severity = RuleSeverity.Error, - CheckAction = CheckViewModelBaseInheritance - }, - - new BestPracticeRule - { - Id = "VM02", - Category = BestPracticeCategory.ViewModel, - Title = "使用智能属性设置方法", - Description = "使用SetPropertySmart方法替代传统SetProperty以获得更好的性能", - Severity = RuleSeverity.Warning, - CheckAction = CheckSmartPropertyUsage - }, - - new BestPracticeRule - { - Id = "VM03", - Category = BestPracticeCategory.ViewModel, - Title = "启用性能监控", - Description = "在开发和测试阶段启用性能监控以识别性能瓶颈", - Severity = RuleSeverity.Information, - CheckAction = CheckPerformanceMonitoring - }, - - new BestPracticeRule - { - Id = "VM04", - Category = BestPracticeCategory.ViewModel, - Title = "避免频繁属性更新", - Description = "对于频繁更新的属性,使用延迟更新或批量更新机制", - Severity = RuleSeverity.Warning, - CheckAction = CheckFrequentPropertyUpdates - }, - - // 集合相关规则 - new BestPracticeRule - { - Id = "COL01", - Category = BestPracticeCategory.Collections, - Title = "使用线程安全集合", - Description = "在多线程环境中使用ThreadSafeObservableCollection而不是ObservableCollection", - Severity = RuleSeverity.Error, - CheckAction = CheckThreadSafeCollections - }, - - new BestPracticeRule - { - Id = "COL02", - Category = BestPracticeCategory.Collections, - Title = "大集合使用虚拟化", - Description = "超过1000项的集合应使用VirtualizedObservableCollection", - Severity = RuleSeverity.Warning, - CheckAction = CheckVirtualizationUsage - }, - - new BestPracticeRule - { - Id = "COL03", - Category = BestPracticeCategory.Collections, - Title = "使用批量操作", - Description = "集合的批量添加/删除应使用AddRange/RemoveRange方法", - Severity = RuleSeverity.Information, - CheckAction = CheckBatchOperations - }, - - // 绑定相关规则 - new BestPracticeRule - { - Id = "BIND01", - Category = BestPracticeCategory.Binding, - Title = "优化绑定表达式", - Description = "复杂的绑定表达式应注册到BindingExpressionOptimizer", - Severity = RuleSeverity.Warning, - CheckAction = CheckBindingOptimization - }, - - new BestPracticeRule - { - Id = "BIND02", - Category = BestPracticeCategory.Binding, - Title = "避免双向绑定过度使用", - Description = "只在必要时使用双向绑定,优先使用单向绑定", - Severity = RuleSeverity.Information, - CheckAction = CheckTwoWayBindingUsage - }, - - new BestPracticeRule - { - Id = "BIND03", - Category = BestPracticeCategory.Binding, - Title = "使用绑定缓存", - Description = "重复计算的绑定值应启用缓存机制", - Severity = RuleSeverity.Information, - CheckAction = CheckBindingCaching - }, - - // 同步相关规则 - new BestPracticeRule - { - Id = "SYNC01", - Category = BestPracticeCategory.Synchronization, - Title = "注册跨ViewModel同步", - Description = "需要数据同步的ViewModel应注册到CrossViewModelSynchronizer", - Severity = RuleSeverity.Warning, - CheckAction = CheckCrossViewModelSync - }, - - new BestPracticeRule - { - Id = "SYNC02", - Category = BestPracticeCategory.Synchronization, - Title = "避免循环依赖", - Description = "检查并避免ViewModel之间的循环依赖关系", - Severity = RuleSeverity.Error, - CheckAction = CheckCircularDependencies - }, - - // 内存相关规则 - new BestPracticeRule - { - Id = "MEM01", - Category = BestPracticeCategory.Memory, - Title = "及时清理事件订阅", - Description = "ViewModel释放时应正确清理事件订阅以避免内存泄漏", - Severity = RuleSeverity.Error, - CheckAction = CheckEventSubscriptionCleanup - }, - - new BestPracticeRule - { - Id = "MEM02", - Category = BestPracticeCategory.Memory, - Title = "控制缓存大小", - Description = "各种缓存的大小应根据应用需求进行合理配置", - Severity = RuleSeverity.Information, - CheckAction = CheckCacheConfiguration - } - }; - - #endregion - - #region 规则检查实现 - - /// - /// 检查ViewModel是否继承ViewModelBase - /// - private static BestPracticeViolation CheckViewModelBaseInheritance(object context) - { - if (context is ViewModelBase) - { - return null; // 合规 - } - - if (context is INotifyPropertyChanged viewModel) - { - return new BestPracticeViolation - { - RuleId = "VM01", - Message = $"ViewModel {viewModel.GetType().Name} 应继承 ViewModelBase 基类", - Recommendation = "修改类定义:public class MyViewModel : ViewModelBase", - Context = context - }; - } - - return null; - } - - /// - /// 检查是否使用智能属性设置 - /// - private static BestPracticeViolation CheckSmartPropertyUsage(object context) - { - // 这里可以通过反射或代码分析来检查 - // 为了简化,返回建议性信息 - if (context is ViewModelBase viewModel) - { - return new BestPracticeViolation - { - RuleId = "VM02", - Message = "建议使用 SetPropertySmart 方法以获得更好的性能", - Recommendation = "使用 SetPropertySmart(ref _field, value, PropertyUpdateMode.Delayed)", - Context = context, - Severity = RuleSeverity.Information - }; - } - - return null; - } - - /// - /// 检查性能监控是否启用 - /// - private static BestPracticeViolation CheckPerformanceMonitoring(object context) - { - var monitor = DataBindingPerformanceMonitor.Instance; - if (!monitor.IsMonitoringEnabled) - { - return new BestPracticeViolation - { - RuleId = "VM03", - Message = "性能监控未启用,建议在开发阶段启用以识别性能问题", - Recommendation = "调用 DataBindingPerformanceMonitor.Instance.IsMonitoringEnabled = true", - Context = context, - Severity = RuleSeverity.Information - }; - } - - return null; - } - - /// - /// 检查频繁属性更新 - /// - private static BestPracticeViolation CheckFrequentPropertyUpdates(object context) - { - // 通过性能监控数据检查 - var monitor = DataBindingPerformanceMonitor.Instance; - var overview = monitor.GetPerformanceOverview(); - - if (overview.TotalSlowUpdates > overview.TotalPropertyUpdates * 0.1) // 超过10%的慢更新 - { - return new BestPracticeViolation - { - RuleId = "VM04", - Message = $"检测到较多的慢属性更新 ({overview.TotalSlowUpdates} / {overview.TotalPropertyUpdates})", - Recommendation = "考虑使用延迟更新或批量更新机制", - Context = context, - Severity = RuleSeverity.Warning - }; - } - - return null; - } - - /// - /// 检查线程安全集合使用 - /// - private static BestPracticeViolation CheckThreadSafeCollections(object context) - { - if (context is System.Collections.ObjectModel.ObservableCollection collection && - !(collection is ThreadSafeObservableCollection)) - { - return new BestPracticeViolation - { - RuleId = "COL01", - Message = "在多线程环境中应使用 ThreadSafeObservableCollection", - Recommendation = "替换为: new ThreadSafeObservableCollection()", - Context = context, - Severity = RuleSeverity.Error - }; - } - - return null; - } - - /// - /// 检查虚拟化集合使用 - /// - private static BestPracticeViolation CheckVirtualizationUsage(object context) - { - if (context is System.Collections.ICollection collection && collection.Count > 1000) - { - if (!(collection is VirtualizedObservableCollection)) - { - return new BestPracticeViolation - { - RuleId = "COL02", - Message = $"大集合 ({collection.Count} 项) 建议使用虚拟化", - Recommendation = "使用 VirtualizedObservableCollection 以提高性能", - Context = context, - Severity = RuleSeverity.Warning - }; - } - } - - return null; - } - - /// - /// 检查批量操作使用 - /// - private static BestPracticeViolation CheckBatchOperations(object context) - { - // 这里可以通过方法调用分析来检查 - // 为简化,返回建议信息 - return new BestPracticeViolation - { - RuleId = "COL03", - Message = "建议使用批量操作方法提高集合操作性能", - Recommendation = "使用 AddRange() / RemoveRange() 而不是循环调用 Add() / Remove()", - Context = context, - Severity = RuleSeverity.Information - }; - } - - /// - /// 检查绑定优化 - /// - private static BestPracticeViolation CheckBindingOptimization(object context) - { - var optimizer = BindingExpressionOptimizer.Instance; - var stats = optimizer.GetStatistics(); - - if (stats.RegisteredBindingsCount == 0) - { - return new BestPracticeViolation - { - RuleId = "BIND01", - Message = "没有注册绑定优化,复杂绑定可能存在性能问题", - Recommendation = "使用 BindingExpressionOptimizer.OptimizeBinding() 注册复杂绑定", - Context = context, - Severity = RuleSeverity.Information - }; - } - - return null; - } - - /// - /// 检查双向绑定使用 - /// - private static BestPracticeViolation CheckTwoWayBindingUsage(object context) - { - // 静态分析检查,这里返回建议 - return new BestPracticeViolation - { - RuleId = "BIND02", - Message = "检查双向绑定的必要性", - Recommendation = "只在必要时使用 Mode=TwoWay,优先使用 Mode=OneWay", - Context = context, - Severity = RuleSeverity.Information - }; - } - - /// - /// 检查绑定缓存 - /// - private static BestPracticeViolation CheckBindingCaching(object context) - { - var optimizer = BindingExpressionOptimizer.Instance; - if (!optimizer.EnableBindingCaching) - { - return new BestPracticeViolation - { - RuleId = "BIND03", - Message = "绑定缓存未启用", - Recommendation = "启用绑定缓存: BindingExpressionOptimizer.Instance.EnableBindingCaching = true", - Context = context, - Severity = RuleSeverity.Information - }; - } - - return null; - } - - /// - /// 检查跨ViewModel同步 - /// - private static BestPracticeViolation CheckCrossViewModelSync(object context) - { - var synchronizer = CrossViewModelSynchronizer.Instance; - var stats = synchronizer.GetStatistics(); - - if (stats.RegisteredViewModelsCount == 0) - { - return new BestPracticeViolation - { - RuleId = "SYNC01", - Message = "没有注册ViewModel同步,可能存在数据一致性问题", - Recommendation = "使用 CrossViewModelSynchronizer.RegisterViewModel() 注册需要同步的ViewModel", - Context = context, - Severity = RuleSeverity.Information - }; - } - - return null; - } - - /// - /// 检查循环依赖 - /// - private static BestPracticeViolation CheckCircularDependencies(object context) - { - if (context is ViewModelBase viewModel) - { - var synchronizer = CrossViewModelSynchronizer.Instance; - - // 检查是否存在循环依赖(简化检查) - try - { - // 这里可以实现更复杂的循环依赖检测逻辑 - var dependencies = synchronizer.GetPropertyDependencies(viewModel, "*"); - if (dependencies.Any()) - { - return new BestPracticeViolation - { - RuleId = "SYNC02", - Message = "检测到可能的循环依赖", - Recommendation = "检查ViewModel之间的依赖关系,避免循环引用", - Context = context, - Severity = RuleSeverity.Warning - }; - } - } - catch - { - // 检查失败,忽略 - } - } - - return null; - } - - /// - /// 检查事件订阅清理 - /// - private static BestPracticeViolation CheckEventSubscriptionCleanup(object context) - { - if (context is IDisposable) - { - return null; // 实现了IDisposable,假设会正确清理 - } - - if (context is ViewModelBase) - { - return new BestPracticeViolation - { - RuleId = "MEM01", - Message = "ViewModel应实现IDisposable以正确清理资源", - Recommendation = "实现IDisposable接口并在Dispose中清理事件订阅", - Context = context, - Severity = RuleSeverity.Warning - }; - } - - return null; - } - - /// - /// 检查缓存配置 - /// - private static BestPracticeViolation CheckCacheConfiguration(object context) - { - var monitor = DataBindingPerformanceMonitor.Instance; - var bindingOptimizer = BindingExpressionOptimizer.Instance; - - if (bindingOptimizer.MaxCacheSize < 100) - { - return new BestPracticeViolation - { - RuleId = "MEM02", - Message = "绑定缓存大小可能过小", - Recommendation = "考虑增加缓存大小以提高性能", - Context = context, - Severity = RuleSeverity.Information - }; - } - - return null; - } - - #endregion - - #region 验证和报告 - - /// - /// 验证对象的数据绑定最佳实践合规性 - /// - /// 要验证的对象 - /// 要检查的规则类别 - /// 违规列表 - public static List ValidateObject(object context, params BestPracticeCategory[] categories) - { - var violations = new List(); - - if (context == null) - return violations; - - var categoriesToCheck = categories?.Length > 0 ? categories : (BestPracticeCategory[])Enum.GetValues(typeof(BestPracticeCategory)); - - foreach (var rule in Rules) - { - if (System.Linq.Enumerable.Contains(categoriesToCheck, rule.Category)) - { - try - { - var violation = rule.CheckAction?.Invoke(context); - if (violation != null) - { - violations.Add(violation); - } - } - catch (Exception ex) - { - LogManager.Error($"规则检查失败 {rule.Id}: {ex.Message}"); - } - } - } - - return violations; - } - - /// - /// 验证ViewModel的数据绑定最佳实践 - /// - /// 要验证的ViewModel - /// 验证报告 - public static BestPracticeReport ValidateViewModel(ViewModelBase viewModel) - { - var violations = ValidateObject(viewModel); - - return new BestPracticeReport - { - TargetObject = viewModel, - TargetType = viewModel.GetType(), - ValidationTime = DateTime.UtcNow, - Violations = violations, - OverallScore = CalculateScore(violations) - }; - } - - /// - /// 验证整个应用的数据绑定最佳实践 - /// - /// 要验证的ViewModel集合 - /// 应用验证报告 - public static ApplicationBestPracticeReport ValidateApplication(IEnumerable viewModels) - { - var reports = new List(); - var allViolations = new List(); - - foreach (var viewModel in viewModels) - { - var report = ValidateViewModel(viewModel); - reports.Add(report); - allViolations.AddRange(report.Violations); - } - - // 添加系统级检查 - var systemViolations = ValidateSystemConfiguration(); - allViolations.AddRange(systemViolations); - - return new ApplicationBestPracticeReport - { - ValidationTime = DateTime.UtcNow, - ViewModelReports = reports, - SystemViolations = systemViolations, - AllViolations = allViolations, - OverallScore = CalculateScore(allViolations), - Summary = GenerateViolationSummary(allViolations) - }; - } - - /// - /// 验证系统配置 - /// - /// 系统级违规列表 - private static List ValidateSystemConfiguration() - { - var violations = new List(); - - // 检查性能监控 - violations.AddRange(ValidateObject("system_performance")); - - // 检查绑定优化器 - violations.AddRange(ValidateObject("system_binding")); - - // 检查同步器 - violations.AddRange(ValidateObject("system_sync")); - - return violations.Where(v => v != null).ToList(); - } - - /// - /// 计算合规性评分 - /// - /// 违规列表 - /// 评分 (0-100) - private static int CalculateScore(List violations) - { - if (violations.Count == 0) - return 100; - - var errorCount = violations.Count(v => v.Severity == RuleSeverity.Error); - var warningCount = violations.Count(v => v.Severity == RuleSeverity.Warning); - var infoCount = violations.Count(v => v.Severity == RuleSeverity.Information); - - // 错误-30分,警告-10分,信息-2分 - var deduction = errorCount * 30 + warningCount * 10 + infoCount * 2; - - return Math.Max(0, 100 - deduction); - } - - /// - /// 生成违规汇总 - /// - /// 违规列表 - /// 汇总信息 - private static ViolationSummary GenerateViolationSummary(List violations) - { - var summary = new ViolationSummary(); - - foreach (BestPracticeCategory category in Enum.GetValues(typeof(BestPracticeCategory))) - { - var categoryViolations = violations.Where(v => - Rules.FirstOrDefault(r => r.Id == v.RuleId)?.Category == (BestPracticeCategory)category).ToList(); - - summary.ByCategory[category] = new CategorySummary - { - TotalCount = categoryViolations.Count, - ErrorCount = categoryViolations.Count(v => v.Severity == RuleSeverity.Error), - WarningCount = categoryViolations.Count(v => v.Severity == RuleSeverity.Warning), - InfoCount = categoryViolations.Count(v => v.Severity == RuleSeverity.Information) - }; - } - - summary.TotalViolations = violations.Count; - summary.MostCommonViolations = violations - .GroupBy(v => v.RuleId) - .OrderByDescending(g => g.Count()) - .Take(5) - .ToDictionary(g => g.Key, g => g.Count()); - - return summary; - } - - /// - /// 生成最佳实践报告文档 - /// - /// 验证报告 - /// 报告文档 - public static string GenerateReportDocument(ApplicationBestPracticeReport report) - { - var doc = new StringBuilder(); - - doc.AppendLine("# 数据绑定最佳实践验证报告"); - doc.AppendLine($"生成时间: {report.ValidationTime:yyyy-MM-dd HH:mm:ss}"); - doc.AppendLine($"总体评分: {report.OverallScore}/100"); - doc.AppendLine(); - - // 执行摘要 - doc.AppendLine("## 执行摘要"); - doc.AppendLine($"- 验证的ViewModel数量: {report.ViewModelReports.Count}"); - doc.AppendLine($"- 发现的问题总数: {report.AllViolations.Count}"); - doc.AppendLine($"- 错误: {report.Summary.ByCategory.Values.Sum(c => c.ErrorCount)}"); - doc.AppendLine($"- 警告: {report.Summary.ByCategory.Values.Sum(c => c.WarningCount)}"); - doc.AppendLine($"- 信息: {report.Summary.ByCategory.Values.Sum(c => c.InfoCount)}"); - doc.AppendLine(); - - // 按类别分组的问题 - doc.AppendLine("## 问题分类统计"); - foreach (var kvp in report.Summary.ByCategory) - { - if (kvp.Value.TotalCount > 0) - { - doc.AppendLine($"### {kvp.Key}"); - doc.AppendLine($"- 总计: {kvp.Value.TotalCount}"); - doc.AppendLine($"- 错误: {kvp.Value.ErrorCount}"); - doc.AppendLine($"- 警告: {kvp.Value.WarningCount}"); - doc.AppendLine($"- 信息: {kvp.Value.InfoCount}"); - doc.AppendLine(); - } - } - - // 最常见问题 - doc.AppendLine("## 最常见问题"); - foreach (var kvp in report.Summary.MostCommonViolations) - { - var rule = Rules.FirstOrDefault(r => r.Id == kvp.Key); - if (rule != null) - { - doc.AppendLine($"- **{rule.Title}** ({kvp.Key}): {kvp.Value}次"); - doc.AppendLine($" {rule.Description}"); - doc.AppendLine(); - } - } - - // 详细问题列表 - doc.AppendLine("## 详细问题列表"); - var violationsByViewModel = report.ViewModelReports - .Where(r => r.Violations.Count > 0) - .OrderByDescending(r => r.Violations.Count); - - foreach (var vmReport in violationsByViewModel) - { - doc.AppendLine($"### {vmReport.TargetType.Name}"); - doc.AppendLine($"评分: {vmReport.OverallScore}/100"); - doc.AppendLine(); - - foreach (var violation in vmReport.Violations.OrderByDescending(v => v.Severity)) - { - var severityIcon = ""; - switch (violation.Severity) - { - case RuleSeverity.Error: - severityIcon = "❌"; - break; - case RuleSeverity.Warning: - severityIcon = "⚠️"; - break; - case RuleSeverity.Information: - severityIcon = "ℹ️"; - break; - default: - severityIcon = "•"; - break; - } - - doc.AppendLine($"{severityIcon} **{violation.RuleId}**: {violation.Message}"); - doc.AppendLine($" 💡 建议: {violation.Recommendation}"); - doc.AppendLine(); - } - } - - // 优化建议 - doc.AppendLine("## 优化建议"); - doc.AppendLine(GenerateOptimizationRecommendations(report)); - - return doc.ToString(); - } - - /// - /// 生成优化建议 - /// - /// 验证报告 - /// 优化建议 - private static string GenerateOptimizationRecommendations(ApplicationBestPracticeReport report) - { - var recommendations = new StringBuilder(); - - // 基于违规情况生成针对性建议 - var errorCount = report.AllViolations.Count(v => v.Severity == RuleSeverity.Error); - var warningCount = report.AllViolations.Count(v => v.Severity == RuleSeverity.Warning); - - if (errorCount > 0) - { - recommendations.AppendLine("### 高优先级 (必须修复)"); - recommendations.AppendLine("1. 修复所有错误级别的问题,这些问题可能导致运行时错误或严重的性能问题"); - recommendations.AppendLine("2. 确保所有ViewModel继承ViewModelBase基类"); - recommendations.AppendLine("3. 使用线程安全的集合类型"); - recommendations.AppendLine(); - } - - if (warningCount > 0) - { - recommendations.AppendLine("### 中等优先级 (建议修复)"); - recommendations.AppendLine("1. 解决警告级别的问题以提高应用性能"); - recommendations.AppendLine("2. 对大集合启用虚拟化"); - recommendations.AppendLine("3. 优化频繁更新的属性"); - recommendations.AppendLine(); - } - - recommendations.AppendLine("### 一般建议"); - recommendations.AppendLine("1. 在开发阶段启用性能监控以及时发现问题"); - recommendations.AppendLine("2. 定期运行最佳实践验证"); - recommendations.AppendLine("3. 建立代码审查流程确保新代码符合最佳实践"); - recommendations.AppendLine("4. 为团队成员提供数据绑定最佳实践培训"); - - return recommendations.ToString(); - } - - #endregion - - #region 自动修复建议 - - /// - /// 获取自动修复建议 - /// - /// 违规项 - /// 修复建议 - public static AutoFixSuggestion GetAutoFixSuggestion(BestPracticeViolation violation) - { - switch (violation.RuleId) - { - case "VM01": - return new AutoFixSuggestion - { - CanAutoFix = false, - Description = "需要手动修改类继承关系", - Steps = new[] - { - "1. 添加using NavisworksTransport.UI.WPF.ViewModels;", - "2. 修改类定义: public class MyViewModel : ViewModelBase", - "3. 移除手动实现的INotifyPropertyChanged相关代码" - } - }; - - case "COL01": - return new AutoFixSuggestion - { - CanAutoFix = true, - Description = "可以自动替换为线程安全集合", - Steps = new[] - { - "1. 替换ObservableCollection为ThreadSafeObservableCollection", - "2. 添加using NavisworksTransport.UI.WPF.Collections;" - } - }; - - case "COL02": - return new AutoFixSuggestion - { - CanAutoFix = true, - Description = "可以自动替换为虚拟化集合", - Steps = new[] - { - "1. 替换为VirtualizedObservableCollection", - "2. 实现IVirtualDataProvider接口" - } - }; - - default: - return new AutoFixSuggestion - { - CanAutoFix = false, - Description = "需要手动修复", - Steps = new[] { violation.Recommendation } - }; - } - } - - #endregion - } - - #region 数据结构定义 - - /// - /// 最佳实践规则 - /// - public class BestPracticeRule - { - public string Id { get; set; } - public BestPracticeCategory Category { get; set; } - public string Title { get; set; } - public string Description { get; set; } - public RuleSeverity Severity { get; set; } - public Func CheckAction { get; set; } - } - - /// - /// 最佳实践违规 - /// - public class BestPracticeViolation - { - public string RuleId { get; set; } - public string Message { get; set; } - public string Recommendation { get; set; } - public RuleSeverity Severity { get; set; } - public object Context { get; set; } - } - - /// - /// 最佳实践报告 - /// - public class BestPracticeReport - { - public object TargetObject { get; set; } - public Type TargetType { get; set; } - public DateTime ValidationTime { get; set; } - public List Violations { get; set; } = new List(); - public int OverallScore { get; set; } - } - - /// - /// 应用最佳实践报告 - /// - public class ApplicationBestPracticeReport - { - public DateTime ValidationTime { get; set; } - public List ViewModelReports { get; set; } = new List(); - public List SystemViolations { get; set; } = new List(); - public List AllViolations { get; set; } = new List(); - public int OverallScore { get; set; } - public ViolationSummary Summary { get; set; } - } - - /// - /// 违规汇总 - /// - public class ViolationSummary - { - public Dictionary ByCategory { get; set; } = new Dictionary(); - public int TotalViolations { get; set; } - public Dictionary MostCommonViolations { get; set; } = new Dictionary(); - } - - /// - /// 类别汇总 - /// - public class CategorySummary - { - public int TotalCount { get; set; } - public int ErrorCount { get; set; } - public int WarningCount { get; set; } - public int InfoCount { get; set; } - } - - /// - /// 自动修复建议 - /// - public class AutoFixSuggestion - { - public bool CanAutoFix { get; set; } - public string Description { get; set; } - public string[] Steps { get; set; } - } - - /// - /// 最佳实践类别 - /// - public enum BestPracticeCategory - { - ViewModel, - Collections, - Binding, - Synchronization, - Memory, - Performance - } - - /// - /// 规则严重性 - /// - public enum RuleSeverity - { - Information = 0, - Warning = 1, - Error = 2 - } - - #endregion -} \ No newline at end of file