基于AgileEAS.NET SOA 中间件领域模型数据器快速打造自己的代码生成器

一、前言

     AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台。用于帮助中小型软件企业建立一条适合市场快速变化的开发团队,以达到节省开发成本、缩短开发时间,快速适应市场变化的目的。

     AgileEAS.NET SOA中间件平台提供了敏捷快速开发软件工程的最佳实践,通过提供大量的基础支撑功能如IOC、ORM、SOA、分布式体系及敏捷并发开发方法所支撑的插件开发体系,以及提供了大量的实体、数据模型设计生成工具、代码生成工具,用于帮助中小软件开发商快速成长。

     AgileEAS.NET平台充分把握目前软件行业快速发展的新趋势,基于敏捷并行开发、快速适应市场这样淳朴的软件工程实践,采用业界广泛使用的Microsoft .Net构件(组件)开发技术实践了这种开发思想,帮助软件企业实现“敏捷变化、快速适合”的目标,从而帮助软件企业在激烈的市场竞争中赢得先机并获得更高的回报。

二、关于领域模型设计器

      AgileEAS.NET SOA 中间件平台一直努力为广大的程序员弟兄们提供更方便、更轻松、更简单的开发体验,所以除了提供容器、ORM、Linq、通信、SOA、消息总线等各种强大的类库之外,还努力为广大的程序员弟兄们提供优秀的开发工具集,其中就包括我们认为了最有价值的领域模型设计器。

image

      AgileEAS.NET SOA 中间件平台领域模型设计器提供领域(数据库)建模、数据库文档生成、实体代码(业务或其他代码)生成、DDL脚本生成有等一系列强大的功能。

      领域模型设计器不仅支持对单一模型的定义,也可以定义各种模型之间的关系,目前支持模块的引用实体(类似外键引用)、子实体(父子关系)定义,也支持扩展的属性和枚举对象的关联引用定义。

image

image

image 

image

image
     应用AgileEAS.NET SOA 中间件进行开发,我们倡导使用优先进行模型设计的思路,而不是优先进行数据库结构设计,一是思路上面模型优先,另外一个是当完后模型之后,系统就能导出数据库设计文档,大大节省重复工具,并且能提高文档效率。

image

     基于此种思路也能保证文档与数据库、代码是强一致的,不会产生文档与程序,与数据库对不上的情况,这种情况在很多很多的软件企业应该是常事,控制文档、代码、数据库一致性的成本很高,使用AgileEAS.NET SOA 中间件平台领域模型设计器并应用此种思路则能很好的解决此问题。

image

     生成模型对应数据表的脚本,目前支持SQLServer、ORACLE、Mysql、SqlLite四种数据库,DLL脚本可以一个对象一个对象生成,也可以选择统一生成解决方案之中的所有脚本。

image

     代码生成,生成对应的模型定义代码,单模型代码以及模型之间的关联关系,模型与枚举的关联关系。

image

     领域模型设计器提供了直接输出解决方案的功能,即可以直接生成可供VS开发工具直接打的项目或者解决方案。

image

三、领域模型设计器插件机制详解

     AgileEAS.NET SOA 中间件平台领域模型设计器在众多的合作伙伴以及社区朋友的使用过程之中,我们一直接受一些客户和社区朋友的反馈进行完善和改进,有很多的社区朋友都有这样的一个需求,有的朋友开发了自己的ORM框架,但是自己写一个类似于我们领域模型设计器这样的功能成本又非常的大,所以希望我们能提供一种插件机制能实现他自己的代码生成功能,别外,我们的一些客户在项目之中也需要应用到一些第三方的产品(比如医院进行集成的ESB平台),这些产品也提供一些二次开发功能,其中就有需求生成模型定义代码。

      基于各种反馈,我们决定为 AgileEAS.NET SOA 中间件平台领域模型设计器提供插件功能,来实现各种客户和社区朋友的需求,目前我们提供了两种插件,一种是代码生成插件,另外是单一的界面插件。

