`
xiaolu6t6t
  • 浏览: 2740 次
  • 性别: Icon_minigender_2
  • 来自: 郑州
最近访客 更多访客>>
社区版块
存档分类
最新评论

NFinal的生成原理 揭秘(一)

阅读更多

1.数据库生成方面:
在开发时,我们的数据库的类型是已知的.
因此,程序可以从SQL语句中判断出数据库类型,
然后再根据数据库类型判断出对应的csharp类型,最终生成类手工的代码.

2.Router生成方面
在开发时,控制器都是放在Controlers目录下.
因此通过分析类中的方法,就可以逆向生成相对应的Router执行代码.

 

3.代码的生成
代码生成利用的是.net开源的VTempalte引擎,此引擎使用LGPL协议.
请不要修改VTempalte中的代码,如果发布产品,也要公开VTempalte中的代码.  

 

下面来看一下生成Web层的代码:

 

using System;
using System.Collections.Generic;
using System.Web;
using System.Text.RegularExpressions;
using System.IO;
using System.Text;

namespace NFinal.Template
{
    /// <summary>
    /// ASPX模板引擎
    /// </summary>
    public class ASPX
    {
        /// <summary>
        /// 当某变量为空时设置默认值
        /// </summary>
        /// <param name="val">变量</param>
        /// <param name="def">默认值</param>
        /// <returns></returns>
        public string getString(string val, string def)
        {
            return string.IsNullOrEmpty(val) ? def : val;
        }
		/// <summary>
		/// 将View模板中的C#代码进行翻译转换
		/// </summary>
		/// <param name="template"></param>
		/// <returns></returns>
        public string TranslateHTMLTag(string template)
        {
            string ifBeginPattern = @"<if\s+condition\s*=\s*""\s*<%=((?><%(?<open>)|%>(?<-open>)|(?:(?!%>).)*)*(?(Open)(?!)))\s*%>\s*""\s*>";
            string elsePattern = @"<else\s*/>";
            string elseifPattern = @"<elseif\s+condition\s*=\s*""\s*<%=((?><%(?<open>)|%>(?<-open>)|(?:(?!%>).)*)*(?(Open)(?!)))\s*%>\s*""\s*>";
            string ifEndPattern = @"</if>";
            string foreachBeginPattern = @"<foreach\s+enumerator\s*=\s*""\s*<%\s*var\s+([_0-9a-zA-Z]+)\s*=([\s\S]+?);\s*%>\s*""\s*>";
            string foreachEndPattern = @"</foreach>";

            string switchBeginPattern = @"<switch\s*name\s*=\s*""\s*<%=((?><%(?<open>)|%>(?<-open>)|(?:(?!%>).)*)*(?(Open)(?!)))\S*%>\s*""\s*>";
            string caseBeginPattern = @"<case\s*value\s*=\s*""\s*<%=((?><%(?<open>)|%>(?<-open>)|(?:(?!%>).)*)*(?(Open)(?!)))\S*%>\s*""\s*>";
            string caseEndPattern = @"</case>";
            string defaultBeginPattern = @"<default>";
            string defaultEndPattern = @"</default>";
            string switchEndPattern = @"</switch>";

            string forBeginPattern = @"<for\s*start\s*=\s*""\s*<%\s*(int\s+)?([_0-9a-zA-Z]+)\s*=([\s\S]+?);*\s*%>\s*""\s*condition\s*=\s*""\s*<%=((?><%(?<open>)|%>(?<-open>)|(?:(?!%>).)*)*(?(Open)(?!)))\S*%>\s*""\s*step\s*=\s*""\s*<%\s*([_0-9a-zA-Z]+\s*[\s\S]+?)\s*%>\s*""\s*>";
            string forEndPattern = @"</for>";

            string whileBeginPattern = @"<while\s+condition\s*=\s*""\s*<%=((?><%(?<open>)|%>(?<-open>)|(?:(?!%>).)*)*(?(Open)(?!)))\s*%>\s*""\s*>";
            string whileEndPattern = @"</while>";

            //if
            Regex ifBeginReg = new Regex(ifBeginPattern);
            MatchCollection ifBeginMac = ifBeginReg.Matches(template);
            int relative_position = 0;
            string tempCode = string.Empty;
            for (int i = 0; i < ifBeginMac.Count; i++)
            {
                template = template.Remove(ifBeginMac[i].Index + relative_position, ifBeginMac[i].Length);
                tempCode = string.Format("<%if({0}){{%>", ifBeginMac[i].Groups[1].Value.Trim(';'));
                template = template.Insert(ifBeginMac[i].Index + relative_position, tempCode);
                relative_position += tempCode.Length - ifBeginMac[i].Length;
            }

            Regex elseReg = new Regex(elsePattern);
            MatchCollection elseMac = elseReg.Matches(template);
            relative_position = 0;
            for (int i = 0; i < elseMac.Count; i++)
            {
                template = template.Remove(elseMac[i].Index + relative_position, elseMac[i].Length);
                tempCode = "<%}else{%>";
                template = template.Insert(elseMac[i].Index + relative_position, tempCode);
                relative_position += tempCode.Length - elseMac[i].Length;
            }

            Regex elseifReg = new Regex(elseifPattern);
            MatchCollection elseifMac = elseifReg.Matches(template);
            relative_position = 0;
            for (int i = 0; i < elseifMac.Count; i++)
            {
                template = template.Remove(elseifMac[i].Index + relative_position, elseifMac[i].Length);
                tempCode = string.Format("<%}}else if({0}){{%>", elseifMac[i].Groups[1].Value.Trim(';', ' '));
                template = template.Insert(elseifMac[i].Index + relative_position, tempCode);
                relative_position += tempCode.Length - elseifMac[i].Length;
            }
            template = template.Replace(ifEndPattern, "<%}%>");

            //foreach
            Regex foreachBeginReg = new Regex(foreachBeginPattern);
            MatchCollection foreachBeginMac = foreachBeginReg.Matches(template);
            relative_position = 0;
            for (int i = 0; i < foreachBeginMac.Count; i++)
            {
                template = template.Remove(foreachBeginMac[i].Index + relative_position, foreachBeginMac[i].Length);
                tempCode = string.Format("<%var {0}={1}; while({0}.MoveNext()){{%>",
                    foreachBeginMac[i].Groups[1].Value, foreachBeginMac[i].Groups[2].Value);
                template = template.Insert(foreachBeginMac[i].Index + relative_position, tempCode);
                relative_position += tempCode.Length - foreachBeginMac[i].Length;
            }
            template = template.Replace(foreachEndPattern, "<%}%>");

            //switch
            Regex switchBeginReg = new Regex(switchBeginPattern);
            MatchCollection switchMac = switchBeginReg.Matches(template);
            relative_position = 0;
            for (int i = 0; i < switchMac.Count; i++)
            {
                template = template.Remove(switchMac[i].Index + relative_position, switchMac[i].Length);
                tempCode = string.Format("<%switch({0}){{%>", switchMac[i].Groups[1].Value.Trim(';', ' '));
                template = template.Insert(switchMac[i].Index + relative_position, tempCode);
                relative_position += tempCode.Length - switchMac[i].Length;
            }

            Regex casehBeginReg = new Regex(caseBeginPattern);
            MatchCollection caseMac = casehBeginReg.Matches(template);
            relative_position = 0;
            for (int i = 0; i < caseMac.Count; i++)
            {
                template = template.Remove(caseMac[i].Index + relative_position, caseMac[i].Length);
                tempCode = string.Format("<%case {0}:{{%>", caseMac[i].Groups[1].Value.Trim(';', ' '));
                template = template.Insert(caseMac[i].Index + relative_position, tempCode);
                relative_position += tempCode.Length - caseMac[i].Length;
            }

            template = template.Replace(caseEndPattern, "<%}break;%>");
            template = template.Replace(defaultBeginPattern, "<%default:{%>");
            template = template.Replace(defaultEndPattern, "<%}%>");
            template = template.Replace(switchEndPattern, "<%}%>");

            //for
            Regex forBeginReg = new Regex(forBeginPattern);
            MatchCollection forMac = forBeginReg.Matches(template);
            relative_position = 0;
            for (int i = 0; i < forMac.Count; i++)
            {
                template = template.Remove(forMac[i].Index + relative_position, forMac[i].Length);
                tempCode = string.Format("<%for({0} {1}={2};{3};{4}){{%>", forMac[i].Groups[1].Value.Trim(), forMac[i].Groups[2].Value, forMac[i].Groups[3].Value, forMac[i].Groups[4].Value.Trim(';', ' '), forMac[i].Groups[5].Value.Trim(';', ' '));
                template = template.Insert(forMac[i].Index + relative_position, tempCode);
                relative_position += tempCode.Length - forMac[i].Length;
            }

            template = template.Replace(forEndPattern, "<%}%>");

            //while
            Regex whileBeginReg = new Regex(whileBeginPattern);
            MatchCollection whileBeginMac = whileBeginReg.Matches(template);
            relative_position = 0;
            tempCode = string.Empty;
            for (int i = 0; i < whileBeginMac.Count; i++)
            {
                template = template.Remove(whileBeginMac[i].Index + relative_position, whileBeginMac[i].Length);
                tempCode = string.Format("<%while({0}){{%>", whileBeginMac[i].Groups[1].Value.Trim(';', ' '));
                template = template.Insert(whileBeginMac[i].Index + relative_position, tempCode);
                relative_position += tempCode.Length - whileBeginMac[i].Length;
            }

            template = template.Replace(whileEndPattern, "<%}%>");

            return template;
        }
        /// <summary>
        /// 获取模板渲染后的字符串
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <param name="encoding">文件的编码方式</param>
        /// <returns></returns>
        public string GetRenderText(string fileName, System.Text.Encoding encoding, int tab)
        {
            StringWriter sw = new StringWriter();
            Render(sw, fileName, tab);
            return sw.ToString();
        }
        /// <summary>
        /// 获取完整的模板字符串
        /// </summary>
        /// <param name="template">模板字符串</param>
        /// <returns>模板字符串,包含引用模板的信息</returns>
        public string GetAllTemplateFromReference(string template)
        {
            return template;
        }

		/// <summary>
		/// 找出模板中引入的用户控件
		/// </summary>
		/// <param name="template"></param>
		/// <returns></returns>
        public Dictionary<string, string> GetRegistWebControls(string template)
        {
            string pattern = @"<%@\s+Register\s+Src=""([^""\s]+)""\s+TagPrefix=""([^""\s]+)""\s+TagName=""([^""\s]+)""\s*%>";
            Regex reg = new Regex(pattern, RegexOptions.IgnoreCase);
            Dictionary<string, string> dicControls = new Dictionary<string, string>();
            MatchCollection mac = reg.Matches(template);
            if (mac.Count > 0)
            {
                for (int i = 0; i < mac.Count; i++)
                {
                    dicControls.Add(mac[i].Groups[2].Value + ":" + mac[i].Groups[3].Value, mac[i].Groups[1].Value);
                }
            }
            return dicControls;
        }
		/// <summary>
		/// 删除ViewBag字符串
		/// </summary>
		/// <param name="text"></param>
		/// <returns></returns>
        public string DeleteViewBag(string text)
        {
            string pattern = @"[^_0-9a-zA-Z](ViewBag\s*\.\s*)";
            Regex reg = new Regex(pattern, RegexOptions.Multiline);
            MatchCollection mac = reg.Matches(text);
            int position_relative = 0;
            for (int i = 0; i < mac.Count; i++)
            {
                text= text.Remove(position_relative +mac[i].Groups[1].Index, mac[i].Groups[1].Length);
                position_relative -= mac[i].Groups[1].Length;
            }
            pattern = @"^\s*(ViewBag\s*\.\s*)";
            reg = new Regex(pattern, RegexOptions.Multiline);
            mac = reg.Matches(text);
            position_relative = 0;
            for (int i = 0; i < mac.Count; i++)
            {
                text = text.Remove(position_relative + mac[i].Groups[1].Index, mac[i].Groups[1].Length);
                position_relative -= mac[i].Groups[1].Length;
            }
            return text;
        }

		/// <summary>
		/// 将用户控件转换为相应的控件中的内容
		/// </summary>
		/// <param name="template"></param>
		/// <param name="deepth"></param>
		/// <returns></returns>
        public string TransWebControls(string template, int deepth)
        {
            Dictionary<string, string> dicControls = GetRegistWebControls(template);
            string pattern = @"<(([^<\s:>]+):([^<\s:>]+))\s+runat\s*=\s*""server""(\s+id\s*=\s*""([^""\s]*)"")?\s*/>";
            Regex reg = new Regex(pattern, RegexOptions.IgnoreCase);
            MatchCollection mac = reg.Matches(template);
            string fileName;
            string content;
            Match m;
            int relative_position = 0;
            if (mac.Count > 0 && deepth < 6)
            {
                for (int i = 0; i < mac.Count; i++)
                {
                    m = mac[i];
                    if (dicControls.ContainsKey(mac[i].Groups[1].Value))
                    {
                        fileName = Frame.MapPath(dicControls[mac[i].Groups[1].Value].TrimStart('~'));
                        StreamReader sr = new StreamReader(fileName, System.Text.Encoding.UTF8);
                        content = sr.ReadToEnd();
                        template = template.Remove(relative_position + m.Index, m.Length);
                        if (mac[i].Groups[4].Success == false || mac[i].Groups[5].Value.Trim() == "")
                        {
                            template = template.Insert(relative_position + m.Index, content);
                        }
                        else
                        {
                            content = string.Format("<%{0}.__render__ = ({1}ViewBag)=>{{ %>{2}<%}};{0}.__render__({0});%>",
                                mac[i].Groups[5].Value.Trim(), mac[i].Groups[3].Value.Trim(), content);
                            template = template.Insert(relative_position + m.Index,content);
                        }
                        relative_position += content.Length - m.Length;
                    }
                    //如果找不到注册的组件名,则删除
                    else
                    {
                        template = template.Remove(relative_position + m.Index, m.Length);
                        relative_position -= m.Length;
                    }
                }
                template = TransWebControls(template, deepth);
            }
            return template;
        }
        /// <summary>
        /// 渲染模板
        /// </summary>
        /// <param name="writer">写操作类</param>
        /// <param name="template">模板字符串</param>
        /// <returns></returns>
        public string Render(TextWriter writer, string template, int tab)
        {
            int deepth = 0;
            //template= Reference(template,deepth);
            deepth = 0;
            template = TransWebControls(template, deepth);
            template = TranslateHTMLTag(template);
            template= HtmlCompressor.compress(template);
            string text = "";
            string section = @"(?isx)<%((?><%(?<open>)|%>(?<-open>)|(?:(?!%>).)*)*(?(Open)(?!)))%>";
            Regex reg = new Regex(section);
            MatchCollection matches = reg.Matches(template);
            //开始
            int text_start = 0;
            //结束
            int text_end = 0;
            if (matches.Count > 0)
            {
                foreach (Match m in matches)
                {
                    text_end = m.Index - 1;
                    if (m.Groups[1].Value[0] == '@')
                    {

                        //添加写入html的源码字符串
                        if (text_end - text_start >= 0)
                        {
                            text = template.Substring(text_start, text_end - text_start + 1);
                            if (!IsNullOrWhiteSpace(text))
                            {
                                WriteTab(writer, tab);
                                text = BuildWriteCode(text);
                                writer.WriteLine(text);
                            }
                        }
                        //如果<%@ Reference VirtualPath="" %>

                        //让开头指向结尾
                        text_start = m.Index + m.Length;
                    }
                    else if (m.Groups[1].Value[0] == '=')
                    {
                        //添加写入html的源码字符串
                        if (text_end - text_start >= 0)
                        {
                            text = template.Substring(text_start, text_end - text_start + 1);
                            if (!IsNullOrWhiteSpace(text))
                            {
                                WriteTab(writer, tab);
                                text = BuildWriteCode(text);
                                writer.WriteLine(text);
                            }
                        }
                        //替换掉<%%>,转为源码

                        if (m.Value.IndexOf("}") > 0)
                        {
                            tab--;
                        }
                        WriteTab(writer, tab);
                        writer.WriteLine(BuildWriteVar(m.Groups[1].Value.Trim().TrimStart('=').TrimEnd(';')));
                        if (m.Value.IndexOf("{") > 0)
                        {
                            tab++;
                        }
                        //让开头指向结尾
                        text_start = m.Index + m.Length;
                    }
                    else
                    {

                        //添加写入html的源码字符串
                        if (text_end - text_start >= 0)
                        {
                            text = template.Substring(text_start, text_end - text_start + 1);
                            if (!IsNullOrWhiteSpace(text))
                            {
                                WriteTab(writer, tab);
                                text = BuildWriteCode(text);
                                writer.WriteLine(text);
                            }
                        }

                        if (m.Value.IndexOf("}") > 0)
                        {
                            tab--;
                        }
                        //替换掉<%%>,转为源码
                        WriteTab(writer, tab);
                        writer.WriteLine(DeleteViewBag(m.Groups[1].Value));
                        if (m.Value.IndexOf("{") > 0)
                        {
                            tab++;
                        }
                        //让开头指向结尾
                        text_start = m.Index + m.Length;
                    }
                }
                text_end = template.Length - 1;
                text = template.Substring(text_start, text_end - text_start + 1);
                if (!IsNullOrWhiteSpace(text))
                {
                    WriteTab(writer, tab);
                    text = BuildWriteCode(text);
                    writer.WriteLine(text);
                }
            }
            writer.Close();
            return writer.ToString();
        }
        /// <summary>
        /// 输入代码中的缩进
        /// </summary>
        /// <param name="tw">写类</param>
        /// <param name="tab">table符的数量</param>
        /// <param name="isFirstLine">是否是第一行</param>
        public void WriteTab(TextWriter tw, int tab)
        {
            if (tab > 0)
            {
                for (int i = 0; i < tab; i++)
                {
                    tw.Write("\t");
                }
            }
        }
        /// <summary>
        /// 返回写变量的csharp代码
        /// </summary>
        /// <param name="text">内容</param>
        /// <returns></returns>
        public string BuildWriteVar(string text)
        {
            //text = ReserveString(text);//输出csharp无需转义
            text = string.Format("Write({0});", DeleteViewBag(text.Trim()));
            return text;
        }
        public bool IsNullOrWhiteSpace(string text)
        {
            char[] space = new char[] { ' ', '\r', '\n', '\t', '\f', '\v' };
            return string.IsNullOrEmpty(text.Trim(space));
        }
        /// <summary>
        /// 返回输出字符串的csharp代码
        /// </summary>
        /// <param name="text">字符串</param>
        /// <returns></returns>
        public string BuildWriteCode(string text)
        {
            
            text = ReserveString(text);
            text = string.Format("Write(\"{0}\");", text.Trim());
            return text;
        }
        /// <summary>
        /// 字符串反转义
        /// </summary>
        /// <param name="text">字符串</param>
        /// <returns>返回csharp中的字符串表示</returns>
        public string ReserveString(string text)
        {
            char[] temp_old = text.ToCharArray();

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < temp_old.Length; i++)
            {
                switch (temp_old[i])
                {
                    case '\'': sb.Append("\\\'"); break;
                    case '\"': sb.Append("\\\""); break;
                    case '\\': sb.Append("\\\\"); break;
                    case '\0': sb.Append("\\0"); break;
                    case '\a': sb.Append("\\a"); break;
                    case '\b': sb.Append("\\b"); break;
                    case '\f': sb.Append("\\f"); break;
                    case '\n': sb.Append("\\n"); break;
                    case '\r': sb.Append("\\r"); break;
                    case '\t': sb.Append("\\t"); break;
                    case '\v': sb.Append("\\v"); break;
                    default: sb.Append(temp_old[i]); break;
                }
            }
            return sb.ToString();
        }
        /// <summary>
        /// 渲染模板
        /// </summary>
        /// <param name="context">页面类</param>
        /// <param name="fileName">模板文件名</param>
        public void Render(HttpContext context, string fileName, int tab)
        {
            Render(context.Response.Output, context.Server.MapPath(fileName), tab);
        }
        /// <summary>
        /// 渲染模板到指定文件
        /// </summary>
        /// <param name="fileName">模板文件路径</param>
        /// <param name="outFileName">输出文件路径</param>
        public void RenderTo(string fileName, string outFileName, int tab)
        {
            if (!Directory.Exists(Path.GetDirectoryName(outFileName)))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(outFileName));
            }
            StreamWriter sw = new StreamWriter(outFileName, false, System.Text.Encoding.UTF8);
            Render(sw, fileName, tab);
        }
    }
}

 

分享到:
评论

相关推荐

    NFinal最快的.net mvc框架

    NFinal框架是基于新的魔法糖思想创建的框架 论坛网址:http://bbs.nfinal.com 视频网址:http://bbs.nfinal.com/index.php?c=thread&fid=3 NFinal框架是基于新的魔法糖思想创建的框架 本框架有两大特点. 1.所有框架...

    NFinal:最快的 .net MVC 框架

    2.类似于thinkphp,整个项目只有一个文件夹,无需任何配置,复制到网站项目下运行WebCompiler.exe即可, Lucas会根据系统的IIS版本自动修改Web.config文件,以及引入相关的dll文件.并且会自动配置好自动生成. (当您编译...

    数学建模灰色预测MATLAB程序

    1. **累积生成处理**:对原始数据序列 \( x(k) \) 进行一次累积生成处理,得到新的数据序列 \( \hat{x}(k) \)。 2. **构建背景值**:计算背景值 \( z(k) \),一般采用加权平均的方式。 3. **建立模型方程**:利用...

    EvaluacionModulo4:Evaluaciónfinal del modulo 4

    Java是一种广泛使用的、面向对象的编程语言,由Sun Microsystems(现为Oracle Corporation的一部分)于1995年推出。它的设计目标是实现“编写一次,到处运行”(Write Once, Run Anywhere)的跨平台能力,通过Java...

    Final-SO:Proyecto解析器comoevaluaciónfinal

    Evaluación决赛-Sistemas Operativos普遍适用的诉讼程序监控Java使用状况入门Descargar el repositorio como ZIP。 地方法院内部档案。 Utilizar NetBeans IDE(推荐),从头到尾都是proyecto。...

    C语言链表解决汉诺塔问题

    接下来,创建一个函数`createNode(int size)`用于生成新的节点,初始化其大小值: ```c Node* createNode(int size) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode-&gt;size = size; newNode-&gt;next = ...

    modulo-3-evaluacion-final-Martcacio:Evaluaciónfinal modulo 3玛塔·卡诺

    你好! 里克·莫蒂(Rick y Morty)的礼物。 失去了对自己的印象,就失去了自己的人格。 在德勒达拉达州立大学的女校长,在西班牙代表处任职。 在任何情况下都无法识别的URL或可疑对象的名称,可以在图像上显示出来...

    Final IK 当前最新版

    《Final IK:Unity中的高效骨骼IK解决方案》\n\nFinal IK是Unity引擎中的一款强大插件,专为解决角色Inverse Kinematics(IK)问题而设计。在游戏开发中,IK系统对于实现逼真的角色动画至关重要,它使得角色的肢体...

    Java SwingWorkder使用实例

    taOutput.append("\nFinal Result: " + result + "\n"); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } }; // 监听按钮事件 b.addActionListener(new ActionListener...

Global site tag (gtag.js) - Google Analytics