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