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;
        } 
    }
}
原文地址:https://www.cnblogs.com/blackice/p/2634198.html