zoukankan      html  css  js  c++  java
  • YbSoftwareFactory 代码生成插件【三】:二次开发之 IPlugInRepository 接口的实现

        每个公司为加快项目的开发效率,都会使用一些成熟的框架或组件,然后在此基础之上进行开发。YbSoftwareFactory也可复用这些框架和组件,通过二次开发来开发一个代码生成插件,把大部分和框架有关的公共代码和组件封装打包压缩到项目文件中,而把和具体业务管理有关的需要变化的代码使用T4模板来生成。然后使用该代码生成插件来快速生成一个适合自身开发习惯的可立即运行的解决方案来提高开发进度,然后在此基础之上进行后续代码的二次开发。

        曾经的某公司用户在使用了YbSoftwareFactory来进行首个项目的辅助开发,原本计划28天的项目编码任务仅仅只用了3天,这3天的工作量也就是进行个性化的界面呈现调整和统计报表的制作,因为代码生成插件所生成的解决方案和代码已经集成了身份认证、权限管理、验证规则、日志输出等公共功能以及实体的增、删、查、改和导出个性化功能,工作效率的提高程度由此可见。

        前一篇文章已经介绍了怎样实现 IPlugInGroupRepository 接口来完成插件组的开发,本章则介绍插件二次开发的最后一项任务,即插件组内各个插件怎样实现 IPlugInRepository 接口来完成插件的二次开发。

        IPlugInRepository的实现类主要的职责就是完成代码的生成。 首先来看看IPlugInRepository的接口定义:

    IPlugInRepository 接口定义
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Yb.PlugIn.Base;

    namespace Yb.PlugIn.Base
    {
        public interface IPlugInRepository
        {
            /// <summary>
            
    /// 生成进度通知有关的事件
            
    /// </summary>
            event EventHandler<NotifyChangedEventArgs> NotifyChanged;
            ///// <summary>
            
    ///// 代码生成插件组,包含相关的一组插件,每个插件可生成不同类型的代码
            
    ///// </summary>
            //IPlugInGroupRepository GroupRepository { get; set; }
            /// <summary>
            
    /// 获取模板信息
            
    /// </summary>
            
    /// <returns></returns>
            IEnumerable<TemplateInfo> GetTemplateInfos();

            /// <param name="arg">/// <summary>
            
    /// 生成代码前的操作,如创建目录,解压文件等
            
    /// </summary>
            
    /// <param name="arg">1、解压后的路径</param></param>
            void BeforeBuild(object arg);
            /// <summary>
            
    /// 生成代码
            
    /// </summary>
            
    /// <param name="arg">数据源</param>
            
    /// <param name="templateInfos">The template infos.</param>
            
    /// <returns></returns>
            IEnumerable<TemplateInfo> BuildCodes(object arg, IEnumerable<TemplateInfo> templateInfos);

            /// <summary>
            
    /// 输出代码,如写文件或者显示等
            
    /// </summary>
            
    /// <param name="outputMode">输出模式,如输出文件则会依次执行 BeforeBuild,BuildCodes,AfterBuild</param>
            
    /// <param name="beforeBuildArg">开始生成代码前事件</param>
            
    /// <param name="argument">数据源</param>
            
    /// <param name="templateInfos">The template infos.</param>
            
    /// <param name="afterBuildArg">开始生成代码后参数</param>
            
    /// <returns></returns>
            IEnumerable<TemplateInfo> BuildCodes(object beforeBuildArg, object argument, IEnumerable<TemplateInfo> templateInfos, object afterBuildArg);
            /// <summary>
            
    /// 代码生成后的任务,如运行数据库初始化脚本等
            
    /// </summary>
            
    /// <param name="arg">1、连接字符串</param>
            void AfterBuild(object arg);
        }
    }

        下面将通过一个Demo来介绍接口下各个方法和属性的含义。

        一、元数据定义

    View Code
        [PlugInMetadataAttribute(Name = "解决方案",
            Description = "生成Castel数据访问层,DevExpress界面层代码的解决方案",
            DisplayOrder = 1,
            ImageUri = "pack://application:,,,/Yb.PlugIn.CastleDevExpress.WebForm;component/Images/WebFormSolution.png",
            LargeImageUri = "pack://application:,,,/Yb.PlugIn.CastleDevExpress.WebForm;component/Images/WebFormSolution.png",
            CodeOutputMode = CodeOutputMode.File)]
        [Export(StaticResources.PlugInGroupKey,typeof(IPlugInRepository))]
        public class CastleDxWebSolutionPlugInRepository : CastleDxWebPlugInRepositoryBase

        Name:将在Ribbion控件中显示的本插件的名称

        DisplayOrder:显示顺序

        ImageUri和LargeImageUri:将显示的个性化图标的URI路径,可参考上篇文章。

        CodeOutputMode:代码生成模式,File和Preview可选,File模式将生成代码文件,通常用于完整的解决方案的生成。Preview将显示预览的代码窗口,通常用于实体层、数据访问层、界面层等某一类的代码生成,生成的代码可预览、编辑并输出到文件。

         二、BeforeBuild方法

        本方法主要在代码生成前执行,主要可用于解压项目文件到指定路径,如你无这方面的需求可不用重写,传入的 arg 参数为文件路径。以下是某个具体的实现代码:

    BeforeBuild 方法
    /// <summary>
            
    /// 解压文件到指定路径
            
    /// </summary>
            
    /// <param name="arg">解压路径</param>
            public override void BeforeBuild(object arg)
            {
                if (arg == null)
                {
                    throw new ArgumentNullException("arg""参数不能为空");
                }
                var path = arg.ToString();
                if (string.IsNullOrWhiteSpace(path))
                {
                    throw new ArgumentNullException("arg""解压路径不能为空");
                }
                OnNotifyChanged(new NotifyChangedEventArgs(NotifyType.Infomation, "正在解压文件,请稍候"));
                //解压文件到指定路径
                FileUtility.ExtractFileTo(ZipFileRelativePath,path);
                OnNotifyChanged(new NotifyChangedEventArgs(NotifyType.Infomation, "解压文件结束"));
            }

        三、GetTemplateInfos 方法

        本方法返回本插件代码生成所需的模板信息记录列表,这些模板对象将供 YbSoftwareFactory 处理,代码示例如下:

    GetTemplateInfos 方法
    /// <summary>
            
    /// 获取本插件所需的模板信息
            
    /// </summary>
            
    /// <returns></returns>
            public override IEnumerable<TemplateInfo> GetTemplateInfos()
            {
                var templateInfo = base.GetTemplateInfos();
                return templateInfo.Where(c => c.BuildEnable && (c.Tag & StaticResources.SolutionPlugInTemplateTag) > 0);
            }

        四、BuildCodes 方法

        本方法为代码生成的核心代码,其中arg参数为一个表信息记录列表,templateInfos为模板信息,生成后的代码将保存到模板信息的“ExportContent”字段并返回。

    BuildCodes 方法
    /// <summary>
            
    /// 生成代码
            
    /// </summary>
            
    /// <param name="arg"></param>
            
    /// <param name="templateInfos"></param>
            
    /// <returns></returns>
            public override IEnumerable<TemplateInfo> BuildCodes(object arg, IEnumerable<TemplateInfo> templateInfos)
            {
                //参数类型转换
                var tableInfos = BaseInfoUtility.ObjectToTableInfoList(arg).Where(c=>c.IsSelected).ToList();

                //生成结果
                var templateList = new List<TemplateInfo>();
                _totalCount = tableInfos.Count() * (templateInfos.Count() - 3) + 3;
                _currentIndex = 0;

                foreach (var templateInfo in templateInfos)
                {
                    if(!templateInfo.BuildEnable) continue;
                    //读模板信息
                    templateInfo.TemplateContent = FileUtility.ReadFile(templateInfo.TemplateRelativePath);
                    //判断模板类型,是否每张表都需生成一个模板
                    if ((templateInfo.Tag & StaticResources.IsTableInfoListOfTemplateArg) == 0)
                    {
                        foreach (var tableInfo in tableInfos)
                        {
                            //复制模板,防止生成后下一个循环被覆盖
                            var currentTemplateInfo = (TemplateInfo)templateInfo.Clone();
                            //生成代码
                            BuildTableInfoCode("CurrentTable", templateList, tableInfo, currentTemplateInfo);
                        }
                    }
                    else
                    {
                        //生成 Web.Config 文件
                        if (templateInfo.ExportFileNameFormatString.Equals("Web.config",StringComparison.OrdinalIgnoreCase))
                        {
                            //创建Web.Config代码
                            BuildWebConfigCode(templateList, templateInfo, tableInfos);
                        }
                        else
                        {
                            //创建如项目文件等需要传入“表对象集合”为参数的模板代码
                            BuildTableInfosCode(templateList, templateInfo, tableInfos);
                        }
                    }
                }
                return templateList;
            }

        五、AfterBuild方法

        AfterBuild方法主要在代码生成后进行一些后续处理操作,你可利用该方法进行一些任务,如安装数据库初始化脚本等,示例代码如下:

    AfterBuild 方法
    /// <summary>
            
    /// 安装和权限有关的数据库脚本
            
    /// </summary>
            
    /// <param name="arg"></param>
            public override void AfterBuild(object arg)
            {
                if (arg == null || string.IsNullOrWhiteSpace(arg.ToString())) return;
                var connStr = arg.ToString();
                OnNotifyChanged(new NotifyChangedEventArgs(NotifyType.Infomation, "正在安装数据库脚本"));
                try
                {
                    //执行创建表的脚本文件
                    ExecuteSqlServerDbScript(connStr);
                    //进度通知
                    OnNotifyChanged(new NotifyChangedEventArgs(NotifyType.Infomation, "数据库脚本处理完成"));
                }
                catch (Exception er)
                {
                    //进度通知
                    OnNotifyChanged(new NotifyChangedEventArgs(NotifyType.Infomation,string.Format("数据库脚本安装失败,{0}",er.Message)));
                }
    }

        六、OnNotifyChanged方法

        该方法主要进行事件通知,在界面上显示滚动条等。

    附下载地址:

        “Yb.PlugIn.CastleDevExpress.WebForm”插件源码下载

        附“Yb.PlugIn.CastleDevExpress.WebForm”代码生成插件的Demo数据库下载

         YbSoftwareFactory主应用程序下载

     

  • 相关阅读:
    XMPP Openfire集成windows身份认证
    WIF claimsbased identity
    VMWare Workstation使用总结几则
    把成熟的代码从.NET移植到Mono 【转】
    工作流jBPM使用总结
    C++实现的IO高效的算法TPIE
    XMPP的简介和基本概念
    NoSQL学习路线图 使用 NoSQL 数据库分析大规模数据[转]
    Spring Security 3 网站安全授权
    jBPM 5 的点滴
  • 原文地址:https://www.cnblogs.com/gyche/p/2484697.html
Copyright © 2011-2022 走看看