/****************************** * 说明:表格报表模版 * 创建人:龚宇超 * 创建日期:2017-11-20 * 修改人: * 修改日期: * 修改备注: * 版本:1.0.0.0 ******************************/ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using Lskj.Control; using Lskj.Model; using Lskj.Control.Model; using Lskj.Util; using Lskj.Data; using Lskj.Business.Impl; using Lskj.Business; using System.Threading.Tasks; using System.Collections; using System.IO; using System.Reflection; namespace Lskj.Report { public partial class FrmMain : BaseForm { /// /// 报表动态链接库参数 /// public DynamicReportModel Model; private readonly HashSet mPreexistingGridLocalizerViews = CaptureGridLocalizerViews(); private readonly HashSet mReportGridLocalizerViews = new HashSet(); private bool mReportGridResourcesReleased; private int mDisposedReportGridViewCount; private int mRemovedGridLocalizerHandlerCount; public FrmMain() { InitializeComponent(); this.Disposed += OnFrmMainDisposed; } /// /// 说明:窗口加载 /// 创建人:龚宇超 /// 创建日期:2017-11-21 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The instance containing the event data. protected override void OnLoad(EventArgs e) { WaitForm.ShowForm(); try { Dictionary dataCaches = Model != null ? Model.DataCaches : null; this.Model.Privilege = this.Model.Privilege.Equals("3") ? "1" : Model.ModuleId > 0 ? BaseImpl.GetUserPurviewsByMenuId(Model.ModuleId + "") + "" : BaseImpl.GetUserPurviewsByMenuCode(Model.ModuleCode) + ""; this.mControl.ModuleGridDetailObj.ModuleGridObj.VisibleOperPanel = false; if (!dataCaches.GetValue(this, "Details", out List details)) { details = GetReportDetails(); } this.mControl.Details = details; this.mControl.InitControls(Model); CaptureReportGridLocalizerViews(); this.FormClosing += new FormClosingEventHandler(OnClose); } catch (Exception ex) { LogHelper.Instance.WriteError(ex, ResourceKeys.BaseReport); //MessageUtil.Show(ex.Message + "\r\n" + ex.StackTrace); string Message = ErrorMessage.PromptErrorMessage(ex); MessageUtil.Show(Message, ex.Message); } finally { Lskj.Control.Model.AutoSizeChange.ControllInitializeSize(this); this.mControl.Visible = true; } WaitForm.HideForm(); } private void OnClose(object sender, FormClosingEventArgs e) { WriteReportLifecycleDiagnostics("closing-before-close-module"); this.mControl.CloseModule(); WriteReportLifecycleDiagnostics("closing-after-close-module"); } private void OnFrmMainDisposed(object sender, EventArgs e) { DisposeReportGridViews(); WriteReportLifecycleDiagnostics( "disposed-event;disposedGridViews=" + mDisposedReportGridViewCount + ";gridLocalizerRemoved=" + mRemovedGridLocalizerHandlerCount); mReportGridLocalizerViews.Clear(); mPreexistingGridLocalizerViews.Clear(); this.FormClosing -= OnClose; this.Disposed -= OnFrmMainDisposed; DynamicReportModel model = this.Model; this.Model = null; if (model == null || model.DataCaches == null) { return; } try { model.DataCaches.Clear(); } catch (Exception ex) { LogHelper.Instance.WriteError(ex, ResourceKeys.BaseReport); } } private void DisposeReportGridViews() { if (mReportGridResourcesReleased) { return; } mReportGridResourcesReleased = true; WriteReportLifecycleDiagnostics("dispose-before-gridviews"); CaptureReportGridLocalizerViews(); if (this.mControl != null) { this.mControl.ReleaseResourcesForDispose(); } HashSet disposedViews = new HashSet(); int disposeErrorCount = 0; int detachedDataSourceCount = 0; foreach (System.Windows.Forms.Control control in EnumerateControls(this.mControl)) { DevExpress.XtraGrid.GridControl gridControl = control as DevExpress.XtraGrid.GridControl; if (gridControl != null) { try { if (gridControl.DataSource != null) { gridControl.DataSource = null; detachedDataSourceCount++; } } catch (Exception ex) { disposeErrorCount++; LogHelper.Instance.WriteError(ex, ResourceKeys.BaseReport); } DevExpress.XtraGrid.Views.Base.BaseView[] views = gridControl.ViewCollection .Cast() .ToArray(); foreach (DevExpress.XtraGrid.Views.Base.BaseView view in views) { if (view == null || !disposedViews.Add(view)) { continue; } try { view.Dispose(); } catch (Exception ex) { disposeErrorCount++; LogHelper.Instance.WriteError(ex, ResourceKeys.BaseReport); } } } Type controlType = control.GetType(); if (controlType.FullName != null && controlType.FullName.StartsWith( "DevExpress.XtraTreeList.", StringComparison.Ordinal)) { try { PropertyInfo dataSourceProperty = controlType.GetProperty( "DataSource", BindingFlags.Instance | BindingFlags.Public); if (dataSourceProperty != null && dataSourceProperty.CanRead && dataSourceProperty.CanWrite && dataSourceProperty.GetValue(control, null) != null) { dataSourceProperty.SetValue(control, null, null); detachedDataSourceCount++; } } catch (Exception ex) { disposeErrorCount++; LogHelper.Instance.WriteError(ex, ResourceKeys.BaseReport); } } } int trackedGridViews = mReportGridLocalizerViews.Count; int removedGridLocalizerHandlers = ReleaseTrackedGridLocalizerViews(disposedViews); mDisposedReportGridViewCount = disposedViews.Count; mRemovedGridLocalizerHandlerCount = removedGridLocalizerHandlers; WriteReportLifecycleDiagnostics( "dispose-after-gridviews;dispose-attempts=" + disposedViews.Count + ";dispose-errors=" + disposeErrorCount + ";detachedDataSources=" + detachedDataSourceCount + ";trackedGridViews=" + trackedGridViews + ";gridLocalizerRemoved=" + removedGridLocalizerHandlers); } private void CaptureReportGridLocalizerViews() { HashSet currentViews = CaptureGridLocalizerViews(); foreach (DevExpress.XtraGrid.Views.Base.BaseView view in currentViews) { if (!mPreexistingGridLocalizerViews.Contains(view)) { mReportGridLocalizerViews.Add(view); } } } private int ReleaseTrackedGridLocalizerViews( HashSet disposedViews) { foreach (DevExpress.XtraGrid.Views.Base.BaseView view in mReportGridLocalizerViews) { if (view == null || (disposedViews != null && !disposedViews.Add(view))) { continue; } try { view.Dispose(); } catch (Exception exception) { LogHelper.Instance.WriteError(exception, ResourceKeys.BaseReport); } } return RemoveGridLocalizerHandlers(mReportGridLocalizerViews); } private static HashSet CaptureGridLocalizerViews() { HashSet result = new HashSet(); try { var activeLocalizer = DevExpress.XtraGrid.Localization.GridLocalizer.Active; if (activeLocalizer == null) { return result; } Type currentType = activeLocalizer.GetType(); while (currentType != null && currentType != typeof(object)) { FieldInfo[] fields = currentType.GetFields( BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); foreach (FieldInfo field in fields) { if (!typeof(Delegate).IsAssignableFrom(field.FieldType)) { continue; } object owner = field.IsStatic ? null : (object)activeLocalizer; Delegate current; try { current = field.GetValue(owner) as Delegate; } catch { continue; } if (current == null) { continue; } foreach (Delegate handler in current.GetInvocationList()) { if (IsGridLocalizerHandler(handler)) { result.Add( (DevExpress.XtraGrid.Views.Base.BaseView) handler.Target); } } } currentType = currentType.BaseType; } } catch { // Diagnostics cleanup must never interfere with form construction. } return result; } private static int RemoveGridLocalizerHandlers( HashSet targetViews) { if (targetViews == null || targetViews.Count == 0) { return 0; } int removedCount = 0; try { var activeLocalizer = DevExpress.XtraGrid.Localization.GridLocalizer.Active; if (activeLocalizer == null) { return 0; } Type currentType = activeLocalizer.GetType(); while (currentType != null && currentType != typeof(object)) { FieldInfo[] fields = currentType.GetFields( BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); foreach (FieldInfo field in fields) { if (!typeof(Delegate).IsAssignableFrom(field.FieldType)) { continue; } object owner = field.IsStatic ? null : (object)activeLocalizer; Delegate current; try { current = field.GetValue(owner) as Delegate; } catch { continue; } if (current == null) { continue; } Delegate retained = null; int fieldRemovedCount = 0; foreach (Delegate handler in current.GetInvocationList()) { DevExpress.XtraGrid.Views.Base.BaseView view = handler.Target as DevExpress.XtraGrid.Views.Base.BaseView; if (IsGridLocalizerHandler(handler) && targetViews.Contains(view)) { fieldRemovedCount++; continue; } retained = retained == null ? handler : Delegate.Combine(retained, handler); } if (fieldRemovedCount == 0) { continue; } try { field.SetValue(owner, retained); removedCount += fieldRemovedCount; } catch { // Some DevExpress versions expose a read-only backing field. } } currentType = currentType.BaseType; } } catch { // Diagnostics cleanup must never interfere with form disposal. } return removedCount; } private static bool IsGridLocalizerHandler(Delegate handler) { return handler != null && string.Equals( handler.Method.Name, "OnLocalizer_Changed", StringComparison.Ordinal) && handler.Target is DevExpress.XtraGrid.Views.Base.BaseView; } private void WriteReportLifecycleDiagnostics(string phase) { if (!IsReportDiagnosticsEnabled()) { return; } try { LogHelper.Instance.WriteLog( "REPORT_DIAGNOSTIC phase=" + (phase ?? string.Empty) + " " + GetReportGridDiagnostics(), "ResourceDiagnostics.Report"); } catch { // Diagnostics must never interfere with module close/dispose. } } private string GetReportGridDiagnostics() { int controlCount = 0; int gridControlCount = 0; int viewCount = 0; HashSet views = new HashSet(); StringBuilder viewDetails = new StringBuilder(); try { if (this.mControl != null) { foreach (System.Windows.Forms.Control control in EnumerateControls(this.mControl)) { controlCount++; DevExpress.XtraGrid.GridControl gridControl = control as DevExpress.XtraGrid.GridControl; if (gridControl == null) { continue; } gridControlCount++; foreach (DevExpress.XtraGrid.Views.Base.BaseView view in gridControl.ViewCollection.Cast()) { if (view == null || !views.Add(view)) { continue; } viewCount++; if (viewDetails.Length < 1800) { if (viewDetails.Length > 0) { viewDetails.Append(","); } viewDetails.Append(SafeViewDescription(view)); } } } } } catch (Exception exception) { viewDetails.Append(",enumeration-error="); viewDetails.Append(exception.GetType().Name); } return "formDisposed=" + this.IsDisposed + ";controlCount=" + controlCount + ";gridControlCount=" + gridControlCount + ";viewCount=" + viewCount + ";views=" + viewDetails + ";gridLocalizer=" + DescribeGridLocalizer(); } private static string SafeViewDescription( DevExpress.XtraGrid.Views.Base.BaseView view) { try { return view.GetType().FullName + ":" + (view.Name ?? string.Empty).Replace(";", ","); } catch { return ""; } } private static string DescribeGridLocalizer() { try { var active = DevExpress.XtraGrid.Localization.GridLocalizer.Active; if (active == null) { return "active=null"; } StringBuilder handlers = new StringBuilder(); int handlerCount = 0; Type currentType = active.GetType(); while (currentType != null && currentType != typeof(object)) { FieldInfo[] fields = currentType.GetFields( BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); foreach (FieldInfo field in fields) { if (!typeof(Delegate).IsAssignableFrom(field.FieldType)) { continue; } object owner = field.IsStatic ? null : (object)active; Delegate value = field.GetValue(owner) as Delegate; if (value == null) { continue; } foreach (Delegate handler in value.GetInvocationList()) { handlerCount++; if (handlers.Length < 1800) { if (handlers.Length > 0) { handlers.Append(","); } string targetType = handler.Target == null ? "static" : handler.Target.GetType().FullName; handlers.Append(field.Name.Replace(";", ",")); handlers.Append("->"); handlers.Append(targetType.Replace(";", ",")); handlers.Append("."); handlers.Append(handler.Method.Name.Replace(";", ",")); } } } currentType = currentType.BaseType; } return "activeType=" + active.GetType().FullName.Replace(";", ",") + ";handlerCount=" + handlerCount + ";handlers=" + handlers; } catch (Exception exception) { return "localizer-error=" + exception.GetType().Name; } } private static bool IsReportDiagnosticsEnabled() { try { return File.Exists( Path.Combine( AppDomain.CurrentDomain.BaseDirectory, "Logs", "ResourceDiagnostics", "resource-diagnostics.enabled")); } catch { return false; } } private static IEnumerable EnumerateControls( System.Windows.Forms.Control root) { if (root == null) { yield break; } yield return root; foreach (System.Windows.Forms.Control child in root.Controls) { foreach (System.Windows.Forms.Control nested in EnumerateControls(child)) { yield return nested; } } } /// /// 说明:获取报表明细 /// 创建人:龚宇超 /// 创建日期:2017-11-22 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// List<GridDetailModel>. private List GetReportDetails() { List details = new List(); DataTable table = ReportImpl.GetReportDetailPages(Model.ModuleCode); foreach (DataRow item in table.Rows) { DataTable gridColumns = ReportImpl.GetReportDetailColumns(Model.ModuleCode, item["id"] + ""); details.Add(new GridDetailModel(item, gridColumns, GridCustomColumnStruct.BaseDetailGridView)); } return details; } /// /// 获取数据源缓存 /// /// public void GetDataCaches(Dictionary cachesDic) { //全局数据 Task dynamicModelTask = cachesDic.AddTask(this, "DynamicModel", new Task(() => { return Model;//动态链接库对象 })); Task systemDllRowTask = cachesDic.AddTask(this, "SystemDllRow", new Task(() => { return MainImpl.GetSystemdllTab(Model.ModuleCode);//获取单个模块信息 })); Task sysModelTask = cachesDic.AddTask(this, "SysModel", new Task(() => { ModuleModel sysModel = new ModuleModel(systemDllRowTask.Result); return sysModel;//系统模块实体对象 })); Task> detailTask = cachesDic.AddTask(this, "Details", new Task>(() => { DataTable detailPages = ReportImpl.GetReportDetailPages(Model.ModuleCode);// List details = new List();//表格明细对象的集合 foreach (DataRow item in detailPages.Rows) { GridDetailModel gridDetailModel = new GridDetailModel(item, null, GridCustomColumnStruct.BaseDetailGridView); details.Add(gridDetailModel); Task addGridColumnsTask = cachesDic.AddTask(gridDetailModel, "GridColumns", new Task(() => { DataTable gridColumns = ReportImpl.GetReportDetailColumns(Model.ModuleCode, item["id"] + "");//获取报表明细列 gridDetailModel.GridColumns = gridColumns; return gridColumns; })); } return details; })); Task formTypeTask = cachesDic.AddTask(this, "FormType", new Task(() => { return BaseImpl.GetBaseType(Model.ModuleCode); })); Task privilegeTask = cachesDic.AddTask(this, "Privilege", new Task(() => { return Model.Privilege.Equals("3") ? "1" : Model.ModuleId > 0 ? BaseImpl.GetUserPurviewsByMenuId(Model.ModuleId + "") + "" : BaseImpl.GetUserPurviewsByMenuCode(Model.ModuleCode) + "";// 权限(1.有操作权限.0.无权限.2.只读权限.3.右键配置权限全部开放) })); //添加数据到mControl cachesDic.AddTask(mControl, "DynamicModel", dynamicModelTask); cachesDic.AddTask(mControl, "SystemDllRow", systemDllRowTask); cachesDic.AddTask(mControl, "SysModel", sysModelTask); cachesDic.AddTask(mControl, "Details", detailTask); //获取mControl控件的数据 mControl.GetDataCaches(cachesDic); } } }