这是一个基于Razor Engine的代码生成器,在强大的Razor语法支持下通过编写模板针对数据库的Schema或者一段SQL的查询结果生成代码。(模板使用Razor C# 语法)下载地址:http://razorsourcegenerator.codeplex.com/releases/view/96371运行前提:
安装 .net 4.0 client profile特性:
1. 支持多种主流数据库(因为使用OleDb获得Schema,理论上OleDb支持的数据库都可以。)
2. 编写模板比较简单,生成代码非常灵活,并且有一定程度的错误提示(这主要归功于 RazorEngine)
Razor模板内嵌的helper方法,让你编写模板如虎添翼
3. 支持文件名的参数化,可以批量生成代码
4. 可以Append方式生成代码(可将多个Table的信息生成到一个文件中),生成代码更方便
5. 可以通过自定义SQL生成代码[SQLServer mdf file]代码生成 ibatis JAVA 代码示例:
<模板>@*
Razor注释:编写Template(BySchema)可以使用下面的变量
@Model.Context.IsFirst, @Model.Context.IsLast, @Model.TableName, @Model.Columns(多行)
*@
/* FileName: @ConvNameUpper(Model.TableName)Entity.java
* (c)Copyright XXX Corporation 2012 All Rights Reserved.
*
* History
* Ver Author Date Comment
* Ver.1.00 XXX @DateTime.Now.ToString("yyyy/MM/dd") Created
*/
package xxx.xxx.xxx.common.entity;import java.math.BigDecimal;
import java.io.Serializable;public final class @ConvNameUpper(Model.TableName)Entity extends BaseEntity {
private static final long serialVersionUID = 1L; @foreach(dynamic x in Model.Columns)
{
var javaType = GetDbType(x.DataType.ToString(), x.NumericScale.ToString());
@(" //") @x.Description @("\r\n")
@(" private ") @javaType @(" ") @ConvNameLower(x.ColumnName) @(";\r\n")
} @foreach(dynamic x in Model.Columns)
{
var javaType = GetDbType(x.DataType.ToString(), x.NumericScale.ToString());
@(" /**\r\n")
@(" * 「") @x.Description @("」 getter\r\n")
@(" */\r\n")
@(" public ") @javaType @(" ") @Getter(x.ColumnName) @("() {\r\n")
@(" return ") @ConvNameLower(x.ColumnName) @(";\r\n")
@(" }\r\n")
@("\r\n")
@(" /**\r\n")
@(" * 「") @x.Description @("」 setter\r\n")
@(" */\r\n")
@(" public void ") @Setter(x.ColumnName) @("(") @javaType @(" ") @ConvNameLower(x.ColumnName) @(") {\r\n")
@(" this.") @ConvNameLower(x.ColumnName) @(" = ") @ConvNameLower(x.ColumnName) @(";\r\n")
@(" }\r\n")
@("\r\n")
}
}@helper ConvNameUpper(string str) {
@string.Join("", str.ToLower().Split('_', ' ').Select(s => char.ToUpper(s[0]).ToString() + s.Substring(1)).ToArray())
}
@helper ConvNameLower(string str) {
@string.Join("", str.ToLower().Split('_', ' ').Select((s,i) => i==0 ? s : char.ToUpper(s[0]).ToString() + s.Substring(1)).ToArray())
}
@helper Getter(string str) {
@("get" + string.Join("", str.ToLower().Split('_', ' ').Select(s => char.ToUpper(s[0]).ToString() + s.Substring(1)).ToArray()))
}
@helper Setter(string str) {
@("set" + string.Join("", str.ToLower().Split('_', ' ').Select(s => char.ToUpper(s[0]).ToString() + s.Substring(1)).ToArray()))
}
@helper Upper(string str) {
@string.Format("{0}{1}", char.ToUpper(str[0]), str.Substring(1))
}
@helper GetDbType(string type, string scale) {
@if(type == "System.Decimal" && scale == "0") {
@("Integer")
} else if (type == "System.Decimal" && scale != "0") {
@("BigDecimal")
} else {
@("String")
}
}
通过自定义模板,可以适应不同项目的要求(比如:代码的头部声明,不同项目的命名规则,基类等等)
利用OleDb还可以直接连接 Excel 来生成代码。使用上,比 MyGeneration 要简单得多。
接下来还会实现Razor语法着色,预览等功能,有兴趣的童鞋可以关注这个项目。
安装 .net 4.0 client profile特性:
1. 支持多种主流数据库(因为使用OleDb获得Schema,理论上OleDb支持的数据库都可以。)
2. 编写模板比较简单,生成代码非常灵活,并且有一定程度的错误提示(这主要归功于 RazorEngine)
Razor模板内嵌的helper方法,让你编写模板如虎添翼
3. 支持文件名的参数化,可以批量生成代码
4. 可以Append方式生成代码(可将多个Table的信息生成到一个文件中),生成代码更方便
5. 可以通过自定义SQL生成代码[SQLServer mdf file]代码生成 ibatis JAVA 代码示例:
<模板>@*
Razor注释:编写Template(BySchema)可以使用下面的变量
@Model.Context.IsFirst, @Model.Context.IsLast, @Model.TableName, @Model.Columns(多行)
*@
/* FileName: @ConvNameUpper(Model.TableName)Entity.java
* (c)Copyright XXX Corporation 2012 All Rights Reserved.
*
* History
* Ver Author Date Comment
* Ver.1.00 XXX @DateTime.Now.ToString("yyyy/MM/dd") Created
*/
package xxx.xxx.xxx.common.entity;import java.math.BigDecimal;
import java.io.Serializable;public final class @ConvNameUpper(Model.TableName)Entity extends BaseEntity {
private static final long serialVersionUID = 1L; @foreach(dynamic x in Model.Columns)
{
var javaType = GetDbType(x.DataType.ToString(), x.NumericScale.ToString());
@(" //") @x.Description @("\r\n")
@(" private ") @javaType @(" ") @ConvNameLower(x.ColumnName) @(";\r\n")
} @foreach(dynamic x in Model.Columns)
{
var javaType = GetDbType(x.DataType.ToString(), x.NumericScale.ToString());
@(" /**\r\n")
@(" * 「") @x.Description @("」 getter\r\n")
@(" */\r\n")
@(" public ") @javaType @(" ") @Getter(x.ColumnName) @("() {\r\n")
@(" return ") @ConvNameLower(x.ColumnName) @(";\r\n")
@(" }\r\n")
@("\r\n")
@(" /**\r\n")
@(" * 「") @x.Description @("」 setter\r\n")
@(" */\r\n")
@(" public void ") @Setter(x.ColumnName) @("(") @javaType @(" ") @ConvNameLower(x.ColumnName) @(") {\r\n")
@(" this.") @ConvNameLower(x.ColumnName) @(" = ") @ConvNameLower(x.ColumnName) @(";\r\n")
@(" }\r\n")
@("\r\n")
}
}@helper ConvNameUpper(string str) {
@string.Join("", str.ToLower().Split('_', ' ').Select(s => char.ToUpper(s[0]).ToString() + s.Substring(1)).ToArray())
}
@helper ConvNameLower(string str) {
@string.Join("", str.ToLower().Split('_', ' ').Select((s,i) => i==0 ? s : char.ToUpper(s[0]).ToString() + s.Substring(1)).ToArray())
}
@helper Getter(string str) {
@("get" + string.Join("", str.ToLower().Split('_', ' ').Select(s => char.ToUpper(s[0]).ToString() + s.Substring(1)).ToArray()))
}
@helper Setter(string str) {
@("set" + string.Join("", str.ToLower().Split('_', ' ').Select(s => char.ToUpper(s[0]).ToString() + s.Substring(1)).ToArray()))
}
@helper Upper(string str) {
@string.Format("{0}{1}", char.ToUpper(str[0]), str.Substring(1))
}
@helper GetDbType(string type, string scale) {
@if(type == "System.Decimal" && scale == "0") {
@("Integer")
} else if (type == "System.Decimal" && scale != "0") {
@("BigDecimal")
} else {
@("String")
}
}
通过自定义模板,可以适应不同项目的要求(比如:代码的头部声明,不同项目的命名规则,基类等等)
利用OleDb还可以直接连接 Excel 来生成代码。使用上,比 MyGeneration 要简单得多。
接下来还会实现Razor语法着色,预览等功能,有兴趣的童鞋可以关注这个项目。
感觉还不错啊
WPF 我一直看好它的,虽然有人总说它BUG多而不喜。不过WPF的学习难度也不小,本以为很容易上手的,但是思路一改常态,等理解了依赖属性后,估计就可以顺手了。
难点在解析引擎,其实Razor 是Asp.net mvc 里开源的解析引擎。
{
public static readonly bool isTcpClient = !showjim.sys.config.isConfigName(typeof(showjim.config.tcpCall.server), "@serverType");
public @serverType(showjim.setup.attribute.tcpServer value)
: base(new System.Net.IPAddress(BitConverter.GetBytes(showjim.setup.deploy.process.registerIp)), value.port == 0 ? showjim.setup.deploy.process.register(value.register, value.isRegisterOnly) : value.port, value.verifyFileName, value.isCompress, value.isAsynchronous, value.checkKeepAliveSecond, value.checkKeepAliveSkipSecond) { }
public @serverType() : this(showjim.sys.config.loadConfig("@tcpCallAttribute.register", showjim.config.tcpCall.server.get(showjim.config.tcpCall.server.enumType.@serverType))) { }
/// <summary>
/// 设置命令处理委托集合
/// </summary>
[showjim.setup.attribute.tcpCall(isIgnore = true)]
protected override void SetOnCommands()
{
if (IsAsynchronous)
{
showjim.sys.list<System.Collections.Generic.KeyValuePair<showjim.sys.hashBytes, System.Collections.Generic.KeyValuePair<Action<showjim.sys.net.asyncSocket, int>, bool>>> onCommands = new showjim.sys.list<System.Collections.Generic.KeyValuePair<showjim.sys.hashBytes, System.Collections.Generic.KeyValuePair<Action<showjim.sys.net.asyncSocket, int>, bool>>>(@methods.Length + 1);
onCommands.addUnsafe(new System.Collections.Generic.KeyValuePair<showjim.sys.hashBytes, System.Collections.Generic.KeyValuePair<Action<showjim.sys.net.asyncSocket, int>, bool>>(CloseCommandData, new System.Collections.Generic.KeyValuePair<Action<showjim.sys.net.asyncSocket, int>, bool>(Close, false)));
byte[] command;
#region LOOP methods
showjim.sys.array.reverse(command = showjim.sys.String.bytes("@methodFullName"));
onCommands.addUnsafe(new System.Collections.Generic.KeyValuePair<showjim.sys.hashBytes, System.Collections.Generic.KeyValuePair<Action<showjim.sys.net.asyncSocket, int>, bool>>(command, new System.Collections.Generic.KeyValuePair<Action<showjim.sys.net.asyncSocket, int>, bool>(@methodIndexName, @isParameter)));
#endregion LOOP methods
OnCommandsAsynchronous = new showjim.sys.staticDictionary<showjim.sys.hashBytes, System.Collections.Generic.KeyValuePair<Action<showjim.sys.net.asyncSocket, int>, bool>>(onCommands);
}
else
{
showjim.sys.list<System.Collections.Generic.KeyValuePair<showjim.sys.hashBytes, System.Collections.Generic.KeyValuePair<Action<showjim.sys.net.socket, int>, bool>>> onCommands = new showjim.sys.list<System.Collections.Generic.KeyValuePair<showjim.sys.hashBytes, System.Collections.Generic.KeyValuePair<Action<showjim.sys.net.socket, int>, bool>>>(@methods.Length + 1);
onCommands.addUnsafe(new System.Collections.Generic.KeyValuePair<showjim.sys.hashBytes, System.Collections.Generic.KeyValuePair<Action<showjim.sys.net.socket, int>, bool>>(CloseCommandData, new System.Collections.Generic.KeyValuePair<Action<showjim.sys.net.socket, int>, bool>(Close, false)));
byte[] command;
#region LOOP methods
showjim.sys.array.reverse(command = showjim.sys.String.bytes("@methodFullName"));
onCommands.addUnsafe(new System.Collections.Generic.KeyValuePair<showjim.sys.hashBytes, System.Collections.Generic.KeyValuePair<Action<showjim.sys.net.socket, int>, bool>>(command, new System.Collections.Generic.KeyValuePair<Action<showjim.sys.net.socket, int>, bool>(@methodIndexName, @isParameter)));
#endregion LOOP methods
OnCommands = new showjim.sys.staticDictionary<showjim.sys.hashBytes, System.Collections.Generic.KeyValuePair<Action<showjim.sys.net.socket, int>, bool>>(onCommands);
}
}
}与它的数据视图 [showjim.setup.attribute.cSharp]
partial class tcpCall : tcpServer<showjim.setup.attribute.tcpCall>
{
protected override void SetMembers() { }
public string defaultNamespace;
public showjim.config.tcpCall.server.enumType serverType;
public bool isClass;
public void create(Type type, showjim.setup.coder.methodInfo[] methods, string defaultNamespace
, showjim.config.tcpCall.server.enumType serverType)
{
this.methods = methods;
this.defaultNamespace = defaultNamespace;
this.serverType = serverType;
isClass = true;
create(type, (showjim.setup.attribute.tcpCall)null);
} public int clientCount
{
get { return tcpCallAttribute.clientCount <= 0 ? 1 : tcpCallAttribute.clientCount; }
}
public showjim.setup.attribute.tcpServer tcpCallAttribute;
public string create(showjim.config.tcpCall.server.enumType serverType, showjim.setup.coder.methodInfo[] methods)
{
isClass = false;
tcpCallAttribute = showjim.config.tcpCall.server.get(this.serverType = serverType);
this.methods = methods;
Create();
return Code.ToString();
}
}
代码生成不应该局限于ORM,对于替代反射,函数代理,性能优化方面很有用。
嗯,使用Razor的创意非常赞。
寻找追求完美的csharper一起搭建一个C#开源框架
WPF 我一直看好它的,虽然有人总说它BUG多而不喜。不过WPF的学习难度也不小,本以为很容易上手的,但是思路一改常态,等理解了依赖属性后,估计就可以顺手了。
比如说明有:
@Model.Context.IsFirst, @Model.Context.IsLast, @Model.TableName, @Model.Columns
这些变量可用,但是好像少了些,有没有下面字段支持,如没有,能否增加:
foreach (x in @Model.Columns)
{
x.IsFirst ????
}
@helper PrepareModelColumns() {
var index = 0;
foreach(dynamic x in Model.Columns)
{
index++;
x.Index = index;
x.IsFirst = x.Index == 1;
x.IsLast = x.Index == Model.Columns.Count;
}
}
多谢关注,Model.Columns 就是字段的集合了,帮助文档会进一步完善。
目前可以点击 TableName 的 LinkButton 看到DB的Schema,里面的列就是这个 Columns 里元素的属性。
foeach(var x in @Model.Columns)
{
@x.ColumnName
@x.ColumnSize
@x.ColumnOrdinal
@x.NumericPrecision
@x.NumericScale
@x.DataType
@x.IsLong
@x.AllowDBNull
@x.IsReadOnly
@x.IsUnique
@x.IsKey
@x.IsAutoIncrement
@x.BaseTableName
@x.BaseColumnName
@x.Description
}
我会尽快完善文档