image

     代码生成插件用于替换内置的代码生成插件,用于生成自己的各种模型代码,界面生成插件用于处理当前正在打开的解决方案。

     为了实现这种需求,我们定义义两个接口:

     代码生成插件接口ICodeGenerator:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EAS.Design
{
    /// <summary>
    /// 代码生成器接口,用于完成代码生成。
    /// </summary>
    public interface ICodeGenerator
    {
        /// <summary>
        /// 代码方案名称。
        /// </summary>
        string Name
        {
            get;
        }

        /// <summary>
        /// 生成数据表对象及表列信息生成代码。
        /// </summary>
        /// <param name="rootEntity">表信息。</param>
        /// <param name="project">工作项目信息。</param>
        /// <returns>生成代码结果。</returns>
        string GeneratCode(RootEntity rootEntity,Project project);

        /// <summary>
        /// 生成枚举对象代码。
        /// </summary>
        /// <param name="enumeration">枚举对象。</param>
        /// <param name="project">工作项目信息。</param>
        /// <returns>生成代码结果。</returns>
        string GeneratCode(Enumeration enumeration, Project project);

        /// <summary>
        /// 输出/生成解决方法。
        /// </summary>
        /// <param name="project">项目元数据。</param>
        /// <param name="outputFolder">输出路径。</param>
        /// <param name="haveSolution">是否生成解决方案。</param>
        void GeneratSolution(Project project, string outputFolder, bool haveSolution = false);
    }
}

     ICodeGenerator接口之中定义一个Name属性,用于返回插件名称,以及用于生成单一实体和枚举的GeneratCode方法,以后生成整体解决方案的GeneratSolution定义,要实现自己的代码生成插件,就必须实现本接口。

     界面插件接口IDesignAddIn:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EAS.Design
{
    /// <summary>
    /// 元数据设计器插件。
    /// </summary>
    public interface IDesignAddIn
    {
        /// <summary>
        /// 插件名称。
        /// </summary>
        string Name
        {
            get;
        }

        /// <summary>
        /// 执行插件。
        /// </summary>
        /// <param name="workProject">当前项目。</param>
        void Start(Project workProject);
    }
}

     IDesignAddIn接口之中定义比较简单, 除了插件名称Name定义,就只有一个Start方法,用于处理当前的解决方案项目,在领域模型设计器的插件菜单下的“列名大小写切换”就是一个内置IDesignAddIn插件,其代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using EAS.Loggers;
using EAS.Design.CodeGenerator;

namespace EAS.Design.UI
{
    class ColumnNameSwAddIn:EAS.Design.IDesignAddIn
    {
        #region IDesignAddIn 成员

        string IDesignAddIn.Name
        {
            get
            {
                return "列名大小写切换";
            }
        }

        public void Start(Project workProject)
        {
            ColumnNameSwForm form = new ColumnNameSwForm();
            form.Project = workProject;
            form.StartPosition = FormStartPosition.CenterScreen;
            form.ShowDialog();
        }

        #endregion
    }

    partial class ColumnNameSwForm : Form
    {
        internal Project Project
        {
            get;
            set;
        }

        public ColumnNameSwForm()
        {
            InitializeComponent();
        }

        private void btnGenerat_Click(object sender, EventArgs e)
        {
            foreach (var item in this.Project.RootEntities)
            {
                if (this.rbUpper.Checked && this.cbTableName.Checked && !string.IsNullOrEmpty(item.MapTable))
                {
                    item.MapTable = item.MapTable.ToUpper();
                }
                else if (!this.rbUpper.Checked && this.cbTableName.Checked && !string.IsNullOrEmpty(item.MapTable))
                {
                    item.MapTable = item.MapTable.ToLower();
                }

                if (this.cbColumnName.Checked)
                {
                    foreach (var column in item.Properties)
                    {
                        if (string.IsNullOrEmpty(column.ColumnName))
                            column.ColumnName = column.Name;

                        if (this.rbUpper.Checked)
                        {
                            column.ColumnName = column.ColumnName.ToUpper();
                        }
                        else 
                        {
                            column.ColumnName = column.ColumnName.ToLower();
                        }
                    }
                }
            }

            MessageBox.Show("处理完成,请重新打开相关模型!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            this.Close();
        }
    }
}

