fastCSharp - 代码生成的底层应用框架


BSD
Windows
C#

软件简介

fastCSharp是一个基于.NET元数据的 代码生成底层应用框架 ,目标是打造一个“ 开发 + 运行
效率双优 的开源框架。

经过半年多的时间,除了与 web开发 直接相关的部分,都已经在fastCSharp part
1.5
中完成了重写工作。

fastCSharp现在实现的 代码生成实例 主要有 5个

1、 基于缓存 查询模式的 ORM 代码生成实例(现在只支持 MSSQL
),自定义配置类是fastCSharp.setup.cSharp.sqlTable,同时 支持反射模式
fastCSharp.setup.cSharp.sqlTable.sqlTool。

下面是ORM的model定义示例

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 [fastCSharp.setup.cSharp.sqlTable(ConnectionName = "Connection1")] public partial class model1 { /// /// 自增列,一个表格只允许一个,如果不配置IsIdentity = true,将自动匹配名称为 id 的成员 /// [fastCSharp.setup.sqlMember(IsIdentity = true)] public int id; /// /// 关键字1,多个关键字成员按照成员定义顺序一致 /// [fastCSharp.setup.sqlMember(IsPrimaryKey = true)] public int key1; /// /// 关键字2 /// [fastCSharp.setup.sqlMember(IsPrimaryKey = true, IsAscii = true, MaxLength = 32)] public string key2; public enum EnumByte : byte { Enum1 } /// /// 直接支持枚举类型转换,可以不指定SqlType = typeof(byte) /// [fastCSharp.setup.sqlMember(SqlType = typeof(byte))] public EnumByte key2; /// /// 指定隐式类型转换 /// [fastCSharp.setup.sqlMember(SqlType = typeof(string))] public partial struct image { public string url; /// /// 如果不能隐式类型转换,必须实现互转函数 /// public static implicit operator image(string url) { return new image { url = url }; } public static implicit operator string(image image) { return image.url; } } /// /// 支持隐式类型转换 /// [fastCSharp.setup.sqlMember(IsAscii = true, MaxLength = 64)] public image icon = string.Empty; }

fastCSharp的配置文件是一个 纯数据的json 格式文件,比如 Connection1 的配置定义

1 2 3 4 5 6 7 8 9 10 11 12 { sql: { checkConnection:["Connection1"], Connection1: { Diantou:{ Type:"sql2008", Connection:"server=192.168.0.100;database=dbname;uid=username;pwd=password" } } } }

下面是代码生成模式 示例 ,采用 派生类 的模式

1 2 3 4 5 6 7 8 9 10 11 12 13 14 public partial class bModel1 : model1.sqlTable { static bModel1() { if (SqlTool != null) { //定义缓存 Cache = new fastCSharp.sql.cache.whole.identityArray(SqlTool); //定义缓存同步个性化处理事件 Cache.OnInserted += XXX; Cache.OnUpdated += XXX; } } }

有时候 多个表格结构相同 ,那么只需要定义一个model,比如可以

1 2 3 4 5 6 7 8 9 10 public abstract class bModelBase : model1.sqlTable where tableType : bModelBase { } public partial class bModel1_1 : bModelBase { } public partial class bModel1_N : bModelBase { }

下面是 反射模式示例

1 2 3 4 5 6 7 8 9 10 11 public class bModel1 : model1 { private static readonly fastCSharp.setup.cSharp.sqlTable.sqlTool sqlTool = fastCSharp.setup.cSharp.sqlTable.sqlTool.Default; static bModel1() { if (sqlTool != null) { //缓存定义与事件定义 和 代码生成模式示例一样 } } }

有人说ORM不适应于 复杂的综合查询 。真的吗?我现在展示一段查询代码

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 return diantou.dataProxy.questionTopic.getTopicCache(id) .getArray(value => diantou.dataProxy.question.get(value.linkId)) .getHash(value => value.bestAnswerId) .getArray(value => diantou.dataProxy.answer.get(value)) .getFind(value => value != null) .group(value => value.userId) .getArray(value => new keyValue(diantou.dataProxy.user.get(value.Key), value.Value.Count)) .group(value => value.Key.grade0) .getArray(value => new userStat { grade0 = value.Key, count = value.Value.Count, path = topic.path.bestAnswer, users = value.Value.rangeSort((left, right) => right.Value - left.Value, 0, 6) .getArray(user => diantou.dataProxy.user.get(user.Key, userId)) });

这个查询需求是,先根据话题(topic)ID查找相关联的问题(question)ID集合,然后找到这些问题的最佳答案(answer)ID集合,然后根据这些答案的用户(user)ID分组统计答案数量,最后将这些用户根据用户等级分组,每个分组根据答案数量取前6个用户。

我个人认为基于ORM的查询 更简单流畅 。如果用SQL实现这个需求,该是一个多么 复杂的SQL语句
?如果需求有一点点变化,修改这个SQL语句该是多麻烦的事?

2、 数据类快速序列化 代码生成实例,自定义配置类是fastCSharp.setup.cSharp.serialize,同时 支持反射模式

1 2 3 4 5 6 7 /// /// 仅仅选择字段成员,反射模式可以不必配置 /// [fastCSharp.setup.cSharp.serialize(Filter = fastCSharp.setup.memberFilter.InstanceField)] public partial class model1 { }

代码生成模式将实现接口fastCSharp.setup.cSharp.serialize.ISerialize

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 /// /// 序列化接口 /// public interface ISerialize { /// /// 对象序列化 /// /// 序列化数据 byte[] Serialize(); /// /// 对象序列化 /// /// 数据流 void Serialize(memoryStream stream); /// /// 对象序列化 /// /// 对象序列化器 void Serialize(dataSerializer serializer); /// /// 反序列化 /// /// 序列化数据 bool DeSerialize(byte[] data); /// /// 反序列化 /// /// 序列化数据 /// 起始位置 /// 结束位置 bool DeSerialize(byte[] data, int startIndex, out int endIndex); /// /// 反序列化 /// /// 对象反序列化器 void DeSerialize(deSerializer deSerializer); }

如果自定义配置IsStreamSerialize =
true,将实现接口fastCSharp.setup.cSharp.serialize.IStreamSerialize

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 /// /// 序列化流接口 /// public interface IStreamSerialize : ISerialize { /// /// 对象序列化 /// /// 数据流 void Serialize(Stream stream); /// /// 对象序列化 /// /// 对象序列化器 void Serialize(streamSerializer serializer); }

反射模式的话, 直接调用反射函数

1 2 3 fastCSharp.setup.cSharp.serialize.dataSerialize.Get(value); fastCSharp.setup.cSharp.serialize.streamSerialize.Get(value); fastCSharp.setup.cSharp.serialize.deSerialize.Get(data);

3、 TCP(静态方法)调用代码 生成实例,自定义配置类是fastCSharp.setup.cSharp.tcpCall ,支持泛型
支持跨类 (只能支持单例), 不支持反射模式 。下面是示例:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 /// /// 序列化流接口 /// [fastCSharp.setup.cSharp.tcpCall(Service = "tcpCallVerifyAsynchronous", VerifyType = typeof(tcpVerifyAsynchronous))] public partial class tcpCallVerifyAsynchronous { [fastCSharp.setup.cSharp.tcpCall(IsClientAsynchronous = false)] protected static void action() { isServer = true; } [fastCSharp.setup.cSharp.tcpCall(IsClientAsynchronous = true)] protected static void actionAsynchronous() { isServer = true; } [fastCSharp.setup.testCase] internal static bool Test() { using (fastCSharp.testCase.tcpServer.tcpCallVerifyAsynchronous server = new fastCSharp.testCase.tcpServer.tcpCallVerifyAsynchronous()) { if (!server.Start()) throw new Exception("tcpCallVerifyAsynchronous"); if (fastCSharp.testCase.tcpClient.tcpCallVerifyAsynchronous.defaultTcpServer.IsServer) throw new Exception("IsServer"); isServer = false; tcpCall.tcpCallVerifyAsynchronous.action(); checkServer("action"); isServer = false; isReturn = null; tcpCall.tcpCallVerifyAsynchronous.actionAsynchronous(actionAsynchronousReturn); checkIsReturn("actionAsynchronous"); } return true; } }

4、 TCP(动态方法)服务 代码生成实例,自定义配置类是fastCSharp.setup.cSharp.tcpServer, 支持泛型
不支持跨类不支持反射模式 。下面是示例:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 [fastCSharp.setup.cSharp.tcpServer(Service = "tcpServerVerifyAsynchronous", VerifyType = typeof(tcpVerifyAsynchronous))] public partial class tcpServerVerifyAsynchronous { [fastCSharp.setup.cSharp.tcpServer(IsClientAsynchronous = false)] protected void action() { isServer = true; } [fastCSharp.setup.cSharp.tcpServer(IsClientAsynchronous = true)] protected void actionAsynchronous() { isServer = true; } [fastCSharp.setup.testCase] internal static bool Test() { using (fastCSharp.testCase.tcpServer.tcpServerVerifyAsynchronous server = new fastCSharp.testCase.tcpServer.tcpServerVerifyAsynchronous()) { if (!server.Start()) throw new Exception("tcpServerVerifyAsynchronous"); using (fastCSharp.testCase.tcpClient.tcpServerVerifyAsynchronous client = new fastCSharp.testCase.tcpClient.tcpServerVerifyAsynchronous()) { isServer = false; client.action(); checkServer("action"); isServer = false; isReturn = null; client.actionAsynchronous(actionAsynchronousReturn); checkIsReturn("actionAsynchronous"); } } return true; } }

与TCP(静态方法)调用代码生成实例相似,可以参考一下fastCSharp.setup.tcpRegister。

5、 快速json处理 代码生成实例,自定义配置类是fastCSharp.setup.cSharp.ajax,同时 支持反射模式

1 2 3 4 5 6 7 /// /// 可以选择只生成 序列化 或者 反序列化 的代码,反射模式可以不必配置 /// [fastCSharp.setup.cSharp.ajax(IsToJson = true, IsParseJson = true)] public partial class model1 { }

代码生成模式将实现接口fastCSharp.setup.cSharp.ajax.IToJson与fastCSharp.setup.cSharp.ajax.IParseJson

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 /// /// 对象转换成JSON字符串接口 /// public interface IToJson { /// /// 对象转换成JSON字符串 /// /// JSON字符串 string ToJson(); /// /// 对象转换成JSON字符串 /// /// 对象转换JSON字符串 void ToJson(toJsoner toJsoner); } /// /// JSON字符串转换成对象接口 /// public interface IParseJson { /// /// JSON字符串转换成对象 /// /// JSON字符串 void FromJson(string json); /// /// JSON字符串解析节点换成对象 /// /// JSON字符串解析节点 void FromJson(jsonNode node); }

反射模式的话, 直接调用反射函数

1 2 fastCSharp.setup.cSharp.ajax.toJson.Get(value); fastCSharp.setup.cSharp.ajax.parseJson.Get(json);

由于很多人不需要代码生成那么好的运行效率,也 不想配置初始环境 ,所以某些代码生成实例提供了 基于反射的实例实现
。有的代码生成实例需要生成代理实例(比如TCP调用),没有办法使用反射实现相同的效果。

今天是我在现在这个公司工作的最后一天了,感谢李陶冶大牛这几年对我的照顾,感谢你对于这个项目开源发展的支持。也许过几天我就回老家“休息”了,在这里默默的祝福你和
51nod 能够一切顺利。

最后欢迎对算法有兴趣的朋友到基于 fastCSharp 开发的51nod
OJ
上去 AC问题 或者讨论算法问题。