一接触FluentAPI,就被它的流畅编码和良好可读性吸引,园子里有很多介绍FluentAPI的文章,我也忍不住把自己最近写的一个小类库放在这里来补充一下流畅API的应用场景。

我写这个小型的类库来源于我昨天的发表的文章<asp.net webForm也可以这样用Ajax -- My Ajax Framework>一文后面网友 “、Dark”对我的一个建议,是否可以用框架动态生成JS文件,这样直接类似AjaxPro的方式,仔细考虑感觉是很好的建议,于是就写了一下,结果发现向Response中写入一些JS数据流是多么乱,又很容易出错。

我起初的代码是这样的:(为了生成一段Js代码我这样做):

Response.Output.WriteLine("<script>");
Response.Output.WriteLine("var PowerAjax = function () { };");
Response.Output.WriteLine("PowerAjax.__Private = function () { };");
Response.Output.WriteLine("PowerAjax.AsyncAjax = function (methodName, paramArray, success, failure) { PowerAjax.__Private.Ajax(methodName, paramArray, success, failure, true);}");
Response.Output.WriteLine("PowerAjax.SyncAjax = function (methodName, paramArray, success, failure) { PowerAjax.__Private.Ajax(methodName, paramArray, success, failure, false); };");
Response.Output.WriteLine("PowerAjax.__Private.Ajax = function(methodName, paramArray, success, failure,isAsync) {");
Response.Output.WriteLine(" var data = {};");
Response.Output.WriteLine(" switch (paramArray.length) {");
Response.Output.WriteLine(" case 0:data = { 'isAjaxRequest': true, 'MethodName': methodName };break;");
Response.Output.WriteLine(" case 1:data = { 'isAjaxRequest': true, 'MethodName': methodName, 'param0': paramArray[0] }; break;");
Response.Output.WriteLine(" }");
Response.Output.WriteLine(" var url = document.location.href;");
Response.Output.WriteLine("};");
Response.Write("</script>");

