WEB开发网
开发学院软件开发C语言 C#模板编程(2): 编写C#预处理器,让模板来的再自然... 阅读

C#模板编程(2): 编写C#预处理器,让模板来的再自然一点

 2010-09-30 22:42:25 来源:WEB开发网   
核心提示:在《C#模板编程(1):有了泛型,为什么还需要模板?》文中,C#模板编程(2): 编写C#预处理器,让模板来的再自然一点,指出了C#泛型的局限性,为了突破这个局限性,A文件内容为:XXX#regioninclude"B.cs"#endregionXXXB.cs 文件内容为:YYY#regionmix

在《C#模板编程(1):有了泛型,为什么还需要模板?》文中,指出了C#泛型的局限性,为了突破这个局限性,我们需要模板编程。但是,C#语法以及IDE均不支持C#模板编程,怎么办呢?自己动手,丰衣足食,编写自己的C#预处理器。

一、C#预处理机制设计

问题的关键就是在C#的源文件中引入include机制,设计下面的语法:

(1) 引入:#region include <path> #endregion

(2) 被引:#region mixin … #endgion

例子:假设A.cs需要引用B.cs中的代码。A文件内容为:

XXX
#region include "B.cs"
#endregion
XXX

B.cs 文件内容为:

YYY
#region mixin
MMM
#endregion
ZZZ

运行预处理器,对A文件进行处理,生成第三个文件A_.cs:

XXX
MMM
XXX

二、实现

编写预处理器:Csmacro.exe[Csmacro.zip](意思是CSharp Macro)程序,代码如下:

Csmacro

  1 using System;
  2 using System.Collections.Generic;
  3 using System.IO;
  4 using System.Text;
  5 using System.Text.RegularExpressions; 
  6 
  7 namespace Orc.Util.Csmacro
  8 {
  9     class Program
 10     {
 11         static Regex includeReg = new Regex("#region\\s+include.+\\s+#endregion");
 12         static Regex mixinReg = new Regex("(?<=#region\\s+mixin\\s)[\\s|\\S]+(?=#endregion)"); 
 13 
 14         /// <summary>
 15         /// Csmacro [dir|filePath]
 16         /// 
 17         /// 语法:
 18         ///     #region include ""
 19         ///     #endregion
 20         ///     
 21         /// </summary>
 22         /// <param name="args"></param>
 23         static void Main(string[] args)
 24         {
 25             if (args.Length != 1)
 26             {
 27                 PrintHelp();
 28                 return;
 29             } 
 30 
 31             String filePath = args[0]; 
 32 
 33             Path.GetDirectoryName(filePath);
 34             String dirName = Path.GetDirectoryName(filePath);
 35 #if DEBUG
 36             Console.WriteLine("dir:" + dirName);
 37 #endif
 38             String fileName = Path.GetFileName(filePath);
 39 #if DEBUG
 40             Console.WriteLine("file:" + fileName);
 41 #endif 
 42 
 43             if (String.IsNullOrEmpty(fileName))
 44             {
 45                 Csmacro(new DirectoryInfo(dirName));
 46             }
 47             else
 48             {
 49                 if (fileName.EndsWith(".cs") == false)
 50                 {
 51                     Console.WriteLine("Csmacro只能处理后缀为.cs的源程序.");
 52                 }
 53                 else
 54                 {
 55                     Csmacro(new FileInfo(fileName));
 56                 }
 57             } 
 58 
 59             Console.WriteLine("[Csmacro]:处理完毕."); 
 60 
 61 #if DEBUG
 62             Console.ReadKey();
 63 #endif
 64         } 
 65 
 66         static void Csmacro(DirectoryInfo di)
 67         {
 68             Console.WriteLine("[Csmacro]:进入目录" + di.FullName); 
 69 
 70             foreach (FileInfo fi in di.GetFiles("*.cs", SearchOption.AllDirectories))
 71             {
 72                 Csmacro(fi);
 73             }
 74         } 
 75 
 76         static void Csmacro(FileInfo fi)
 77         {
 78             String fullName = fi.FullName;
 79             if (fi.Exists == false)
 80             {
 81                 Console.WriteLine("[Csmacro]:文件不存在-" + fullName);
 82             }
 83             else if (fullName.EndsWith("_Csmacro.cs"))
 84             {
 85                 return;
 86             }
 87             else
 88             {
 89                 String text = File.ReadAllText(fullName); 
 90 
 91                 DirectoryInfo parrentDirInfo = fi.Directory; 
 92 
 93                 MatchCollection mc = includeReg.Matches(text);
 94                 if (mc == null || mc.Count == 0) return;
 95                 else
 96                 {
 97                     Console.WriteLine("[Csmacro]:处理文件" + fullName); 
 98 
 99                     StringBuilder sb = new StringBuilder();
100                     Match first = mc[0];
101                     Match last = mc[mc.Count - 1]; 
102 
103                     sb.Append(text.Substring(0, first.Index)); 
104 
105                     foreach (Match m in mc)
106                     {
107                         String tmp = Csmacro(parrentDirInfo, m.Value);
108                         sb.Append(tmp);
109                     } 
110 
111                     Int32 lastEnd = last.Index + last.Length;
112                     if (lastEnd < text.Length)
113                     {
114                         sb.Append(text.Substring(lastEnd));
115                     }
116                     String newName = fullName.Substring(0, fullName.Length - 3) + "_Csmacro.cs";
117                     if (File.Exists(newName))
118                     {
119                         Console.WriteLine("[Csmacro]:删除旧文件" + newName);
120                     }
121                     File.WriteAllText(newName, sb.ToString());
122                     Console.WriteLine("[Csmacro]:生成文件" + newName);
123                 }
124             }
125         } 
126 
127         static String Csmacro(DirectoryInfo currentDirInfo, String text)
128         {
129             String outfilePath = text.Replace("#region", String.Empty).Replace("#endregion", String.Empty).Replace("include",String.Empty).Replace("\"",String.Empty).Trim();
130             try
131             {
132                 if (Path.IsPathRooted(outfilePath) == false)
133                 {
134                     outfilePath = currentDirInfo.FullName + @"\" + outfilePath;
135                 }
136                 FileInfo fi = new FileInfo(outfilePath);
137                 if (fi.Exists == false)
138                 {
139                     Console.WriteLine("[Csmacro]:文件" + fi.FullName + "不存在.");
140                     return text;
141                 }
142                 else
143                 {
144                     return GetMixinCode(File.ReadAllText(fi.FullName));
145                 }
146             }
147             catch (Exception ex)
148             {
149                 Console.WriteLine("[Csmacro]:出现错误(" + outfilePath + ")-" + ex.Message);
150             }
151             finally
152             {
153             }
154             return text;
155         } 
156 
157         static String GetMixinCode(String txt)
158         {
159             Match m = mixinReg.Match(txt);
160             if (m.Success == true)
161             {
162                 return m.Value;
163             }
164             else return String.Empty;
165         } 
166 
167         static void PrintHelp()
168         {
169             Console.WriteLine("Csmacro [dir|filePath]");
170         }
171     }
172 }
173 
174 

1 2 3  下一页

Tags:模板 编程 编写

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接