zoukankan      html  css  js  c++  java
  • C# 使用委托处理个性化扩展

    近期接手一个项目,其中一个功能是显示查验报告,查验标的有60种之多,特性如下:

    1、原有的数据库设计者,为每种标的建了一个表,每个表中的字段完全不相同;

    2、有些表的数据在输出时,需要进行一些格式化,而有些表的数据则不需要;

    3、有的报表除了默认表的数据外,还需要添加一些额外的数据;

    首先,每个表对应一个报表,我们可以视其为60个报表对象,它们有一些共同的属性(如:报表编号)和方法(GetReport),我们将它们抽取出来,定义成为接口IReport;

     

    其次,为了各种数据表不同的处理方式,我们采用委托来达到这个目标,在有委托方法传入时,调用委托方法处理数据。

    解决方案:

    1、建立报告模板,使用标签替换的方式将数据替换到文本中,并在aspx页面上输出。

    2、接口设计

    View Code
    namespace TableInterface
    {
        /// <summary>
        /// 表数据读取
        /// 报告数据读取
        /// </summary>
        public interface IReport
        {
            string DBName { get; set; }
            string TableName { get; set; }
            string PrtNum { get; set; }
            string PhNum { get; set; }
            string SyNum { get; set; }
            string WtNum { get; set; }
    
            /// <summary>
            /// 获取检验报告
            /// </summary>
            /// <returns></returns>
            string GetReport();
            /// <summary>
            /// 获取数据的JSON串
            /// </summary>
            /// <returns></returns>
            string GetDataJson();
        }
    }


    3、抽象类设计,实现IReport接口

    View Code
    using System.Collections.Generic;
    using Blackice.Utility;
    using TableInterface;
    
    
    namespace ReportCreater
    {
        /// <summary>
        /// #Report使用方法
        /// 1、创建一个新的项目,以grou表名做为项目名称
        /// 2、新建Report类,引用ReportCreater.DLL,TableInterface.DLL
        /// 4、Report 继承抽象类 ReportCreater.Report
        /// 5、新建实体类 Table 
        /// 6、如果有自定义数据,请重写 GetReport 方法
        /// 7、标签规则
        ///             IList数据源的标签格式为      {$字段名称+行或列编号},如{$prtnum1}、{$prtnum2}
        ///             DataTable数据源的标签格式为  {$字段名称[行或列编号]},如{$prtnum[1]}、{$prtnum[2]}
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public abstract class Report<T>: IReport where T : class, new()
        {
            #region 委托定义
            public delegate IList<T> DataFormatDelegate(IList<T> list);
            public delegate string TemplateFormatDelegate(string template);
            #endregion
    
            #region 字段
            private string _currentTable;
            private string _backupTable;
            #endregion
    
            #region 属性
            public int MaxCol;
            public string DBName { get; set; }
            public string TableName { get; set; }
            public string PrtNum { get; set; }
            public string PhNum { get; set; }
            public string SyNum { get; set; }
            public string WtNum { get; set; }
            #endregion
    
            #region 私有函数
            private void InitTableName()
            {
                _currentTable = TableName.Replace("_bak", "_ggggg").Replace("_grou", "_ggggg").Replace("_ggggg", "_grou");
                _backupTable = _currentTable.Replace("_grou", "_bak");
            }
            /// <summary>
            /// 取得模板内容
            /// </summary>
            /// <returns></returns>
            private string GetTemplate()
            {
                var filepath = string.Format("{0}\\{1}.html", Blackice.Config.WebConfig.ReportTemplate,_currentTable);
                var strTemplate = FileHelper.ReadTextFile(filepath);
                return strTemplate;
            }
            /// <summary>
            /// 生成默认查询语句
            /// </summary>
            /// <returns></returns>
            private string GetQueryString()
            {
                var sql =
                    string.Format(
                        "(select * from {0} where prtNum='{1}' ) union all (select * from {2} where prtNum='{1}')",
                        _backupTable, PrtNum, _currentTable);
                return sql;
            }
            #endregion
    
            #region 委托函数
            /// <summary>
            /// 带委托的报告获取
            /// </summary>
            /// <param name="dataFormat">数据处理函数(替换前处理)</param>
            /// <param name="templateFormat">模板处理函数(替换后处理)</param>
            /// <returns></returns>
            public string GetReport(DataFormatDelegate dataFormat, TemplateFormatDelegate templateFormat)
            {
                InitTableName();
    
                var dataGeter = new ReportDataGeter<T>(DBName);
                var reportEngine = new ReportTemplateEngine<T>();
                //获取模板
                var strTemplate = GetTemplate();
    
                //获取数据
                var data = dataGeter.GetData(GetQueryString());
                for (var i = 0; i < (MaxCol + 2 - data.Count); i++)
                {
                    data.Add(new T());
                }
                //委托数据处理
                data = (dataFormat != null) ? dataFormat(data) : data;
    
                //替换数据
                strTemplate = reportEngine.ReplaceLabels(strTemplate, data);
    
                //委托内容处理
                strTemplate = (templateFormat != null) ? templateFormat(strTemplate) : strTemplate;
                return strTemplate;
            }
    
            #endregion
    
            #region 接口的默认实现
            /// <summary>
            /// 获取检验报告
            /// </summary>
            /// <returns></returns>
            public virtual string GetReport()
            {
                return GetReport(null, null);
            }
            public string GetDataJson()
            {
                return null;
            }
            #endregion
    
        }
    }

     4、WebUI调用

    View Code
    using System;
    using System.Reflection;
    using TableInterface;
    
    namespace Blackice.DWZ.Web.Controls
    {
        public class CReport
        {
            public static string GetReport(Model.VData obj)
            {
                string strTemp;
                try
                {
                    var tableName = obj.grou_table.Trim(' ');
                    var dllName = tableName.Replace("_bak", "_grou");
                    //反射创建类
                    var assembly = Assembly.LoadFrom(string.Format("{0}\\{1}.dll", Config.WebConfig.BinnPath, dllName));
                    var typeName = string.Format("{0}.Report", dllName);
                    var t = assembly.GetType(typeName);
    
                    //判断程序是否继承了IReport接口
                    if (t.GetInterface("IReport") != null)
                    {
                        var report = (IReport)Activator.CreateInstance(t);
    
                        report.DBName = obj.DBName;
                        report.TableName = tableName;
                        report.SyNum = obj.sy_num;
                        report.WtNum = obj.wt_num;
                        report.PrtNum = obj.prt_num;
                        report.PhNum = obj.ph_num;
                        strTemp = report.GetReport();
                    }
                    else
                    {
                        strTemp = string.Format("非法的应用程序:[{0}.dll]。", dllName);
                    }
                }
                catch (Exception ex)
                {
                    strTemp = ex.Message;
                }
                return strTemp;
            }
        }
    }

    5、扩展一个报表:我们新建一个项目,创建Table.cs数据实体,再新建一个 Report.cs继承抽象类ReportCenter.Report,覆盖原有的GetReport方法,调用委托方法完成数据替换前处理及附加数据替换。

    View Code
    using System.Collections.Generic;
    using System.Linq;
    
    namespace jggj_grou
    {
        public class Report : ReportCreater.Report<Table>
        {
            public Report()
            {
                MaxCol = 2;
            }
            /// <summary>
            /// 获得报表
            /// </summary>
            /// <returns></returns>
            public override string GetReport()
            {
                return GetReport(FormatList, ReplaceAfter);
            }
            /// <summary>
            /// 二次替换数据
            /// </summary>
            /// <param name="template"></param>
            /// <returns></returns>
            private string ReplaceAfter(string template)
            {
                var db = new ReportCreater.ReportDataGeter<Table>(DBName); 
                var dt = db.GetDataTable(string.Format("select * from jggj_record where ph_num='{0}'", PhNum));
                return (new ReportCreater.DataTableTemplateEngine()).ReplaceLabels(template, dt);
            }
            /// <summary>
            /// 对数据进行一些自定义处理
            /// </summary>
            /// <param name="list"></param>
            /// <returns></returns>
            private static IList<Table> FormatList(IList<Table> list)
            {
                foreach (var table in list.Where(table => string.IsNullOrEmpty(table.ph_num)))
                {
                    table.ph_num = "此栏空白";
                }
                return list;
            }
        }
    }

    附1:DataTable扩展

    View Code
        public static class DataTableExtensions
        {
            public static List<T> ToList<T>(this DataTable dt) where T : new()
            {
                var list = new List<T>();
                if (dt == null) return list;
                var len = dt.Rows.Count;
    
                for (var i = 0; i < len; i++)
                {
                    var info = new T();
                    foreach (DataColumn dc in dt.Rows[i].Table.Columns)
                    {
                        var value = dt.Rows[i][dc.ColumnName];
                        if (value == null || string.IsNullOrEmpty(value.ToString())) continue;
                        var p = info.GetType().GetProperty(dc.ColumnName);
    
                        try
                        {
                            if (p.PropertyType == typeof(string))
                            {
                                p.SetValue(info, value.ToString(), null);
                            }
                            else if (p.PropertyType == typeof(int))
                            {
                                p.SetValue(info, int.Parse(value.ToString()), null);
                            }
                            else if (p.PropertyType == typeof(bool))
                            {
                                p.SetValue(info, bool.Parse(value.ToString()), null);
                            }
                            else if (p.PropertyType == typeof(DateTime))
                            {
                                p.SetValue(info, DateTime.Parse(value.ToString()), null);
                            }
                            else if (p.PropertyType == typeof(float))
                            {
                                p.SetValue(info, float.Parse(value.ToString()), null);
                            }
                            else if (p.PropertyType == typeof(double))
                            {
                                p.SetValue(info, double.Parse(value.ToString()), null);
                            }
                            else
                            {
                                p.SetValue(info, value.ToString(), null);
                            }
                        }
                        catch (Exception)
                        {
                            //p.SetValue(info, ex.Message, null);
                        }
    
    
                    }
                    list.Add(info);
                }
                dt.Dispose(); dt = null;
                return list;
            }
            /// <summary>
            /// 按照属性顺序的列名集合
            /// </summary>
            public static IList<string> GetColumnNames(this DataTable dt)
            {
                DataColumnCollection dcc = dt.Columns;
                //由于集合中的元素是确定的,所以可以指定元素的个数,系统就不会分配多余的空间,效率会高点
                IList<string> list = new List<string>(dcc.Count);
                foreach (DataColumn dc in dcc)
                {
                    list.Add(dc.ColumnName);
                }
                return list;
            }
        }

    附2:通用报表标签替换类

    View Code
    using System;
    using System.Collections.Generic;
    using System.Reflection;
    
    namespace ReportCreater
    {
        /// <summary>
        /// 通用报表标签替换类
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public class ReportTemplateEngine<T>
        {
    
            /// <summary>
            /// 替换标签
            /// </summary>
            /// <param name="template">模板数据</param>
            /// <param name="list">IList数据源</param>
            /// <returns></returns>
            public string ReplaceLabels(string template, IList<T> list)
            {
                if (list == null) { return template; }
                try
                {
                    for (var index = 0; index < list.Count; index++)
                    {
                        var obj = list[index];
                        var infos = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
                        var columIndex = index + 1;
                        foreach (var info in infos)
                        {
                            string value = GetFieldValue(obj, info);
                            var field = @"{$" + info.Name + columIndex + @"}";
                            template = template.Replace(field, value);
                        }
                    }
                }
                catch (Exception) { }
                return template;
            }
            /// <summary>
            /// 获取字段的值
            /// </summary>
            /// <param name="obj"></param>
            /// <param name="info"></param>
            /// <returns></returns>
            private string GetFieldValue(T obj, PropertyInfo info)
            {
                string value;
                try
                {
                    value = info.GetValue(obj, null).ToString();
                }
                catch (Exception)
                {
                    value = "---";
                }
                if (string.IsNullOrEmpty(value.Trim(' ')))
                {
                    value = "---";
                }
                return value;
            }
    
        }
    }

    附3:通用DataTable标签替换类

    View Code
    using System;
    using System.Data;
    
    namespace ReportCreater
    {
        /// <summary>
        /// 通用DataTable标签替换类
        /// </summary>
        public class DataTableTemplateEngine
        {
            /// <summary>
            /// 替换标签
            /// </summary>
            /// <param name="template">模板内容</param>
            /// <param name="dt">DataTable数据</param>
            /// <returns></returns>
            public string ReplaceLabels(string template, DataTable dt)
            {
                if (dt == null) { return template; }
                try
                {
                    for (var index = 0; index < dt.Rows.Count; index++)
                    {
                        var obj = dt.Rows[index];
                        var infos = dt.GetColumnNames();
                        var columIndex = index + 1;
                        foreach (var info in infos)
                        {
                            var value = GetFieldValue(info, obj);
                            var field = @"{$" + info + "[" + columIndex + "]" + @"}";
                            template = template.Replace(field, value);
                        }
                    }
                }
                catch (Exception) { }
                return template;
            }
            /// <summary>
            /// 获取字段的值
            /// </summary>
            /// <param name="info"></param>
            /// <param name="obj"></param>
            /// <returns></returns>
            private string GetFieldValue(string info, DataRow obj)
            {
                string value;
                try
                {
                    value = obj[info].ToString();
                }
                catch (Exception)
                {
                    value = "---";
                }
                if (string.IsNullOrEmpty(value.Trim(' ')))
                {
                    value = "---";
                }
                return value;
            }
    
        }
    }

    附4:报告数据读取类

    View Code
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Reflection;
    using SqlHelper;
    
    namespace ReportCreater
    {
        /// <summary>
        /// 报告数据读取类
        /// </summary>
        public class ReportDataGeter<T> where T : new()
        {
            private IDatabase _conn { get; set; }
            private readonly string _dbName;
            public ReportDataGeter(string dbname)
            {
                _dbName = dbname;
                _conn = GetDatabase();
            }
            /// <summary>
            /// 获取数据库连接
            /// </summary>
            /// <returns></returns>
            private IDatabase GetDatabase()
            {
                //根据指定的dbname反射创建数据访问接口
                var assembly = Assembly.LoadFrom(string.Format("{0}\\SqlHelper.dll", Blackice.Config.WebConfig.BinnPath));
                var typeName = string.Format("SqlHelper.{0}DB", _dbName);
                var t = assembly.GetType(typeName);
                var db = (IDatabase)Activator.CreateInstance(t);
                return db;
            }
            /// <summary>
            /// 执行SQL语句获取数据
            /// </summary>
            /// <param name="sql"></param>
            /// <returns></returns>
            public DataTable GetDataTable(string sql)
            {
                return _conn.Execute(sql);
            }
            /// <summary>
            /// 执行SQL语句获取数据,并转换为LIST
            /// </summary>
            /// <param name="sql">指定的SQL命令</param>
            /// <returns></returns>
            public IList<T> GetData(string sql)
            {
                var dt = GetDataTable(sql);
                IList<T> list = dt.ToList<T>();
                return list;
            } 
        }
    }
  • 相关阅读:
    任务二 发布作业信息(已完成)
    查看作业信息(任务一 已完成)
    项目冲刺任务之任务场景分析(四)
    项目冲刺之任务场景分析(三)
    解析XML文件的两种方式 SAX和DOM
    解析XML文件的两种方式 SAX和DOM
    iOS开发代码规范(通用)
    随机创建点击对象
    自定义加载等待框(MBProgressHUD)
    KVO、KVC
  • 原文地址:https://www.cnblogs.com/blackice/p/2634198.html
Copyright © 2011-2022 走看看