插件开发 之 生成代码

插件开发 之 生成代码

三个步骤了解插件开发:

    步骤一:了解插件开发接口

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

namespace ZM.PH.PlugInInterface
{
    
/// <summary>
    
/// 表示生成代码的接口。
    
/// </summary>
    
/// <remarks>欲了解此接口,请参考PlugIns项目中的Demo_GenCode.cs</remarks>
    public interface IGenSymLanguage
    {
        
/// <summary>
        
/// 获取 代码层的集合,将从此获取生成的代码相关信息(详见 GenCodeLayer.cs)。
        
/// </summary>
        List<GenCodeLayer> CodeLayers { get; }

        
/// <summary>
        
/// 获取代码层相关命名规则(类Namespace和类名称规则),即告诉客户默认的代码层命名规则,请从 CodeLayers获取生成结果。
        
/// </summary>
        void GetNamingRules();

        
/// <summary>
        
/// 根据用户设置的代码层命名规则为某一具体数据表生成代码层命名实例(类Namespace和类名称),请从CodeLayers获取生成结果。
        
/// </summary>
        
/// <param name="table">表示数据表的对象</param>
        void GetNamingRules(IDBTable table);

        
/// <summary>
        
/// 生成代码。
        
/// </summary>
        
/// <param name="table">表示当前要生成代码的数据表(请了解IDBTable及其它数据库对象的结构)</param>
        
/// <remarks>
        
///     获取当前表所有数据列:IDBTable.Columns
        
///     获取与当前表关联的存储过程:IDBProcedure.AssociatedTable = IDBTable
        
/// </remarks>
        void Gen(IDBTable table);

        
/// <summary>
        
/// 清除所有不需要的对象。
        
/// </summary>
        void ClearAllUnused();
    }
}

    步骤二:了解数据库对象实体


1. 项目PlugInInterface/IEntities 为数据库实体接口。
2. 项目PlugInInterface/DBEntities 抽象出数据库实体对象,继承数据库实体接口,同时也是其它具体数据库实体的基类。
3. 项目PlugIns/Entities_Sqlserver 为Sqlserver数据库实现的数据库实体对象,分别继承自PlugInInterface/DBEntities。
4. 项目PlugIns/Entities_SQLite 为Sqlite数据库实现的数据库实体对象,分别继承自PlugInInterface/DBEntities。
5. 项目PlugIns/Entities_MySql 为MySql数据库实现的数据库实体对象,分别继承自PlugInInterface/DBEntities。
6. PamProgram及所有子类 为初始化相关插件提供的构造器参数。

    步骤三:看一个简单的插件Demo

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

using ZM.PH.PlugInInterface;

