好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

用C#写的JS代码生成器

用C#写的JS代码生成器

用C#写的JS代码生成器

 一接触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,如果有什么不对的地方请各位指正,很感谢。 从上一篇文章中,各位的指正让我明白了很多东西,抛砖引玉了。

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

 

 

分类:  框架设计

标签:  API ,  FluentAPI ,  框架设计 ,  C#

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于用C#写的JS代码生成器的详细内容...

  阅读:43次

上一篇: Linux下C编程

下一篇:进程间通信小结