日韩亚洲欧美在线com|日本xxxx色视频在线播放|国产熟妇与子伦hd|欧美freesex黑人又粗又大|国产欧美日韩一区二区三区

在《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 == 0return;
 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 

 

編譯之后,放在系統路徑下(或放入任一在系統路徑下的目錄)。然后,在VS的項目屬性的Build Events的Pre-build event command line中寫入“Csmacro.exe $(ProjectDir)”,即可在編譯項目之前,對$(ProjectDir)目錄下的所有cs程序進行預處理。

Csmacro.exe 對于包含#region include <path> #endregion代碼的程序xx.cs,預處理生成名為 xx_Csmacro.cs的文件;對于文件名以"Csmacro.cs”結尾的文件,則不進行任何處理。

使用時要注意:

(1)#region include <path> 與 #endregion 之間不能有任何代碼;

(2)#region mixin 與 #endgion 之間不能有其它的region

(3)不支持多級引用

三、示例

下面,以《C#模板編程(1):有了泛型,為什么還需要模板?》文尾的例子說明怎樣編寫C#模板程序:

(1)建立一個模板類 FilterHelper_Template.cs ,編譯通過:

FilterHelper_Template.cs
 1 using TPixel = System.Byte; 
 2 using TCache = System.Int32; 
 3 using TKernel = System.Int32; 
 4 
 5 using System; 
 6 using System.Collections.Generic; 
 7 using System.Text; 
 8 
 9 namespace Orc.SmartImage.Hidden 