namespace ZM.PH.PlugIns
{
    
/// <summary>
    
/// 生成代码演示,以petshop架构为例。
    
/// </summary>
    [PluginInfo("2bf2331c-d7e3-4b9b-aaab-9b5ca8c8787f""插件开发Demo""1.0.0.0""版权所有(2005-2008) mrhgw""mrhgw""http://www.mrhgw.cn""生成代码示例插件(仿petshop结构), 仅提供插件开发者进行参考。")]
    
public class Demo_GenCode : IGenSymLanguage
    {
        
#region 构造器

        
/// <summary>
        
/// 构造器。
        
/// </summary>
        
/// <param name="_pamProgram">生成代码所需的参数类</param>
        public Demo_GenCode(PamProgram_GenSymLanguage _pamProgram)
        {
            
this.pamProgram = _pamProgram;
        }

        
#endregion

        
#region 变量

        
/// <summary>
        
/// 生成代码所需的参数类。
        
/// </summary>
        private PamProgram_GenSymLanguage pamProgram = null;
        
/// <summary>
        
/// 代码层的集合。
        
/// </summary>
        private List<GenCodeLayer> _codeLayers = new List<GenCodeLayer>();

        
#endregion

        
#region 静态对象

        
/// <summary>
        
/// 分层代码的关键字(仿petshop结构)。
        
/// </summary>
        public enum CodeLayerKeys
        {
            Model,
            IDAL,
            DAL,
            DALFactory,
            BLL
        }

        
#endregion

        
#region IGenSymLanguage 成员

        
/// <summary>
        
/// 获取 代码层的集合,将从此获取生成的代码相关信息(详见 GenCodeLayer.cs)。
        
/// </summary>
        public List<GenCodeLayer> CodeLayers
        {
            
get { return this._codeLayers; }
        }

        
/// <summary>
        
/// 获取代码层相关命名规则(类Namespace和类名称规则),即告诉客户默认的代码层命名规则,请从 CodeLayers获取生成结果。
        
/// </summary>
        public void GetNamingRules()
        {
            
/*以下以petshop为例,告诉客户默认的类命名和命名空间规则。
             *  命名空间规则为(Namespace):
             *   层Model:YouProject.Model
             *   层IDAL:YouProject.IDAL
             *   层DAL:YouProject.DAL
             *   层DALFactory:YouProject.DALFactory
             *   层BLL:YouProject.BLL
             * 
             *  类命名规则为(Class Name,<T>表示数据表名称):
             *   层Model:<T>Info
             *   层IDAL:I<T>
             *   层DAL:<T>
             *   层DALFactory:DataAccess
             *   层BLL:<T>
             
*/

            
//清空。
            this._codeLayers.Clear();

            
foreach (string _name in Enum.GetNames(typeof(CodeLayerKeys)))
            {
                CodeLayerKeys _en 
= (CodeLayerKeys)Enum.Parse(typeof(CodeLayerKeys), _name);
                
//初始化代码层对象。
                GenCodeLayer gcLayer = new GenCodeLayer(_name);

                
//特别说明:<T>表示数据表名称;<DB>表示数据库名称。
                switch (_en)
                {
                    
case CodeLayerKeys.Model:
                        gcLayer.ClassName 
= "<T>Info";
                        gcLayer.Namespace 
= "YouProject.Model";
                        
break;
                    
case CodeLayerKeys.IDAL:
                        gcLayer.ClassName 
= "I<T>";
                        gcLayer.Namespace 
= "YouProject.IDAL";
                        
break;
                    
case CodeLayerKeys.DAL:
                        gcLayer.ClassName 
= "<T>";
                        gcLayer.Namespace 
= "YouProject.DAL";
                        
break;
                    
case CodeLayerKeys.DALFactory:
                        gcLayer.ClassName 
= "DataAccess";
                        gcLayer.Namespace 
= "YouProject.DALFactory";
                        
break;
                    
case CodeLayerKeys.BLL:
                        gcLayer.ClassName 
= "<T>";
                        gcLayer.Namespace 
= "YouProject.BLL";
                        
break;
                }

                
this._codeLayers.Add(gcLayer);
            }
        }

        
/// <summary>
        
/// 根据用户设置的代码层命名规则为某一具体数据表生成代码层命名实例(类Namespace和类名称),请从CodeLayers获取生成结果。
        
/// </summary>
        
/// <param name="table">表示数据表的对象</param>
        public void GetNamingRules(IDBTable table)
        {
            
//清空。
            this._codeLayers.Clear();

            
foreach (string _name in Enum.GetNames(typeof(CodeLayerKeys)))
            {
                CodeLayerKeys _en 
= (CodeLayerKeys)Enum.Parse(typeof(CodeLayerKeys), _name);
                
//初始化代码层对象。
                GenCodeLayer gcLayer = new GenCodeLayer(_name);

                
//获取类的命名规则。
                
//this.pamProgram.ClassNamingRules 是用户确定的命名规则。
                string classNamingRule = this.GetValueByKey(this.pamProgram.ClassNamingRules, _name);
                
//将表示为数据表的特殊字符串<T>替换为表名称(此处可能还需要去除表前缀,大写小格式化等,有需要自己添加)。
                classNamingRule = classNamingRule.Replace("<T>", table.Name);

                
//获取类命名空间的命名规则。
                
//this.pamProgram.NamespaceNamingRules 是用户确定的命名空间规则。
                string nsNamingRule = this.GetValueByKey(this.pamProgram.NamespaceNamingRules, _name);
                
//将表示为数据库的特殊字符串<DB>替换为数据库名称。
                nsNamingRule = classNamingRule.Replace("<DB>", table.OwnerDB.Name);


                gcLayer.ClassName 
= classNamingRule; //设置类名称。
                gcLayer.Namespace = nsNamingRule; //设置类的命名空间。
                gcLayer.SymLanguage = SymLanguages.CSharp; //代码语言类别。
                gcLayer.FileExtension = ".cs"//设置类保存为文件的扩展名。

                
//确定DALFactory层的代码不需要保存为一个独立的文件。
                
//Petshop中,所有反射创建数据访问对象是统一保存为一个文件,不要每个表独立保存为一个文件的。
                if (_en == CodeLayerKeys.DALFactory)
                    gcLayer.IndependentSave 
= false;
                
//加入集合中。
                this._codeLayers.Add(gcLayer);
            }
        }

        
/// <summary>
        
/// 生成代码。
        
/// </summary>
        
/// <param name="table">表示当前要生成代码的数据表(请了解IDBTable及其它数据库对象的结构)</param>
        
/// <remarks>
        
///     获取当前表所有数据列:IDBTable.Columns
        
///     获取与当前表关联的存储过程:IDBProcedure.AssociatedTable = IDBTable
        
/// </remarks>
        public void Gen(IDBTable table)
        {
            
//清空。
            this._codeLayers.Clear();

            
foreach (string _name in Enum.GetNames(typeof(CodeLayerKeys)))
            {
                CodeLayerKeys _en 
= (CodeLayerKeys)Enum.Parse(typeof(CodeLayerKeys), _name);
                
//初始化代码层对象。
                GenCodeLayer gcLayer = new GenCodeLayer(_name);

                
//获取类的命名规则。
                string classNamingRule = this.GetValueByKey(this.pamProgram.ClassNamingRules, _name);
                
//将表示为数据表的特殊字符串<T>替换为表名称(此处可能还需要去除表前缀,大写小格式化等,有需要自己添加)。
                classNamingRule = classNamingRule.Replace("<T>", table.Name);

                
//获取类命名空间的命名规则。
                string nsNamingRule = this.GetValueByKey(this.pamProgram.NamespaceNamingRules, _name);
                
//将表示为数据库的特殊字符串<DB>替换为数据库名称。
                nsNamingRule = classNamingRule.Replace("<DB>", table.OwnerDB.Name);


                gcLayer.ClassName 
= classNamingRule; //设置类名称。
                gcLayer.Namespace = nsNamingRule; //设置类的命名空间。
                gcLayer.SymLanguage = SymLanguages.CSharp; //代码语言类别。
                gcLayer.FileExtension = ".cs"//设置类保存为文件的扩展名。

                
//设置生成的代码,本插件最核心的功能在此实现。
                
//此示例为demo,真实插件需要根据业务编写更为复杂的代码。
                gcLayer.Code = "hollow!这是代码层 " + _name + " 的代码。"

                
//确定DALFactory层的代码不需要保存为一个独立的文件。
                
//Petshop中,所有反射创建数据访问对象是统一保存为一个文件,不要每个表独立保存为一个文件的。
                if (_en == CodeLayerKeys.DALFactory)
                {
                    gcLayer.BittyCodeReplacemen 
= "//{@#@*%*}"//设置片断代码替换标记,请注意在以上代码中的字符串{@#@*%*}即为 BittyCodeReplacemen。
                    gcLayer.IndependentSave = false//设置为不能独立保存。
                }

                
//加入集合。
                this._codeLayers.Add(gcLayer);
            }
        }

        
/// <summary>
        
/// 清除所有不需要的对象。
        
/// </summary>
        public void ClearAllUnused()
        {
            
if (null != this._codeLayers)
                
this._codeLayers.Clear();
        }

        
#endregion        

        
#region 私有的方法

        
/// <summary>
        
/// 根据键从集合中获取对象。
        
/// </summary>
        
/// <param name="sd">SortedList</param>
        
/// <param name="key">要查找的键</param>
        
/// <returns></returns>
        private string GetValueByKey(SortedList<stringstring> sd, string key)
        {
            
foreach (string _key in sd.Keys)
            {
                
if (_key == key)
                    
return sd[_key];
            }

            
return null;
        }

        
#endregion
    }
}

