fix(legacy): finalize hosted module lifecycle cleanup

This commit is contained in:
SugarChes
2026-08-29 18:03:44 +08:00
parent e27d445844
commit 176952d52c
5 changed files with 806 additions and 88 deletions
+119 -6
View File
@@ -46,23 +46,62 @@ namespace Lskj.Control.Model
Dictionary<GridView, List<GridDragGrid>> registrations,
GridView gridView)
{
if (registrations == null)
return;
// A module-close operation must only remove registrations that
// reference the exact view being closed. Never infer ownership
// from GridControl.IsDisposed here: another open tab can be in a
// transient initialization/dispose state and its registration
// must remain untouched.
foreach (KeyValuePair<GridView, List<GridDragGrid>> entry in registrations.ToList())
{
bool removeKey = ReferenceEquals(entry.Key, gridView);
foreach (GridDragGrid registration in entry.Value.ToList())
List<GridDragGrid> registrationsForView = entry.Value;
if (registrationsForView == null)
{
if (removeKey || registration == null || registration._disposed || registration.References(gridView))
registrations.Remove(entry.Key);
continue;
}
foreach (GridDragGrid registration in registrationsForView.ToList())
{
if (removeKey || registration == null || registration._disposed ||
registration.References(gridView))
{
if (registration != null)
registration.Dispose();
entry.Value.Remove(registration);
{
try
{
registration.Dispose();
}
catch (Exception exception)
{
System.Diagnostics.Debug.WriteLine("清理表格拖拽注册失败:" + exception);
}
}
registrationsForView.Remove(registration);
}
}
if (removeKey || entry.Value.Count == 0)
if (removeKey || registrationsForView.Count == 0)
registrations.Remove(entry.Key);
}
}
private static bool IsDisposedView(GridView view)
{
if (view == null)
return true;
try
{
return view.GridControl == null || view.GridControl.IsDisposed;
}
catch
{
return true;
}
}
internal bool References(GridView gridView)
{
return gridView != null &&
@@ -115,8 +154,16 @@ namespace Lskj.Control.Model
/// <param name="tarGridView">目标GridView.</param>
public GridDragGrid(GridView sourceView, GridView targetView)
{
// Do not put an incomplete registration in the global dictionaries.
// A GridView without an owner GridControl cannot receive the drag
// events below and would otherwise remain a strong static reference.
if (IsDisposedView(sourceView) || IsDisposedView(targetView))
return;
this._sourceGridView = sourceView;
this._targetGridView = targetView;
try
{
//记录所有拖拽类到来源表中,后每次进入目标表禁用其他拖拽类的拖拽事件
if (StaticControl.GridViewDragGridDic.ContainsKey(sourceView))
{
@@ -162,6 +209,21 @@ namespace Lskj.Control.Model
{
this._targetGridView.Disposed += OnGridViewDisposed;
}
}
catch
{
// Registration is a two-dictionary operation. If event wiring
// fails, undo everything that was attached before rethrowing.
try
{
Dispose();
}
catch (Exception exception)
{
System.Diagnostics.Debug.WriteLine("回滚表格拖拽注册失败:" + exception);
}
throw;
}
}
private void OnGridViewDisposed(object sender, EventArgs e)
@@ -214,7 +276,8 @@ namespace Lskj.Control.Model
targetGridView,
this);
if (ReferenceEquals(StaticControl.SourceDragGridView, sourceGridView))
if (ReferenceEquals(StaticControl.SourceDragGridView, sourceGridView) &&
!HasRegistrationForView(sourceGridView))
{
StaticControl.SourceDragGridView = null;
}
@@ -226,6 +289,45 @@ namespace Lskj.Control.Model
_targetGridView = null;
}
private static bool HasRegistrationForView(GridView gridView)
{
if (gridView == null)
return false;
return HasRegistration(StaticControl.GridViewDragGridDic, gridView) ||
HasRegistration(StaticControl.TargetViewDragGridDic, gridView);
}
internal static void ClearSourceReferenceIfUnused(GridView gridView)
{
if (gridView != null &&
ReferenceEquals(StaticControl.SourceDragGridView, gridView) &&
!HasRegistrationForView(gridView))
{
StaticControl.SourceDragGridView = null;
}
}
private static bool HasRegistration<TKey>(
Dictionary<TKey, List<GridDragGrid>> registrations,
GridView gridView)
where TKey : class
{
if (registrations == null || gridView == null)
return false;
foreach (KeyValuePair<TKey, List<GridDragGrid>> entry in registrations)
{
List<GridDragGrid> items = entry.Value;
if (items == null)
continue;
foreach (GridDragGrid item in items)
if (item != null && !item._disposed && item.References(gridView))
return true;
}
return false;
}
private static void RemoveRegistration<TKey>(
Dictionary<TKey, List<GridDragGrid>> registrations,
TKey key,
@@ -237,12 +339,23 @@ namespace Lskj.Control.Model
return;
}
if (registrations == null)
{
return;
}
List<GridDragGrid> registrationsForView;
if (!registrations.TryGetValue(key, out registrationsForView))
{
return;
}
if (registrationsForView == null)
{
registrations.Remove(key);
return;
}
registrationsForView.Remove(registration);
if (registrationsForView.Count == 0)
{