286 lines
11 KiB
C#
286 lines
11 KiB
C#
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
|
||
{
|
||
/// <summary>
|
||
/// Releases static references owned by a closed legacy module. Cleanup is
|
||
/// best-effort so it cannot change the module close result.
|
||
/// </summary>
|
||
public static void ReleaseModuleReferences(WinFormsControl moduleRoot, XtraTabPage modulePage, string moduleCode)
|
||
{
|
||
List<GridView> gridViews = new List<GridView>();
|
||
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<GridView> CollectGridViews(WinFormsControl root)
|
||
{
|
||
List<GridView> result = new List<GridView>();
|
||
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<WinFormsControl> 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<GridView> 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<string, GridControlEx>();
|
||
}
|
||
|
||
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<object, Hashtable> caches = model.DataCaches;
|
||
foreach (Hashtable cache in caches.Values.OfType<Hashtable>().ToList())
|
||
{
|
||
foreach (IDisposable item in cache.Values.OfType<IDisposable>().ToList())
|
||
try { item.Dispose(); } catch { }
|
||
cache.Clear();
|
||
}
|
||
caches.Clear();
|
||
model.DataCaches = null;
|
||
}
|
||
/// <summary>
|
||
/// 记录当前U盾权限窗口
|
||
/// </summary>
|
||
public static List<XtraTabPage> DogVerifyModuleForms = new List<XtraTabPage>();
|
||
public static List<IForm> DogVerifyNoPageForms = new List<IForm>();
|
||
/// <summary>
|
||
///模块打开时的条件界面
|
||
/// </summary>
|
||
public static Dictionary<string, ModuleConditionsPanelEx> ConditionsPanelDic = new Dictionary<string, ModuleConditionsPanelEx>();
|
||
/// <summary>
|
||
/// 表格拖拽类,key值为源表
|
||
/// </summary>
|
||
public static Dictionary<GridView, List<GridDragGrid>> GridViewDragGridDic = new Dictionary<GridView, List<GridDragGrid>>();
|
||
/// <summary>
|
||
/// 表格拖拽类,key值为目标表
|
||
/// </summary>
|
||
public static Dictionary<GridView, List<GridDragGrid>> TargetViewDragGridDic = new Dictionary<GridView, List<GridDragGrid>>();
|
||
/// <summary>
|
||
/// 当前拖拽源表格
|
||
/// </summary>
|
||
public static GridView SourceDragGridView;
|
||
/// <summary>
|
||
/// 指纹识别模块
|
||
/// </summary>
|
||
public static FingerHelper fingerHelper;
|
||
///// <summary>
|
||
///// 外部exe进程
|
||
///// </summary>
|
||
//public static Dictionary<ExeType, Process> loadExeProcess = new Dictionary<ExeType, Process>();
|
||
/// <summary>
|
||
/// 打开的Add模块对应的父表格控件(模块编号,GridControlEx)
|
||
/// </summary>
|
||
public static KeyValuePair<string, GridControlEx> AddParentGrid = new KeyValuePair<string, GridControlEx>();
|
||
/// <summary>
|
||
/// 当前右键点击时的表格
|
||
/// </summary>
|
||
public static GridView _RightMenuGridView;
|
||
public static GridView RightMenuGridView
|
||
{
|
||
get
|
||
{
|
||
return StaticControl._RightMenuGridView;
|
||
}
|
||
set
|
||
{
|
||
StaticControl._RightMenuGridView = value;
|
||
StaticControl.Comprefix = "";
|
||
StaticControl.ReturnRowLisy.Clear();
|
||
}
|
||
|
||
}
|
||
/// <summary>
|
||
/// bom附件修改时的关联页签
|
||
/// </summary>
|
||
public static XtraTabPage BomUnionPage;
|
||
/// <summary>
|
||
/// 当前右键点击时的控件对象
|
||
/// </summary>
|
||
public static MyControl RightMenuMyControl;
|
||
/// <summary>
|
||
/// 当前右键点击时的表格的列前缀
|
||
/// </summary>
|
||
public static string Comprefix;
|
||
/// <summary>
|
||
/// 浏览器返回数据
|
||
/// </summary>
|
||
public static List<DataRow> ReturnRowLisy = new List<DataRow>();
|
||
|
||
|
||
}
|
||
}
|