using DevExpress.XtraGrid.Views.Grid; using DevExpress.XtraTab; using Lskj.Control.ZKFinger; using Lskj.Util; using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Diagnostics; using System.Linq; using System.Text; using System.Windows.Forms; using Lskj.Model; using System.Reflection; using WinFormsControl = System.Windows.Forms.Control; namespace Lskj.Control.Model { public static class StaticControl { /// /// Releases static references owned by a closed legacy module. Cleanup is /// best-effort so it cannot change the module close result. /// public static void ReleaseModuleReferences(WinFormsControl moduleRoot, XtraTabPage modulePage, string moduleCode) { List gridViews = new List(); try { gridViews = CollectGridViews(moduleRoot); } catch (Exception exception) { TraceCleanupFailure("收集表格引用", exception); } try { foreach (GridView gridView in gridViews) { try { RemoveGridReferences(gridView); } catch (Exception exception) { TraceCleanupFailure("释放表格拖拽引用", exception); } } TryCleanup(() => RemoveConditionPanels(moduleCode), "释放条件面板引用"); TryCleanup(() => RemoveProtectedReferences(moduleRoot, modulePage), "释放权限保护引用"); TryCleanup(() => ClearRightMenuReferences(moduleRoot, gridViews), "释放右键菜单引用"); TryCleanup( () => StaticBandedControl.ReleaseModuleReferences(moduleRoot, modulePage, moduleCode), "释放带状表格引用"); } finally { // DynamicModel caches retain completed tasks, result tables and // their closures. Always release them after other references. TryCleanup(() => ClearDataCaches(moduleRoot), "释放动态数据缓存"); } } private static void TryCleanup(Action cleanup, string operation) { try { cleanup(); } catch (Exception exception) { TraceCleanupFailure(operation, exception); } } private static void TraceCleanupFailure(string operation, Exception exception) { Debug.WriteLine("释放旧模块引用失败[" + operation + "]:" + exception); } private static List CollectGridViews(WinFormsControl root) { List result = new List(); if (root == null) return result; foreach (WinFormsControl control in EnumerateControls(root)) { DevExpress.XtraGrid.GridControl grid = control as DevExpress.XtraGrid.GridControl; GridView view = grid == null ? null : grid.MainView as GridView; if (view != null && !result.Contains(view)) result.Add(view); } return result; } private static IEnumerable EnumerateControls(WinFormsControl root) { yield return root; foreach (WinFormsControl child in root.Controls) foreach (WinFormsControl nested in EnumerateControls(child)) yield return nested; } private static void RemoveGridReferences(GridView gridView) { GridDragGrid.DisposeRegistrations(GridViewDragGridDic, TargetViewDragGridDic, gridView); if (ReferenceEquals(SourceDragGridView, gridView) || (SourceDragGridView != null && SourceDragGridView.GridControl != null && SourceDragGridView.GridControl.IsDisposed)) SourceDragGridView = null; } private static void RemoveConditionPanels(string moduleCode) { foreach (string key in ConditionsPanelDic.Keys.ToList()) { ModuleConditionsPanelEx panel; if (string.Equals(key, moduleCode, StringComparison.OrdinalIgnoreCase) || !ConditionsPanelDic.TryGetValue(key, out panel) || panel == null || panel.IsDisposed) ConditionsPanelDic.Remove(key); } } private static void RemoveProtectedReferences(WinFormsControl root, XtraTabPage page) { while (page != null && DogVerifyModuleForms.Remove(page)) { } foreach (XtraTabPage item in DogVerifyModuleForms.ToList()) if (item == null || item.IsDisposed || IsContained(root, item)) DogVerifyModuleForms.Remove(item); foreach (IForm item in DogVerifyNoPageForms.ToList()) if (item == null || item.SubForm == null || item.SubForm.IsDisposed || IsContained(root, item.SubForm)) DogVerifyNoPageForms.Remove(item); } private static bool IsContained(WinFormsControl root, WinFormsControl value) { if (root == null || value == null) return false; if (ReferenceEquals(root, value)) return true; foreach (WinFormsControl child in root.Controls) if (IsContained(child, value)) return true; return false; } private static void ClearRightMenuReferences(WinFormsControl root, List gridViews) { if (_RightMenuGridView != null && (gridViews.Contains(_RightMenuGridView) || (_RightMenuGridView.GridControl != null && _RightMenuGridView.GridControl.IsDisposed))) RightMenuGridView = null; if (RightMenuMyControl != null && RightMenuMyControl.MainGridEx != null && (RightMenuMyControl.MainGridEx.IsDisposed || IsContained(root, RightMenuMyControl.MainGridEx))) RightMenuMyControl = null; if (BomUnionPage != null && (BomUnionPage.IsDisposed || IsContained(root, BomUnionPage))) BomUnionPage = null; if (AddParentGrid.Value != null && (AddParentGrid.Value.IsDisposed || IsContained(root, AddParentGrid.Value))) AddParentGrid = new KeyValuePair(); } private static void ClearDataCaches(WinFormsControl root) { if (root == null) return; // Clear the root first because child enumeration can fail while a // DevExpress control is disposing its child collection. ClearDynamicModels(root); try { foreach (WinFormsControl control in EnumerateControls(root).Skip(1).ToList()) ClearDynamicModels(control); } catch (Exception exception) { TraceCleanupFailure("遍历动态数据缓存", exception); } } private static void ClearDynamicModels(object instance) { if (instance == null) return; BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; for (Type type = instance.GetType(); type != null; type = type.BaseType) foreach (FieldInfo field in type.GetFields(flags | BindingFlags.DeclaredOnly)) try { ClearDynamicModel(field.GetValue(instance)); } catch (Exception exception) { Debug.WriteLine("清理动态缓存字段失败:" + exception); } } private static void ClearDynamicModel(object value) { DynamicModel model = value as DynamicModel; if (model == null || model.DataCaches == null) return; Dictionary caches = model.DataCaches; foreach (Hashtable cache in caches.Values.OfType().ToList()) { foreach (IDisposable item in cache.Values.OfType().ToList()) try { item.Dispose(); } catch { } cache.Clear(); } caches.Clear(); model.DataCaches = null; } /// /// 记录当前U盾权限窗口 /// public static List DogVerifyModuleForms = new List(); public static List DogVerifyNoPageForms = new List(); /// ///模块打开时的条件界面 /// public static Dictionary ConditionsPanelDic = new Dictionary(); /// /// 表格拖拽类,key值为源表 /// public static Dictionary> GridViewDragGridDic = new Dictionary>(); /// /// 表格拖拽类,key值为目标表 /// public static Dictionary> TargetViewDragGridDic = new Dictionary>(); /// /// 当前拖拽源表格 /// public static GridView SourceDragGridView; /// /// 指纹识别模块 /// public static FingerHelper fingerHelper; ///// ///// 外部exe进程 ///// //public static Dictionary loadExeProcess = new Dictionary(); /// /// 打开的Add模块对应的父表格控件(模块编号,GridControlEx) /// public static KeyValuePair AddParentGrid = new KeyValuePair(); /// /// 当前右键点击时的表格 /// public static GridView _RightMenuGridView; public static GridView RightMenuGridView { get { return StaticControl._RightMenuGridView; } set { StaticControl._RightMenuGridView = value; StaticControl.Comprefix = ""; StaticControl.ReturnRowLisy.Clear(); } } /// /// bom附件修改时的关联页签 /// public static XtraTabPage BomUnionPage; /// /// 当前右键点击时的控件对象 /// public static MyControl RightMenuMyControl; /// /// 当前右键点击时的表格的列前缀 /// public static string Comprefix; /// /// 浏览器返回数据 /// public static List ReturnRowLisy = new List(); } }