10 
11     static class FilterHelper_Template 
12     { 
13         #region mixin 
14 
15         // 本算法是錯誤的,只為說明C#模板程序的使用。 
16         public unsafe static UnmanagedImage<TPixel> Filter(this UnmanagedImage<TPixel> src, FilterKernel<TKernel> filter) 
17         { 
18             TKernel* kernel = stackalloc TKernel[filter.Length]; 
19 
20             Int32 srcWidth = src.Width; 
21             Int32 srcHeight = src.Height; 
22             Int32 kWidth = filter.Width; 
23             Int32 kHeight = filter.Height; 
24 
25             TPixel* start = (TPixel*)src.StartIntPtr; 
26             TPixel* lineStart = start; 
27             TPixel* pStart = start; 
28             TPixel* pTemStart = pStart; 
29             TPixel* pT; 
30             TKernel* pK; 
31 
32             for (int c = 0; c < srcWidth; c++
33             { 
34                 for (int r = 0; r < srcHeight; r++
35                 { 
36                     pTemStart = pStart; 
37                     pK = kernel; 
38 
39                     Int32 val = 0
40                     for (int kc = 0; kc < kWidth; kc++
41                     { 
42                         pT = pStart; 
43                         for (int kr = 0; kr < kHeight; kr++
44                         { 
45                             val += *pK * *pT; 
46                             pT++
47                             pK++
48                         } 
49 
50                         pStart += srcWidth; 
51                     } 
52 
53                     pStart = pTemStart; 
54                     pStart++
55                 } 
56 
57                 lineStart += srcWidth; 
58                 pStart = lineStart; 
59             } 
60             return null
61         } 
62         #endregion 
63     } 
64 }
65 
66 

 這里,我使用了命名空間Hidden,意思是這個命名空間不想讓外部使用,因為它是模板類。

 

(2)編寫實例化模板類 ImageU8FilterHelper.cs

ImageU8FilterHelper.cs
 1 using System; 
 2 using System.Collections.Generic; 
 3 using System.Text; 
 4 
 5 namespace Orc.SmartImage 
 6 
 7     using TPixel = System.Byte; 
 8     using TCache = System.Int32; 
 9     using TKernel = System.Int32; 
10 
11     public static partial class ImageU8FilterHelper 
12     { 
13         #region include "FilterHelper_Template.cs" 
14         #endregion 
15     } 
16 }

注意:這里使用 partial class 是為了使代碼與預處理器生成的代碼共存,不產生編譯錯誤。

 

(3)編譯項目,可以發現,預處理器自動生成了代碼文件ImageU8FilterHelper_Csmacro.cs,且編譯通過:

ImageU8FilterHelper_Csmacro.cs
 1 using System; 
 2 using System.Collections.Generic; 
 3 using System.Text; 
 4 
 5 namespace Orc.SmartImage 
 6 
 7     using TPixel = System.Byte; 
 8     using TCache = System.Int32; 
 9     using TKernel = System.Int32; 
10 
11     public static partial class ImageU8FilterHelper 
12     {
13 
14         // 本算法是錯誤的,只為說明C#模板程序的使用。 
15         public unsafe static UnmanagedImage<TPixel> Filter(this UnmanagedImage<TPixel> src, FilterKernel<TKernel> filter) 
16         { 
17             TKernel* kernel = stackalloc TKernel[filter.Length]; 
18 
19             Int32 srcWidth = src.Width; 
20             Int32 srcHeight = src.Height; 
21             Int32 kWidth = filter.Width; 
22             Int32 kHeight = filter.Height; 
23 
24             TPixel* start = (TPixel*)src.StartIntPtr; 
25             TPixel* lineStart = start; 
26             TPixel* pStart = start; 
27             TPixel* pTemStart = pStart; 
28             TPixel* pT; 
29             TKernel* pK; 
30 
31             for (int c = 0; c < srcWidth; c++
32             { 
33                 for (int r = 0; r < srcHeight; r++
34                 { 
35                     pTemStart = pStart; 
36                     pK = kernel; 
37 
38                     Int32 val = 0
39                     for (int kc = 0; kc < kWidth; kc++
40                     { 
41                         pT = pStart; 
42                         for (int kr = 0; kr < kHeight; kr++
43                         { 
44                             val += *pK * *pT; 
45                             pT++
46                             pK++
47                         } 
48 
49                         pStart += srcWidth; 
50                     } 
51 
52                     pStart = pTemStart; 
53                     pStart++
54                 } 
55 
56                 lineStart += srcWidth; 
57                 pStart = lineStart; 
58             } 
59             return null
60         } 
61     } 
62 }
63 
64 

四、小結

這樣一來,C#模板類使用就方便了很多,不必手動去處理模板類的復制和粘帖。雖然仍沒有C++模板使用那么自然,畢竟又近了一步。:P

 

主站蜘蛛池模板: 亚洲精欧美一区二区精品| 日韩精品无码一本二本三本色 | 久久精品国产精品亚洲38| 18禁黄网站禁片免费观看女女| 看成年全黄大色黄大片| 亚洲最新版av无码中文字幕| 人妻系列高清在线一区| 国产精品久久久久电影网| 久久精品一区二区免费播放| 亚洲男人的天堂在线aⅴ视频| 内射中文字幕一区| 2019精品手机国产品在线| 亚洲a∨大乳天堂在线| 1000部啪啪未满十八勿入下载| 成人免费毛片aaaaaa片| 国产va精品午夜福利视频| 久久大香香蕉国产免费网动漫 | 日本狂喷奶水在线播放212| 国产精品h片在线播放| 日本黄网免费一区二区精品 | 亚洲美女av在线一区| 日本精品3p视频一区二区| 亚洲人成网站日本片| 蜜臀久久人妻一区二区| 丝袜国产一区二区| 华人在线亚洲欧美精品| 四虎国产成人永久精品免费| 国产在线精品一区二区三区| 人妻丰满熟妇aⅴ无码| 亚洲美女在线看一区二区| 久久精品国产自在天天线| 欧美精品日韩一区在线观看| 国产精品爱久久久久久久电影蜜臀| 国产伦精品一区二区三区免费 | 三上悠亚久久精品| 国产国拍亚洲精品av| 美女脱了内裤张开腿让男人桶网站 | 正在播放老肥熟妇露脸| 69精品国产久热在线观看| 亚洲熟妇中文字幕日产无码| 欧美成人一区二区三区|