fix: 收敛旧模块资源释放与诊断
This commit is contained in:
@@ -29,6 +29,65 @@ namespace Lskj.Control.Model
|
||||
public class BandedGridDragGrid : IDisposable
|
||||
{
|
||||
private bool _disposed;
|
||||
|
||||
internal static void DisposeRegistrations(
|
||||
Dictionary<BandedGridView, List<BandedGridDragGrid>> sourceRegistrations,
|
||||
Dictionary<GridView, List<BandedGridDragGrid>> targetRegistrations,
|
||||
BandedGridView sourceGridView,
|
||||
GridView targetGridView)
|
||||
{
|
||||
DisposeSourceRegistrations(sourceRegistrations, sourceGridView);
|
||||
DisposeTargetRegistrations(targetRegistrations, targetGridView);
|
||||
}
|
||||
|
||||
private static void DisposeSourceRegistrations(
|
||||
Dictionary<BandedGridView, List<BandedGridDragGrid>> registrations,
|
||||
BandedGridView gridView)
|
||||
{
|
||||
foreach (KeyValuePair<BandedGridView, List<BandedGridDragGrid>> entry in registrations.ToList())
|
||||
{
|
||||
bool removeKey = ReferenceEquals(entry.Key, gridView);
|
||||
foreach (BandedGridDragGrid registration in entry.Value.ToList())
|
||||
{
|
||||
if (removeKey || registration == null || registration._disposed || registration.References(gridView))
|
||||
{
|
||||
if (registration != null)
|
||||
registration.Dispose();
|
||||
entry.Value.Remove(registration);
|
||||
}
|
||||
}
|
||||
if (removeKey || entry.Value.Count == 0)
|
||||
registrations.Remove(entry.Key);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DisposeTargetRegistrations(
|
||||
Dictionary<GridView, List<BandedGridDragGrid>> registrations,
|
||||
GridView gridView)
|
||||
{
|
||||
foreach (KeyValuePair<GridView, List<BandedGridDragGrid>> entry in registrations.ToList())
|
||||
{
|
||||
bool removeKey = ReferenceEquals(entry.Key, gridView);
|
||||
foreach (BandedGridDragGrid registration in entry.Value.ToList())
|
||||
{
|
||||
if (removeKey || registration == null || registration._disposed || registration.References(gridView))
|
||||
{
|
||||
if (registration != null)
|
||||
registration.Dispose();
|
||||
entry.Value.Remove(registration);
|
||||
}
|
||||
}
|
||||
if (removeKey || entry.Value.Count == 0)
|
||||
registrations.Remove(entry.Key);
|
||||
}
|
||||
}
|
||||
|
||||
internal bool References(GridView gridView)
|
||||
{
|
||||
return gridView != null &&
|
||||
(ReferenceEquals(_sourceGridView, gridView) ||
|
||||
ReferenceEquals(_targetGridView, gridView));
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否正在拖拽
|
||||
/// </summary>
|
||||
|
||||
@@ -32,6 +32,43 @@ namespace Lskj.Control.Model
|
||||
public class GridDragGrid : IDisposable
|
||||
{
|
||||
private bool _disposed;
|
||||
|
||||
internal static void DisposeRegistrations(
|
||||
Dictionary<GridView, List<GridDragGrid>> sourceRegistrations,
|
||||
Dictionary<GridView, List<GridDragGrid>> targetRegistrations,
|
||||
GridView gridView)
|
||||
{
|
||||
DisposeRegistrations(sourceRegistrations, gridView);
|
||||
DisposeRegistrations(targetRegistrations, gridView);
|
||||
}
|
||||
|
||||
private static void DisposeRegistrations(
|
||||
Dictionary<GridView, List<GridDragGrid>> registrations,
|
||||
GridView gridView)
|
||||
{
|
||||
foreach (KeyValuePair<GridView, List<GridDragGrid>> entry in registrations.ToList())
|
||||
{
|
||||
bool removeKey = ReferenceEquals(entry.Key, gridView);
|
||||
foreach (GridDragGrid registration in entry.Value.ToList())
|
||||
{
|
||||
if (removeKey || registration == null || registration._disposed || registration.References(gridView))
|
||||
{
|
||||
if (registration != null)
|
||||
registration.Dispose();
|
||||
entry.Value.Remove(registration);
|
||||
}
|
||||
}
|
||||
if (removeKey || entry.Value.Count == 0)
|
||||
registrations.Remove(entry.Key);
|
||||
}
|
||||
}
|
||||
|
||||
internal bool References(GridView gridView)
|
||||
{
|
||||
return gridView != null &&
|
||||
(ReferenceEquals(_sourceGridView, gridView) ||
|
||||
ReferenceEquals(_targetGridView, gridView));
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否正在拖拽
|
||||
/// </summary>
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Lskj.Control.Model
|
||||
/// <summary>
|
||||
/// 表格拖拽到树结构
|
||||
/// </summary>
|
||||
public class GridDragTree
|
||||
public class GridDragTree : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// 拖动位置
|
||||
@@ -38,6 +38,7 @@ namespace Lskj.Control.Model
|
||||
/// 拖动目标源
|
||||
/// </summary>
|
||||
private TreeView _treeView;
|
||||
private bool _disposed;
|
||||
public bool CanDragParentNode = false;
|
||||
/// <summary>
|
||||
/// 表格数据拖动完成
|
||||
@@ -60,6 +61,31 @@ namespace Lskj.Control.Model
|
||||
this._treeView.DragOver += new DragEventHandler(treeView_DragOver);
|
||||
this._treeView.DragDrop += new DragEventHandler(treeView_DragDrop);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_disposed = true;
|
||||
if (_gridView != null)
|
||||
{
|
||||
_gridView.MouseDown -= gridView_MouseDown;
|
||||
_gridView.MouseMove -= gridView_MouseMove;
|
||||
}
|
||||
if (_treeView != null)
|
||||
{
|
||||
_treeView.DragOver -= treeView_DragOver;
|
||||
_treeView.DragDrop -= treeView_DragDrop;
|
||||
}
|
||||
|
||||
OnDragComplete = null;
|
||||
_hitInfo = null;
|
||||
_gridView = null;
|
||||
_treeView = null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -913,6 +913,14 @@ namespace Lskj.Control.Model
|
||||
/// <param name="key">The key.</param>
|
||||
/// <returns>DataTable.</returns>
|
||||
public static DataTable GetCustomColumnByDatabase(this GridView gridView, string key)
|
||||
{
|
||||
return GetCustomColumnByDatabase(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取个性配置列数据,不依赖任何界面控件。
|
||||
/// </summary>
|
||||
public static DataTable GetCustomColumnByDatabase(string key)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -954,18 +962,7 @@ namespace Lskj.Control.Model
|
||||
{
|
||||
BaseImpl.ExecSqlValue("alter table " + ResourceKeys.SettingTableName + " add IfFixColumn bit");
|
||||
}
|
||||
// 读取普通用户读取个人配置,没有则读取管理员配置,管理未配置则读取系统默认.逐级上报读取方式.
|
||||
string sqlValue = string.Format("select * from {0} where formKey='{1}' and operatorid='{2}' order by orderid ", ResourceKeys.SettingTableName, key, ERPInfo.Instance.UserId);
|
||||
|
||||
DataTable table = BaseImpl.GetDataTableResult(sqlValue);
|
||||
|
||||
//if (table == null || table.Rows.Count == 0)
|
||||
//{
|
||||
// sqlValue = string.Format("select * from {0} where formKey='{1}' and operatorid='{2}'", ResourceKeys.SettingTableName, key, ERPInfo.Instance.UserManager);
|
||||
// table = BaseImpl.GetDataTableResult(sqlValue);
|
||||
//}
|
||||
|
||||
return table;
|
||||
return GetCustomColumnByDatabase(key);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
@@ -32,8 +32,10 @@ namespace Lskj.Control.Model
|
||||
/// <summary>
|
||||
/// 查询控件、添加修改界面控件管理类
|
||||
/// </summary>
|
||||
public class MyControl
|
||||
public class MyControl : IDisposable
|
||||
{
|
||||
private const long UserSearchCooldownTicks =
|
||||
TimeSpan.TicksPerMillisecond * 350;
|
||||
private string _searchSql;
|
||||
private DataTable _controls;
|
||||
private DataTable _schemes;
|
||||
@@ -46,8 +48,12 @@ namespace Lskj.Control.Model
|
||||
private GridControlEx _gridLeft;
|
||||
private TreeViewEx _tvLeft;
|
||||
private MyControl _leftSearch;
|
||||
private DropDownButton _dropDown = new DropDownButton();
|
||||
private PopupMenu _popupMenu = new PopupMenu();
|
||||
private DropDownButton _dropDown;
|
||||
private PopupMenu _popupMenu;
|
||||
private bool mDisposed;
|
||||
private bool mUserSearchInProgress;
|
||||
private long mLastUserSearchCompletedTicks;
|
||||
private int mAcceptedUserSearchCount;
|
||||
/// <summary>
|
||||
/// 计算字段
|
||||
/// </summary>
|
||||
@@ -112,6 +118,10 @@ namespace Lskj.Control.Model
|
||||
/// </summary>
|
||||
/// <value>The button object.</value>
|
||||
public SimpleButton ButtonObj { get { return _button; } }
|
||||
public int AcceptedUserSearchCount
|
||||
{
|
||||
get { return mAcceptedUserSearchCount; }
|
||||
}
|
||||
/// <summary>
|
||||
/// 条件数据源刷新按钮
|
||||
/// </summary>
|
||||
@@ -1024,6 +1034,10 @@ namespace Lskj.Control.Model
|
||||
// 创建模版搜索
|
||||
if (_schemes != null && ModuleId > 0 && _schemes.Rows.Count > 0)
|
||||
{
|
||||
if (_popupMenu == null)
|
||||
{
|
||||
_popupMenu = new PopupMenu();
|
||||
}
|
||||
_dropDown = new DropDownButton();
|
||||
_dropDown.DropDownArrowStyle = DropDownArrowStyle.Show;
|
||||
_dropDown.DropDownControl = this._popupMenu;
|
||||
@@ -1204,6 +1218,10 @@ namespace Lskj.Control.Model
|
||||
// 创建模版搜索
|
||||
if (_schemes != null && ModuleId > 0 && _schemes.Rows.Count > 0)
|
||||
{
|
||||
if (_popupMenu == null)
|
||||
{
|
||||
_popupMenu = new PopupMenu();
|
||||
}
|
||||
_dropDown = new DropDownButton();
|
||||
_dropDown.DropDownArrowStyle = DropDownArrowStyle.Show;
|
||||
_dropDown.DropDownControl = this._popupMenu;
|
||||
@@ -1736,8 +1754,14 @@ namespace Lskj.Control.Model
|
||||
WaitForm.HideForm();
|
||||
mControlSourceDic.Clear();
|
||||
if (this.OnDataSourceBindCallBack != null) this.OnDataSourceBindCallBack(this, null);
|
||||
this.mTimer.Stop();
|
||||
this.mTimer.Dispose();
|
||||
Timer timer = this.mTimer;
|
||||
this.mTimer = null;
|
||||
if (timer != null)
|
||||
{
|
||||
timer.Tick -= mTimerTick;
|
||||
timer.Stop();
|
||||
timer.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6091,6 +6115,61 @@ namespace Lskj.Control.Model
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryBeginUserSearch()
|
||||
{
|
||||
if (mDisposed || mUserSearchInProgress)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
long now = DateTime.UtcNow.Ticks;
|
||||
if (mLastUserSearchCompletedTicks > 0 &&
|
||||
now - mLastUserSearchCompletedTicks < UserSearchCooldownTicks)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
mUserSearchInProgress = true;
|
||||
mAcceptedUserSearchCount++;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void EndUserSearch()
|
||||
{
|
||||
mUserSearchInProgress = false;
|
||||
mLastUserSearchCompletedTicks = DateTime.UtcNow.Ticks;
|
||||
}
|
||||
|
||||
private bool ExecuteUserSearch(object sender, EventArgs e)
|
||||
{
|
||||
if (!TryBeginUserSearch())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
SearchArgs args = new SearchArgs();
|
||||
if (OnSearchBeforeCallBack != null)
|
||||
{
|
||||
OnSearchBeforeCallBack(sender, args);
|
||||
}
|
||||
if (args.Continue)
|
||||
{
|
||||
this.SearchGrid(false);
|
||||
}
|
||||
if (OnSearchAfterCallBack != null)
|
||||
{
|
||||
OnSearchAfterCallBack(sender, e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
EndUserSearch();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>说明:</para>
|
||||
/// <para>创建人:龚宇超</para>
|
||||
@@ -6115,18 +6194,8 @@ namespace Lskj.Control.Model
|
||||
{
|
||||
if (baseControl.Model.IsSearchControl)
|
||||
{
|
||||
// 搜索控件回车直接搜索
|
||||
SearchArgs args = new SearchArgs();
|
||||
// 查询之前
|
||||
if (OnSearchBeforeCallBack != null)
|
||||
OnSearchBeforeCallBack(sender, args);
|
||||
|
||||
if (args.Continue) this.SearchGrid(false);
|
||||
|
||||
// 查询之后
|
||||
if (OnSearchAfterCallBack != null) OnSearchAfterCallBack(sender, e);
|
||||
|
||||
if (baseControl.Model.ScanAfterEmpty)
|
||||
if (ExecuteUserSearch(sender, e) &&
|
||||
baseControl.Model.ScanAfterEmpty)
|
||||
{
|
||||
baseControl.EditText = string.Empty;
|
||||
}
|
||||
@@ -6225,14 +6294,7 @@ namespace Lskj.Control.Model
|
||||
{
|
||||
if (baseControl.Model.IsSearchControl)
|
||||
{
|
||||
// 搜索控件回车直接搜索
|
||||
SearchArgs args = new SearchArgs();
|
||||
// 查询之前
|
||||
if (OnSearchBeforeCallBack != null)
|
||||
OnSearchBeforeCallBack(sender, args);
|
||||
if (args.Continue) this.SearchGrid(false);
|
||||
// 查询之后
|
||||
if (OnSearchAfterCallBack != null) OnSearchAfterCallBack(sender, e);
|
||||
ExecuteUserSearch(sender, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6249,45 +6311,57 @@ namespace Lskj.Control.Model
|
||||
/// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
|
||||
protected void OnSimpleButtonClick(object sender, EventArgs e)
|
||||
{
|
||||
if (!TryBeginUserSearch())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (Model != null)
|
||||
try
|
||||
{
|
||||
bool allowBefore = ApiHelper.IsExecEventApi(Interface.Api.OperateEvent.BeforeSearchBtnClick, Model.ModuleCode, 0);
|
||||
//查询前调用Api接口
|
||||
if (allowBefore)
|
||||
if (Model != null)
|
||||
{
|
||||
DataRow dataRow = this.GetAllControlValueRow();
|
||||
ApiHelper apiHelper = new ApiHelper(Model.ModuleCode, 0, dataRow);
|
||||
apiHelper.OnEvent(Interface.Api.OperateEvent.BeforeSearchBtnClick, Interface.Api.ActionType.None);
|
||||
if (apiHelper.apiHandlerModels.Count > 0)
|
||||
bool allowBefore = ApiHelper.IsExecEventApi(Interface.Api.OperateEvent.BeforeSearchBtnClick, Model.ModuleCode, 0);
|
||||
//查询前调用Api接口
|
||||
if (allowBefore)
|
||||
{
|
||||
Hashtable hashtable = apiHelper.apiHandlerModels[apiHelper.apiHandlerModels.Count - 1].resultPmsHashtables[0];
|
||||
if (hashtable.ContainsKey("result"))
|
||||
DataRow dataRow = this.GetAllControlValueRow();
|
||||
ApiHelper apiHelper = new ApiHelper(Model.ModuleCode, 0, dataRow);
|
||||
apiHelper.OnEvent(Interface.Api.OperateEvent.BeforeSearchBtnClick, Interface.Api.ActionType.None);
|
||||
if (apiHelper.apiHandlerModels.Count > 0)
|
||||
{
|
||||
string jsonResult = hashtable["result"] + "";
|
||||
DataTable dataTable = JsonConvert.DeserializeObject<DataTable>(jsonResult);
|
||||
this._mainGridEx.SetGridViewDataSource(dataTable);
|
||||
return;
|
||||
Hashtable hashtable = apiHelper.apiHandlerModels[apiHelper.apiHandlerModels.Count - 1].resultPmsHashtables[0];
|
||||
if (hashtable.ContainsKey("result"))
|
||||
{
|
||||
string jsonResult = hashtable["result"] + "";
|
||||
DataTable dataTable = JsonConvert.DeserializeObject<DataTable>(jsonResult);
|
||||
this._mainGridEx.SetGridViewDataSource(dataTable);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageUtil.Show(ex.Message);
|
||||
}
|
||||
SearchArgs args = new SearchArgs();
|
||||
// 查询之前
|
||||
if (OnSearchBeforeCallBack != null)
|
||||
OnSearchBeforeCallBack(sender, args);
|
||||
|
||||
if (args.Continue) this.SearchGrid(false);
|
||||
|
||||
// 查询之后
|
||||
if (OnSearchAfterCallBack != null) OnSearchAfterCallBack(sender, e);
|
||||
}
|
||||
catch (Exception ex)
|
||||
finally
|
||||
{
|
||||
MessageUtil.Show(ex.Message);
|
||||
EndUserSearch();
|
||||
}
|
||||
SearchArgs args = new SearchArgs();
|
||||
// 查询之前
|
||||
if (OnSearchBeforeCallBack != null)
|
||||
OnSearchBeforeCallBack(sender, args);
|
||||
|
||||
if (args.Continue) this.SearchGrid(false);
|
||||
|
||||
// 查询之后
|
||||
if (OnSearchAfterCallBack != null) OnSearchAfterCallBack(sender, e);
|
||||
}
|
||||
|
||||
|
||||
@@ -6322,15 +6396,7 @@ namespace Lskj.Control.Model
|
||||
/// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
|
||||
protected void OnFixButtonClick(object sender, EventArgs e)
|
||||
{
|
||||
SearchArgs args = new SearchArgs();
|
||||
// 查询之前
|
||||
if (OnSearchBeforeCallBack != null)
|
||||
OnSearchBeforeCallBack(sender, args);
|
||||
|
||||
if (args.Continue) this.SearchGrid(false);
|
||||
|
||||
// 查询之后
|
||||
if (OnSearchAfterCallBack != null) OnSearchAfterCallBack(sender, e);
|
||||
ExecuteUserSearch(sender, e);
|
||||
}
|
||||
/// <summary>
|
||||
/// <para>说明:高级搜索按钮鼠标离开时</para>
|
||||
@@ -6716,6 +6782,154 @@ namespace Lskj.Control.Model
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposing || mDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mDisposed = true;
|
||||
mUserSearchInProgress = false;
|
||||
|
||||
Timer timer = mTimer;
|
||||
mTimer = null;
|
||||
if (timer != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
timer.Tick -= mTimerTick;
|
||||
timer.Stop();
|
||||
timer.Dispose();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// A completed delayed-load timer may already be disposed.
|
||||
}
|
||||
}
|
||||
|
||||
if (_button != null)
|
||||
{
|
||||
_button.Click -= OnSimpleButtonClick;
|
||||
_button.Tag = null;
|
||||
}
|
||||
if (_fixButton != null)
|
||||
{
|
||||
_fixButton.Click -= OnFixButtonClick;
|
||||
}
|
||||
if (_refreshButton != null)
|
||||
{
|
||||
_refreshButton.Click -= OnRefreshButtonClick;
|
||||
_refreshButton.Tag = null;
|
||||
}
|
||||
if (btnCondSearch != null)
|
||||
{
|
||||
btnCondSearch.Click -= OnBtnCondSearchClick;
|
||||
btnCondSearch.Tag = null;
|
||||
}
|
||||
if (_dropDown != null)
|
||||
{
|
||||
_dropDown.Leave -= OnDropDownLeave;
|
||||
_dropDown.DropDownControl = null;
|
||||
}
|
||||
foreach (SimpleButton button in mrpBtnDic.Values.Distinct())
|
||||
{
|
||||
if (button != null)
|
||||
{
|
||||
button.Click -= OnModuleClick;
|
||||
button.Tag = null;
|
||||
}
|
||||
}
|
||||
|
||||
BarManager searchSchemeManager =
|
||||
_popupMenu == null ? null : _popupMenu.Manager;
|
||||
if (_popupMenu != null)
|
||||
{
|
||||
_popupMenu.Manager = null;
|
||||
_popupMenu.ItemLinks.Clear();
|
||||
_popupMenu.Dispose();
|
||||
}
|
||||
if (searchSchemeManager != null)
|
||||
{
|
||||
searchSchemeManager.Dispose();
|
||||
}
|
||||
|
||||
if (_mainGridEx != null &&
|
||||
ReferenceEquals(_mainGridEx.ParentControl, this))
|
||||
{
|
||||
_mainGridEx.ParentControl = null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (Model != null && Model.DataCaches != null)
|
||||
{
|
||||
Model.DataCaches.Remove(this);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Cache cleanup must not interrupt module disposal.
|
||||
}
|
||||
|
||||
preSearchVerification = null;
|
||||
OnSearchBeforeCallBack = null;
|
||||
OnSearchAfterCallBack = null;
|
||||
OnAddCallBack = null;
|
||||
ClearDetails = null;
|
||||
OnLastQueryTriggered = null;
|
||||
OnSourceRefrshCallBack = null;
|
||||
OnDataSourceBindCallBack = null;
|
||||
OnDataFileRefrshCallBack = null;
|
||||
OpenDocumentSource = null;
|
||||
|
||||
_calcControls.Clear();
|
||||
_models.Clear();
|
||||
mControlList.Clear();
|
||||
mExtendedReturnSearchControls.Clear();
|
||||
mExtendedReturnPendingChanges.Clear();
|
||||
mControlSourceDic.Clear();
|
||||
mCacheDictionary.Clear();
|
||||
DetailSelection.Clear();
|
||||
changeLabelAutoGridLooks.Clear();
|
||||
mrpBtnDic.Clear();
|
||||
ModuleResultDic.Clear();
|
||||
ParaContrlsDic.Clear();
|
||||
|
||||
_controls = null;
|
||||
_schemes = null;
|
||||
_fixField = null;
|
||||
_fixKey = null;
|
||||
_button = null;
|
||||
_fixButton = null;
|
||||
_refreshButton = null;
|
||||
_dropDown = null;
|
||||
_popupMenu = null;
|
||||
btnCondSearch = null;
|
||||
_gridControl = null;
|
||||
_mainGridEx = null;
|
||||
_gridLeft = null;
|
||||
_tvLeft = null;
|
||||
_leftSearch = null;
|
||||
_parentPanel = null;
|
||||
CurrentData = null;
|
||||
SystemModel = null;
|
||||
SaveCondTab = null;
|
||||
mrpDyncModel = null;
|
||||
Model = null;
|
||||
popUpDyncModel = null;
|
||||
rightItemLinks = null;
|
||||
SpecialLeftTable = null;
|
||||
beforeData = null;
|
||||
OtherParams = null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,11 +7,94 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using WinFormsControl = System.Windows.Forms.Control;
|
||||
|
||||
namespace Lskj.Control.Model
|
||||
{
|
||||
public static class StaticBandedControl
|
||||
{
|
||||
public static void ReleaseModuleReferences(WinFormsControl moduleRoot, XtraTabPage modulePage, string moduleCode)
|
||||
{
|
||||
try
|
||||
{
|
||||
List<BandedGridView> bandedViews = CollectBandedGridViews(moduleRoot);
|
||||
List<GridView> targetViews = CollectTargetGridViews(moduleRoot);
|
||||
foreach (BandedGridView view in bandedViews)
|
||||
BandedGridDragGrid.DisposeRegistrations(
|
||||
BandedGridViewDragGridDic,
|
||||
BandedTargetViewDragGridDic,
|
||||
view,
|
||||
null);
|
||||
foreach (GridView view in targetViews)
|
||||
BandedGridDragGrid.DisposeRegistrations(
|
||||
BandedGridViewDragGridDic,
|
||||
BandedTargetViewDragGridDic,
|
||||
null,
|
||||
view);
|
||||
if (SourceDragBandedGridView != null &&
|
||||
(bandedViews.Contains(SourceDragBandedGridView) ||
|
||||
(SourceDragBandedGridView.GridControl != null && SourceDragBandedGridView.GridControl.IsDisposed)))
|
||||
SourceDragBandedGridView = null;
|
||||
RemoveConditionPanels(moduleCode);
|
||||
while (modulePage != null && DogVerifyModuleForms.Remove(modulePage))
|
||||
{
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("释放旧 Banded 模块引用失败:" + exception);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<BandedGridView> CollectBandedGridViews(WinFormsControl root)
|
||||
{
|
||||
List<BandedGridView> result = new List<BandedGridView>();
|
||||
if (root == null)
|
||||
return result;
|
||||
foreach (WinFormsControl control in EnumerateControls(root))
|
||||
{
|
||||
DevExpress.XtraGrid.GridControl grid = control as DevExpress.XtraGrid.GridControl;
|
||||
BandedGridView view = grid == null ? null : grid.MainView as BandedGridView;
|
||||
if (view != null && !result.Contains(view))
|
||||
result.Add(view);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<GridView> CollectTargetGridViews(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 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);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 记录当前U盾权限窗口
|
||||
/// </summary>
|
||||
@@ -44,4 +127,4 @@ namespace Lskj.Control.Model
|
||||
/// </summary>
|
||||
public static FrmProgressBar frmProgressBar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,17 +3,215 @@ 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>
|
||||
@@ -84,4 +282,4 @@ namespace Lskj.Control.Model
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user