插件开发详细说明:

1. 下载插件开发源代码,点击下载
2. 插件开发源代码简介:
    数据库实体接口对象:PlugInInterface/IEntities
    数据库实体对象:PlugInInterface/DBEntities
    生成码插件接口:PlugInInterface/IActions/IGenSymLanguage.cs
    生成代码插件demo:PlugIns/GenSymLanguages/生成代码示例/Demo_GenCode.cs
3. 创建解决方案。打开Visual Studio创建空白解决方案,然后依次添加现有项目Common、PlugInInterface(依赖于Common层)和PlugIns(依赖于PlugInInterface和Common层)。
4. 开发新插件。如果你要开发新的插件,建议创建一新项目,添加对Common和PlugInInterface的引用,然后根据Demo(Demo_GenCode.cs)创建新插件。
5. 安装插件。插件创建完成编译通过,然后打开主程序,从工具栏依次打开 工具栏 --> 工具箱 --> 安装新插件,打开新插件所在目录并选择编译的dll,系统会自动扫描到新插件。
6. 应用插件。从工具栏依次打开 系统配置 --> 创建新方案 或 打开已有的方案 --> 生成代码,插件列表中将会显示刚刚安装的插件,请选择该插件并完成页面下方的相关配置,点“完成”完成配置并载入当前方案。
7. 生成代码。 载入当前方案,从右边数据表列表中选择某一数据表,弹出右键菜单创建相关功能的存储过程(如果已有存储过程略过),从右边数据表列表中选择某一数据表,右键“生成代码”或从工具栏的“生成代码 --> 从当前表生成代码”生成代码。
8. 代码写入项目。 在生成代码页面,从工具栏上选择“保存代码 --> 当前代码写入项目 或 所有代码写入项目”。如果要重新设置代码写入路径,请从工具栏上进入“系统配置 --> [你当前方案] --> 生成代码,页面下方设置代码保存路径”,点完成重新载入当前方案。

开发插件所需的相关对象:

1. 数据表(IDBTable.cs),数据列(IDBColumn.cs)
2. 与当前数据表关联的存储过程(通过IDBProcedure的AssociatedTable获取),存储过程成员(IDBMember.cs)。
3. 与当前表建立外键关系的其它表(能过IDBTable的Fks、Rks获取)。
4. 视图(IDBView.cs)。

存储过程标签定义说明:

1. Execute
    命令执行方式,选择有ExecuteNonQuery,ExecuteScalar和ExecuteReaderOrDataSet。
2. SPType
    存储过程类别,选择有Insert(添加数据),Update(更新),UpdateByPrimary(以主键更新),Delete(删除数据),DeleteByPrimary(以主键删除数据),Select(获取数据),SelectByPrimary(以主键获取数据),SelectPaging(分页获取数据)。
3. Table
    当前存储过程所关联的数据表,即当前存储过程将作为为该数据表生成代码中的一个方法。
4. Description
    存储过程的说明。
5. MultiDataSource
    表示当前存储过程将返回多个数据集,以便程序作出特别处理。
特别提示:通过IDBProcedure来获取存储过程通过标签定义的特性。

作者:水木    
 
原文地址:https://www.cnblogs.com/hsapphire/p/1568243.html