     这两个接口以及接口涉及的数据结构均定义于EAS.Metadata.dll程序集之累,其中:

     Project:解决方案,包括其中的实体、枚举定义。

     RootEntity:实体模块定义。

     Enumeration:枚举对象定义。

四、代码插件实现、快速打造自己的代码生成器

    此前,有一个朋友自己实现了一个领域模型设计器的代码生成插件,用于生成Castle ActiveRecord的实体代码,并且也愿意把实现源码贡献出来,所以我们就基于此进行一点说明。

     要实现代码生成插件,我们首先要建一个类库项目,并且引用EAS.Metadata.dll程序集,建立一个类并实现ICodeGenerator接口,项目代码结构如下:

image

     实现插件接口的必须属性和方法之后,我们编译代码,并且把生成的EAS.MetaDesign.CodeAddIn.AR.dll复制到EAS.MetaDesigner.exe同一目录,并且打开领域模型设计器进行配置。

image

     完成设计之后重新打开领域模型设计器,我们打开一个实体,可以看到生成的代码已经发生了变更:
image

     同时在领域模型设计器的“输出”=》“生成代码”菜单子项这中,出现了“Castle.AR”菜单,用于输出整个解决方案代码。image

     到此,我们尼桑:

五、例子代码下载

     本文涉及的领域模型设计器代码插件例子,源代码已经一并放在了AgileEAS.NET SOA 中间件的最新版之中,请大请通过AgileEAS.NET SOA 中间件平台官方网站下载,或者通过以下方式下载:

     直接下载:AgileEAS.NET SOA 5.2 下载http://112.74.66.105/downloads/eas/agileeas.net.5.rar

     SVN更新:https://112.74.66.105/svn/eas/5.0,登录用户:eas,密码eas.

     AgileEAS.NET SOA 中间件平台管理员:Administrator,登录密码sa

     直接下载的压缩包可能会有一定的时间差,即有可能不一定是最新版本,建议大家都通过SVN下载最新版本。

六、联系我们

     为了完善、改进和推广AgileEAS.NET而成立了敏捷软件工程实验室,是一家研究、推广和发展新技术,并致力于提供具有自主知识产权的业务基础平台软件,以及基于业务基础平台了开发的管理软件的专业软件提供商。主要业务是为客户提供软件企业研发管理解决方案、企业管理软件开发,以及相关的技术支持,管理及技术咨询与培训业务。

     AgileEAS.NET平台自2004年秋呱呱落地一来,我就一直在逐步完善和改进,也被应用于保险、医疗、电子商务、房地产、铁路、教育等多个应用,但一直都是以我个人在推广,2010年因为我辞职休息,我就想到把AgileEAS.NET推向市场,让更多的人使用。

     技术团队成员都是合作多年的老朋友,因为这个平台是免费的,我们的营运开支主要靠为客户提供咨询服务所得,我们都是因为程序员的那种理想与信念坚持,在此我感谢一起奋斗的朋友和一直支持我们工作的客户、朋友。

团队网站:http://www.agilelab.cn

AgileEAS.NET网站:http://www.agileeas.net

官方博客:http://eastjade.cnblogs.com

github:https://github.com/agilelab/eas

QQ:47920381

AgileEAS.NET QQ群:

113723486(AgileEAS SOA 平台)/上限2000人

199463175(AgileEAS SOA 交流)/上限2000人

116773358(AgileEAS.NET SOA 平台)/上限2000人

邮件:james@agilelab.cn,mail.james@qq.com,

电话:18629261335。

posted @ 2016-06-28 17:48  魏琼东  阅读(2443)  评论(8编辑  收藏  举报