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

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

     
     
    分类: 框架设计
    标签: APIFluentAPI框架设计C#
  • 相关阅读:
    在eclipse中快速多行注释的方法
    Android开发:去掉Activity的头部标题栏及全屏显示
    C#的Process类的一些用法
    C#中隐式操作CMD命令行窗口 (转)
    我的INI 配置文件读写动态库
    Android高手进阶教程(五)之----Android 中LayoutInflater的使用!
    Android高手进阶教程(六)之----Android 中MenuInflater的使用(布局定义菜单)!
    Android Menu 之 optionsMenu 详解
    centos安装php扩展
    linux 权限
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2989860.html
Copyright © 2011-2022 走看看