C#代码生成器-基于Spring.net架构

C#代码生成器-基于Spring.net架构

背景

编写代码生成器的目的是为了进一步减少程序员的重复性“体力劳动”,让程序员有更多的时间去做创造性的工作,提高编码的质量。我在编码和架构过程中层自己开发了一系列代码生成工具,本着开源和分享的目的,会在本期和后期博客中倾情奉献给有需要的朋友,不足指出也请多包含,因为共享源码,你也可以进行修改使用。

实现思路

预先编制模版,包括实体类、数据访问类、业务逻辑类、配置文件,基于已定义的数据库结构进行模版替换生成。

关键模版代码

1、实体类模版(EntityClassTemplate.txt)

/************************************************************************************
 *      ${CopyRight}
 *      File:
 *				${EntityClassName}.cs
 *      Description:
 *		
 *      Author:
 *				${Author}
 *				${AuthorEmail}
 *				${Online}
 *      Finish DateTime:
 *				${Date}
 *      History:
 ***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Text;

namespace ${EntityNameSpace}
{
    /// <summary>
    /// 实体类${EntityClassName}
    /// </summary>
    [Serializable]
    public class ${EntityClassName}
    {
        #region 私有字段

${PrivateFields}

        #endregion

        #region 公有属性

${PublicAttribute}

        #endregion	
    }
}

2、实体类映射文件模版(EntityMapperHandler.txt)

/************************************************************************************
 *      ${CopyRight}
 *      File:
 *				EntityMapperHandler.cs
 *      Description:
 *				 实体类映射文件解析类
 *      Author:
 *				${Author}
 *				${AuthorEmail}
 *				${Online}
 *      Finish DateTime:
 *				${Date}
 *      History:    
 *      
 ***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using System.Configuration;
using System.Reflection;

namespace ${TopComponentsNameSpace}
{
    using ${ComponentNameSpace};
    /// <summary>
    /// 实体类映射文件解析类,使用单例设计模式实现
    /// </summary>
    public class EntityMapperHandler
    {
        #region 私有字段

        private static EntityMapperHandler instance;
        private static Dictionary<string, XmlClassMap> mapperDictionary=new Dictionary<string,XmlClassMap>();

        #endregion

        #region 构造方法

        private EntityMapperHandler() { }

        private EntityMapperHandler(string mapperFiles)
        {
            lock (this)
            {
                string[] files = mapperFiles.Split(new char[] { ',' });
                foreach (string file in files)
                {
                    Stream s = null;
                    if (file.StartsWith("assembly://"))
                    {
                        string prefixStr = "assembly://";
                        string assemblyName = file.Substring(prefixStr.Length, file.LastIndexOf("/") - prefixStr.Length);
                        string fileName = file.Substring(file.LastIndexOf("/") + 1);
                        s = Assembly.Load(assemblyName).GetManifestResourceStream(fileName);
                    }
                    else
                    {
                        s = new FileStream(file, FileMode.Open);
                    }
                    this.CreateMapperDictionary(s);
                }
            }
        }

        private EntityMapperHandler(Stream mapperStream)
        {
            lock (this)
            {
                this.CreateMapperDictionary(mapperStream);
            }
        }

        #endregion

        #region 创建映射字典
        /// <summary>
        /// 解析实体关系映射文件,把解析的结果保存到字典集合中
        /// </summary>
        /// <param name="mapperStream">实体关系映射文件流</param>
        private void CreateMapperDictionary(Stream mapperStream)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(mapperStream);
            //解析实体类与表的映射
            XmlNodeList nl = doc.GetElementsByTagName("class");
            foreach (XmlNode node in nl)
            {
                string className = node.Attributes["name"].Value;
                string tableName = node.Attributes["table"].Value;

                //解析属性与字段的映射
                XmlClassMap classMap = new XmlClassMap(className, tableName);
                XmlNodeList childNl = node.ChildNodes;
                foreach (XmlNode childNode in childNl)
                {
                    if (childNode.Name == "property")
                    {
                        #region 解析属性

                        string propertyName = childNode.Attributes["name"].Value;
                        string columnName = childNode.Attributes["column"].Value;

                        XmlPropertyMap propertyMap = new XmlPropertyMap(propertyName, columnName);
                        classMap.Properties.Add(propertyName, propertyMap);

                        #endregion
                        #region 解析自增列

                        XmlAttribute attrIdentity = childNode.Attributes["isIdentity"];
                        if (attrIdentity != null && attrIdentity.Value == "true")
                        {
                            classMap.Identity = propertyMap;
                        }

                        #endregion
                        #region 解析主键

                        XmlAttribute attrPK = childNode.Attributes["isPK"];
                        if (attrPK != null && attrPK.Value == "true")
                        {
                            classMap.Ids.Add(propertyName, propertyMap);
                        }

                        #endregion
                    }
                }
                mapperDictionary.Add(className, classMap);
            }
            mapperStream.Close();
            mapperStream.Dispose();
        }
        #endregion

        #region 获取解析器实例

        /// <summary>
        /// 获取本类实例的静态方法
        /// </summary>
        /// <param name="mapperFile">映射文件路径</param>
        /// <returns>返回本类实例</returns>
        public static EntityMapperHandler GetInstance(string mapperFile)
        {
            if (instance == null)
            {
                instance = new EntityMapperHandler(mapperFile);
            }
            return instance;
        }

        /// <summary>
        /// 获取本类实例的静态方法
        /// </summary>
        /// <param name="mapperStream">映射文件流</param>
        /// <returns>返回本类实例</returns>
        public static EntityMapperHandler GetInstance(Stream mapperStream)
        {
            if (instance == null)
            {
                instance = new EntityMapperHandler(mapperStream);
            }
            return instance;
        }
        /// <summary>
        /// 获取本类实例的静态方法,默认读取appSetting中entityMapperFile对应的文件,可以配置多个以逗号分隔
        /// </summary>
        /// <returns>返回本类实例</returns>
        public static EntityMapperHandler GetInstance()
        {
            if (instance == null)
            {
                string mapperFiles = ConfigurationManager.AppSettings["entityMapperFile"];
                instance = new EntityMapperHandler(mapperFiles);
            }
            return instance;
        }

        #endregion

        /// <summary>
        /// 获取映射字典
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, XmlClassMap> GetMapDictionary()
        {
            return mapperDictionary;
        }

        /// <summary>
        /// 根据实体类型获取对应的表名
        /// </summary>
        /// <param name="type">实体类型</param>
        /// <returns>返回对应的表名称</returns>
        public string GetTableNameByClassType(Type type)
        {
            return mapperDictionary[type.Name].TableName;
        }
    }
}

3、数据访问接口模版(IDAOTemplate.txt)

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

namespace ${DAONameSpace}.Interface
{
    using ${EntityNameSpace};
    public interface I${EntityClassName}${DAOClassPostFix} : IBase${DAOClassPostFix}<${EntityClassName}>
    {
    }
}

4、数据访问类模版(DAOTemplate.txt)

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

namespace ${DAONameSpace}.Implements
{
    using ${EntityNameSpace};
    using ${DAONameSpace}.Interface;
    public class ${EntityClassName}${DAOClassPostFix} : Base${DAOClassPostFix}<${EntityClassName}>, I${EntityClassName}${DAOClassPostFix}
    {
    }
}

5、业务逻辑接口模版(IBIZTemplate.txt)

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

namespace ${BIZNameSpace}.Interface
{
    using ${EntityNameSpace};
    public interface I${EntityClassName}${BIZClassPostFix} : IBase${BIZClassPostFix}<${EntityClassName}>
    {
    }
}

6、业务逻辑类模版(BIZTemplate.txt)

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

namespace ${BIZNameSpace}.Implements
{
    using ${EntityNameSpace};
    using ${BIZNameSpace}.Interface;
    using ${DAONameSpace}.Interface;
    public class ${EntityClassName}${BIZClassPostFix} : Base${BIZClassPostFix}<${EntityClassName}>, I${EntityClassName}${BIZClassPostFix}
    {
		#region 属性注入
		
        private I${EntityClassName}${DAOClassPostFix} ${CamelDAOClassPostFix};

        public I${EntityClassName}${DAOClassPostFix} ${DAOClassPostFix}
        {
            set { this.${CamelDAOClassPostFix} = value; base.Base${DAOClassPostFix} = this.${CamelDAOClassPostFix}; }
        }
        
        #endregion
    }
}

使用教程

1、 打开VS,新建一个空白解决方案MesnacDemo。
2、 右键点击空白解决方案,添加一个新的类库项目Mesnac,如下图所示:
在这里插入图片描述
3、 启动数据库服务器并运行代码生成器,设置好,服务器、用户名、密码,选择数据库,点击“测试连接”按钮,出现测试成功提示,点击测试连接成功消息框的“确定按钮”后“下一步”变为可用,如下图所示:
在这里插入图片描述
4、 点击“下一步”按钮,出现参数设置窗口,如下图:
在这里插入图片描述
5、设置相应的参数信息,在“输出目录”项填解决方案MesnacDemo.sln所在的目录,你可以点击“保存设置”按钮进行当前设计的保存。然后点击“代码生成”按钮,会出现生成文件个数的消息框,如下图:
在这里插入图片描述
6、 在VS的解决方案小窗口的工具栏上点击“显示所有文件”按钮,如下图:
在这里插入图片描述
7、选中Business、Components、Data、Entity、applicationContext.xml、EntityMapperHandler.cs、SpringObjectFactory.cs点鼠标右键,在弹出菜单中选择“包括在项目中”菜单项,结果如下图:
在这里插入图片描述
8、选中Entity文件夹中的EntityMapper.xml,在属性窗口中把“生成操作”设置为“嵌入的资源”。
9、右键点击Mesnac类库项目,在弹出菜单中选择“添加引用”菜单项,分别添加System.Web、System.Configuration、Common.Logging.dll、Spring.Core.dll 、Spring.Aop.dll、Spring.Data.dll。然后编译此类库项目,看是否编译通过。
10、 在解决方案中添加一个ASP.NET网站,并把Mesnac类库中的applicationContext.xml剪贴到网站根目录下,然后再网站中添加Web.config文件,如下图所示:
在这里插入图片描述
11、修改Web.config,实现ASP.NET与Spring.NET的整合。代码如下:

<?xml version="1.0"?>
<configuration>
  <configSections>
    <sectionGroup name="spring">
      <section name="context" 
type="Spring.Context.Support.WebContextHandler, Spring.Web"/>
      <section name="objects" 
type="Spring.Context.Support.DefaultSectionHandler, Spring.Core"/>
      <section name="parsers" 
		type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core"/>
    </sectionGroup>
  </configSections>
  <spring>
    <context type="Spring.Context.Support.WebApplicationContext, Spring.Web">
      <resource uri="~/applicationContext.xml"/>
    </context>
    <parsers>
      <parser type="Spring.Aop.Config.AopNamespaceParser, Spring.Aop"/>
    </parsers>
  </spring>
  <appSettings>
    <!--实体映射文件的位置-->
<add key="entityMapperFile" 
				value="assembly://Mesnac/Mesnac.Entity.EntityMapper.xml"/>
  </appSettings>
  <connectionStrings/>
  <system.web>
    <httpHandlers>
      <!--Spring Web 支持-->
      <add verb="*" path="*.aspx" 
type="Spring.Web.Support.PageHandlerFactory, Spring.Web"/>
    </httpHandlers>
    <httpModules>
      <!--Spring Web 支持-->
      <add name="Spring" 
type="Spring.Context.Support.WebSupportModule, Spring.Web"/>
    </httpModules>
    <compilation debug="false">
      <assemblies>
        <add assembly="System.Transactions, Version=2.0.0.0, Culture=neutral, 
						PublicKeyToken=B77A5C561934E089"/>
      </assemblies>
    </compilation>
    <authentication mode="Windows"/>
  </system.web>
</configuration>

12、右键点击网站项目,在弹出菜单中选择“添加引用”,添加对Spring.Web.dll、Spring.Web.Extensions.dll和Mesnac类库项目的引用。
13、在Default.aspx页面上放置一个GridView控件,在对应的代码隐藏文件Default.aspx.cs文件中添加相应代码如下所示:

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Mesnac.Business.Interface;
public partial class _Default : System.Web.UI.Page
{
    #region 属性注入

    private ISys_ModuleManager sys_ModuleManager;

    public ISys_ModuleManager Sys_ModuleManager
    {
        set { sys_ModuleManager = value; }
    }

    #endregion
    protected void Page_Load(object sender, EventArgs e)
    {
        //数据绑定操作
        if (!this.IsPostBack)
        {
            this.GridView1.DataSource = this.sys_ModuleManager.GetAllList();
            this.GridView1.DataBind();
        }
    }
}

14、修改applicationContext.xml,在文件后天添加如下代码:

  <!--page config-->
  <object type="Default.aspx">
    <property name="Sys_ModuleManager" ref="sys_ModuleManager" />
  </object>

15、把站点设置为启动项目、把Default.aspx设置为启动页,按Ctrol+F5运行,如下图:
在这里插入图片描述

源代码下载

完整源代码下载

猜你喜欢

转载自blog.csdn.net/zlbdmm/article/details/89642037