感觉这样太不靠谱了,经常性的就会写错了,尤其是对于 “{" 和 ”}“这两个符号的对应,实在纠结,一个不留神不是忘记{就是忘记},结果会导致Javascript根本无法打开。有些语句还经常忘记加一个“;”,那么就因为语句的这一个小“;”,代码就无法执行。

于是我就做了一个简单的改进,写了一个简单的小类库来生成:

我的想法是:  把所有js代码分为两类 ”一般语句“ 和 ”由“{.......}”组成的两种语句, 大括号里可以继续写一般语句和{.....} 。就好比函数里可以继续套N个函数和N条语句,于是就有了以下API。

先看看改善之后的代码是什么样的:

ScriptFactory.CreateScript(new ScriptSentence("var PowerAjax = function () { }"),new ScriptSentence("PowerAjax.__Private = function () { }"),new ScriptContainer("PowerAjax.AsyncAjax = function (methodName, paramArray, success, failure)",new ScriptSentence("PowerAjax.__Private.Ajax(methodName, paramArray, success, failure, true)")),new ScriptContainer("PowerAjax.SyncAjax = function (methodName, paramArray, success, failure)",new ScriptSentence("PowerAjax.__Private.Ajax(methodName, paramArray, success, failure, false)")),new ScriptContainer("PowerAjax.__Private.Ajax = function(methodName, paramArray, success, failure,isAsync)",new ScriptSentence("var data = {}"),new ScriptContainer("switch (paramArray.length)",new ScriptSentence("case 0:data = { 'isAjaxRequest': true, 'MethodName': methodName };break"),new ScriptSentence("case 1:data = { 'isAjaxRequest': true, 'MethodName': methodName, 'param0': paramArray[0] }; break"),new ScriptSentence("var url = document.location.href"))));

有感觉好看一些吗?主要是现在所有的语句我都不需要管;,也不需要加个什么{和}的对应关系了。

敏锐的朋友可能已经感觉到,这种API正是LinqToXML生成一段XML一样类似的代码,如:

 XDocument doc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"),new XElement("xxxConfig",new XElement("a", s_LDAPEnabled),new XElement("b", s_ServerPath),new XElement("c", s_BaseDN),new XElement("d", s_UserCN)));

这种结构的优势:不容易出错,写起来很舒服,排版很严谨,很容易就容易从代码中看出整个文档的结构特点。同样我的输出的JS代码也能很清晰的看出这个在C#的中生成的JS文件是什么样子的?

演示就到这里,把整个API发出来,大家互相学习:

********ScriptFactory类********

目的:方便前台调用。因为本身加载起来的是一个树形的结构,所以需要使用递归来解析数据,生成JS代码。

    public sealed class ScriptFactory{private static string CreateScriptTrue(params IScriptBase[] scriptBases){StringBuilder sb = new StringBuilder();foreach (var scriptBase in scriptBases){if (scriptBase is ScriptSentence){sb.Append(scriptBase.ScriptContent + ";");}if (scriptBase is ScriptContainer){sb.Append(scriptBase.ScriptContent);sb.Append("{");sb.Append(CreateScriptTrue(((ScriptContainer)scriptBase).Children.ToArray())); // 递归调用生成JS树形结构sb.Append("};");}}return sb.ToString();}public static string CreateScript(params IScriptBase[] scriptBases){return string.Format("<script>{0}</script>",ScriptFactory.CreateScriptTrue(scriptBases));}}

********IScriptBase接口********

目的:提供内容规范

    public interface IScriptBase{string ScriptContent { get; set; }}

********ScriptContainer : IScriptBase********

目的:承载包含{}结构的语句,{}中还可能包含语句和各种,所以会有一个m_ScriptBases来保存所有结构

    public sealed class ScriptContainer : IScriptBase{private List<IScriptBase> m_ScriptBases = new List<IScriptBase>();public IEnumerable<IScriptBase> Children{get { return this.m_ScriptBases; }}public string ScriptContent { get; set; }public ScriptContainer(string content, params IScriptBase[] scriptBeses){this.ScriptContent = content;this.m_ScriptBse = scriptBeses.ToList();}}

********Scriptesentence : IScriptBase********

目的:承载一般性质的语句,语句本身内部不具备数据结构,仅仅是内容而已。

    public sealed class ScriptSentence : IScriptBase{public string ScriptContent { get; set; }public ScriptSentence(string content){this.ScriptContent = content;}}

OK,以上就是全部代码,是不是很简单呢?而代码有极为简单呢?

此API要点:接口继承,params用法,树形结构,递归。请注意构造函数中参数的用法,这个流畅API的秘密就在这里(大牛可以绕过了,呵呵)

以上是试水的东西,意在演示这种类LinqToXML生成方式的流畅API,如果有什么不对的地方请各位指正,很感谢。从上一篇文章中,各位的指正让我明白了很多东西,抛砖引玉了。

如果感觉此文对您有帮助,请顶一下了^_^

转载于:https://www.cnblogs.com/A_ming/archive/2013/03/29/2988959.html

FluentAPI --- 用C#写的JS代码生成器相关推荐

  1. js node 打包mac应用_混搭 TypeScript + GraphQL + DI + Decorator 风格写 Node.js 应用

    阅读本文的知识前提:熟悉 TypeScript + GraphQL + Node.js + Decorator + Dependency Inject 等概念.前言 恰逢最近需要编写一个简单的后端 N ...

  2. 紧跟月影大佬的步伐,一起来学习如何写好JS(下)

    如何写好js - 写代码应该关注什么

  3. 紧跟月影大佬的步伐,一起来学习如何写好JS(上)

    如何写好JS - 三大原则

  4. [html] 说说js代码写到html里还是单独写到js文件里哪个好?为什么?

    [html] 说说js代码写到html里还是单独写到js文件里哪个好?为什么? js和html还是分开比较好,一是各功能独立,界面比较干净,二是方便管理,关系清晰,三是方便引用,一些公共js独立导入可 ...

  5. JS 自写datapage.js 通用分页

    JS 自写datapage.js 通用分页 var Page = function () { }; Page.prototype = { Loading: "<img src='/Co ...

  6. 前端面试:手写代码JS实现字符串反转

    前端萌新面试:手写代码JS实现字符串反转 前言 因为做前年小红书的前端校招面试题,发现出现好几道关于字符串对象和数组对象的题目,说难不难,但突然要写的话一时想不起来,这不想着做个小总结. 首先明白字符 ...

  7. 手把手教你自己写一个js表单验证框架

    其实我自己也就能简单用用js而已,但是呢,相对很多初学者来说多懂了点Know How所以斗 胆孟浪一下,将一些所得记录下来,以供更多的初学者能够知道一个东西的实现过程,省去 在源码里摸索的过程. 在表 ...

  8. html 前端分页代码怎么写,前端js写分页

    一个朋友要写分页 问我怎么写我就给写了一个demo感兴趣的可以参考下 一共三个文件 page.js page.html index.json 这三个文件要放在同一个目录下 这里面有ajax请求所以必须 ...

  9. C#写的一个代码生成器

    在实际变成工作中,我们要写大量的程序,比如说把一个表转为一个类对象或者写一个调用带n个参数的存储过程的方法等都需要手工去输入大量的代码,并且还有大量的重复代码.为了避免大量的重复劳动,同时也为了工作的 ...

最新文章

  1. 基于GAN模型的生成人脸重构、返老还童、看见前世今生(Age Progression/Regression)
  2. 寻找Archie服务器中的文件,Archie服务
  3. Markdown 图片助手-MarkdownPicPicker
  4. STL中的list详解
  5. 三维重建学习(2):相机标定基础
  6. MyBatis-Plus 乐观锁 防止超卖、逻辑删除、自动填充、Id自增
  7. rip协议中周期性广播路由信息的报文_距离矢量路由协议(RIP)
  8. win7纯净版下载csdn_win10原版纯净版下载,安装技巧
  9. centos mysql 启动_MYSQL在centos上首次启动
  10. Windows编程—获取Chrome浏览器的安装目录
  11. Luke的各版本下载
  12. Ubuntu16.04安装python3.6.6步骤
  13. Spring容器中 singleton 单例、 prototype多例
  14. 想学python买什么书好-看了许多python书后!我发现学好python这三本书必看
  15. 【滤波器】基于matlab GUI FIR+IIR数字滤波器设计【含Matlab源码 324期】
  16. 开发反应执行阿里云mysql语句报错
  17. JSP+实验室设备管理 毕业设计-附源码191409
  18. RSA加密中PEM、DER的编解码问题
  19. OpenStack开源云平台
  20. Linux RAID磁盘阵列配置

热门文章

  1. java 获取叶子节点_java – 如何获取树的所有叶节点?
  2. IOException: Broken pipe
  3. 攻防世界 mobile 安卓移动端简单题练习区 答题(1-12题解)
  4. 【CCCC】L2-027 名人堂与代金券 (25分),模拟水题
  5. Apsara Clouder专项技能认证:实现调用API接口(阿里云疫情白给课程系列)
  6. 【PAT乙】1004 成绩排名 (20分) struct结构
  7. 【codevs1231】最优布线问题
  8. java 编译环境不一致_安装多JDK后,java编译环境和运行环境版本(JDK版本) 不一致解决:...
  9. 又见n/i下取整+分块
  10. god is a girl