一直想写一个Code生成系列,但写到CodeSimth,发觉在TerryLee努力学习的小熊 两位大牛的博客里讲很详尽,所以就像写些示例方面的,但是苦于没有想到写些什么。最近Artech写了两篇从数据到代码——通过代码生成机制实现强类型编程--上篇和下篇,大牛写得是CodeDom的,今天我就想借借大牛的示例写个CodeSimth版的,希望Artech不要怪我,呵呵。我的Code生成技术已经写了CodeDom的见CodeDom系列目录,欢迎各位园友指教。

        好直接到主题。首先是数据实体MessageEntry(我到老A的基础上添加了description属性作为代码字段描述):

  1. 代码   
  2.  
  3.  1 namespace Wolf   
  4.  2 {   
  5.  3     public class MessageEntry   
  6.  4     {   
  7.  5         public string Id { get; private set; }   
  8.  6         public string Value { get; private set; }          
  9.  7         public string Description { get; private set; }   
  10.  8         public MessageEntry(string id, string value)   
  11.  9         {   
  12. 10             this.Id = id;   
  13. 11             this.Value = value;           
  14. 12         }   
  15. 13   
  16. 14         public MessageEntry(string id, string value, string description)   
  17. 15         {   
  18. 16             this.Id = id;   
  19. 17             this.Value = value;   
  20. 18             this.Description = description;   
  21. 19         }   
  22. 20   
  23. 21         public string Format(params object[] args)   
  24. 22         {   
  25. 23             return string.Format(this.Value, args);   
  26. 24         }   
  27. 25     }   
  28. 26 }  
  29. 27   
  30. 28   
  31. 复制代码 

在我的机子上的COdeSimth是2..0版本的所以不能使用Linq命名空间,我又想利用这个空间,比较快捷,所以我就在先3.0转化为

Dictionary<string, List<MessageEntry>>实体再传入模板:

Code:

  1. 代码   
  2.  
  3.  1 using System;   
  4.  2 using System.Collections.Generic;   
  5.  3 using System.Linq;   
  6.  4 using System.Text;   
  7.  5 using System.Xml;   
  8.  6 using System.Xml.Linq;   
  9.  7   
  10.  8 namespace Wolf   
  11.  9 {   
  12. 10     public class MessageCodeGenerator   
  13. 11     {   
  14. 12         public Dictionary<string, List<MessageEntry>> GeneratorCode(string  path)   
  15. 13         {   
  16. 14             return GeneratorCode(XElement.Load(path));   
  17. 15         }   
  18. 16         public Dictionary<string, List<MessageEntry>> GeneratorCode(XElement root)   
  19. 17         {   
  20. 18   
  21. 19             var elemts = root.Elements("message").GroupBy(e => ((XAttribute)e.Attribute("category")).Value);   
  22. 20             Dictionary<string, List<MessageEntry>> dict = new Dictionary<string, List<MessageEntry>>();   
  23. 21             foreach (var item in elemts)   
  24. 22             {   
  25. 23                 List<MessageEntry> list = new List<MessageEntry>();   
  26. 24                 foreach (var g in item)   
  27. 25                 {   
  28. 26                     if (g.Attribute("description") != null)   
  29. 27                     {   
  30. 28                         list.Add(new MessageEntry(((XAttribute)g.Attribute("id")).Value, ((XAttribute)g.Attribute("value")).Value, ((XAttribute)g.Attribute("description")).Value));   
  31. 29                     }   
  32. 30                     else   
  33. 31                     {   
  34. 32                         list.Add(new MessageEntry(((XAttribute)g.Attribute("id")).Value, ((XAttribute)g.Attribute("value")).Value));   
  35. 33                     }   
  36. 34   
  37. 35                 }   
  38. 36                 dict.Add(item.Key.ToString(), list);   
  39. 37             }   
  40. 38             return dict;   
  41. 39   
  42. 40         }   
  43. 41     }   
  44. 42 }  
  45. 43   
  46. 44   
  47. 复制代码 

这下几可开始写模板了,见下Code:

  1. 代码   
  2.  
  3.  1 <%@ CodeTemplate Language="C#" TargetLanguage="Text" Src="" Inherits="" Debug="False" Description="Template description here." %>   
  4.  2   
  5.  3 <%@ Import NameSpace="System" %>   
  6.  4 <%@ Import NameSpace="System.Xml" %>   
  7.  5 <%@ Import NameSpace="System.Text" %>   
  8.  6 <%@ Import NameSpace="System.Collections.Generic" %>   
  9.  7 <%@ Import NameSpace="Wolf" %>   
  10.  8 <%@ Assembly Name="Wolf" %>   
  11.  9   
  12. 10 <script runat="template">   
  13. 11   
  14. 12 private Dictionary<string, List<MessageEntry>> dict;   
  15. 13 public Dictionary<string, List<MessageEntry>> Generator   
  16. 14 {   
  17. 15     get   
  18. 16     {   
  19. 17         return dict;   
  20. 18     }   
  21. 19     set   
  22. 20     {   
  23. 21         dict=value;   
  24. 22     }   
  25. 23 }   
  26. 24   
  27. 25 public string GeneratorCode()   
  28. 26         {              
  29. 27             string str = "using Wolf;\r\nusing System;\r\nusing System.Collections.Generic;\r\nnamespace Wolf.Message\r\n{ \r\n   public class Messages\r\n    {\r\n";   
  30. 28             foreach (string catage in Generator.Keys)   
  31. 29             {   
  32. 30                 str += "        public class  "+catage + "\r\n        {        \r\n";   
  33. 31                 foreach (Wolf.MessageEntry entry in Generator[catage])   
  34. 32                 {   
  35. 33                     str += "\r\n            /// <summary>" +   
  36. 34                     "\r\n            ///" + entry.Description +   
  37. 35                     "\r\n            /// </summary>" +   
  38. 36                     "\r\n            public static Wolf.MessageEntry " + entry.Id + " = new MessageEntry(\"" + entry.Id + "\", \"" + entry.Value +"\", \"" + entry.Value +"\");\r\n";   
  39. 37                 }   
  40. 38                 str += "\r\n        }\r\n\r\n";   
  41. 39   
  42. 40             }   
  43. 41             str += "\r\n    }\r\n}";   
  44. 42             return str;   
  45. 43         }   
  46. 44   
  47. 45 </script>   
  48. 46 //Copyright (C) Wolf.  All rights reserved.   
  49. 47 <%=  GeneratorCode()%>  
  50. 48   
  51. 49   
  52. 复制代码 

很简单,就不说了,如果有问题请留言,其中命名空间完全可以以属性方式传入。

XMl实体用的是老A的:代码

  1. 1 <?xml version="1.0" encoding="utf-8" ?>    
  2. 2 <messages>     
  3. 3 <message id="MandatoryField" value="The {0} is mandatory."  category="Validation"  description="description" />     
  4. 4 <message id="GreaterThan" value="The {0} must be greater than {1}."  category="Validation" description="description" />     
  5. 5 <message id="ReallyDelete" value="Do you really want to delete the {0}."  category="Confirmation" description="description" />    
  6. 6 </messages>  
  7. 7   
  8. 8  

我想脱离CodeSimth工具,所以在建立了一个控制台程序,引用CodeSmith.Engine.dll程序集。

Code:

  1. 代码   
  2.  
  3.  1 static void Main(string[] args)   
  4.  2        {   
  5.  3           // Wolf.Message.Messages.Confirmation.ReallyDelete.Value   
  6.  4            // test();   
  7.  5            CodeTemplate template = CompileTemplate(@"E:\MyApp\LinqTest\ConsoleApplication1\MessageCodeGenerator.cst",s=>Console.WriteLine(s));   
  8.  6            if (template != null)   
  9.  7            {   
  10.  8                template.SetProperty("_MessageFilePath""");   
  11.  9                Wolf.MessageCodeGenerator gen = new MessageCodeGenerator();   
  12. 10                Dictionary<string, List<MessageEntry>> dict = gen.GeneratorCode(@"E:\MyApp\LinqTest\ConsoleApplication1\Sample.xml");   
  13. 11                template.SetProperty("Generator", dict);   
  14. 12                template.RenderToFile("gen.cs"true);   
  15. 13               // System.Diagnostics.Process.Start("gen.cs");   
  16. 14            }   
  17. 15           // Console.Read();   
  18. 16   
  19. 17        }  
  20. 18   
  21. 19        public static CodeTemplate CompileTemplate(string templateName,Action<string> errorWriter)   
  22. 20        {   
  23. 21            CodeTemplateCompiler compiler = new CodeTemplateCompiler(templateName);   
  24. 22            compiler.Compile();   
  25. 23   
  26. 24            if (compiler.Errors.Count == 0)   
  27. 25            {   
  28. 26                return compiler.CreateInstance();   
  29. 27            }   
  30. 28            else   
  31. 29            {   
  32. 30                for (int i = 0; i < compiler.Errors.Count; i++)   
  33. 31                {   
  34. 32                    errorWriter(compiler.Errors[i].ToString());   
  35. 33                }   
  36. 34                return null;   
  37. 35            }   
  38. 36   
  39. 37        }  
  40. 38   
  41. 39   
  42. 复制代码 

生成后的代码:

  1. 代码   
  2.  
  3.  1 //Copyright (C) Wolf.  All rights reserved.   
  4.  2 using Wolf;   
  5.  3 using System;   
  6.  4 using System.Collections.Generic;   
  7.  5 namespace Wolf.Message   
  8.  6 {   
  9.  7     public class Messages   
  10.  8     {   
  11.  9         public class Validation   
  12. 10         {   
  13. 11   
  14. 12             /// <summary>   
  15. 13             ///description   
  16. 14             /// </summary>   
  17. 15             public static Wolf.MessageEntry MandatoryField = new MessageEntry("MandatoryField",   
  18. 16   
  19. 17 "The {0} is mandatory.""The {0} is mandatory.");   
  20. 18   
  21. 19             /// <summary>   
  22. 20             ///description   
  23. 21             /// </summary>   
  24. 22             public static Wolf.MessageEntry GreaterThan = new MessageEntry("GreaterThan",   
  25. 23   
  26. 24 "The {0} must be greater than {1}.""The {0} must be greater than {1}.");   
  27. 25   
  28. 26         }   
  29. 27   
  30. 28         public class Confirmation   
  31. 29         {   
  32. 30   
  33. 31             /// <summary>   
  34. 32             ///description   
  35. 33             /// </summary>   
  36. 34             public static Wolf.MessageEntry ReallyDelete = new MessageEntry("ReallyDelete",   
  37. 35   
  38. 36 "Do you really want to delete the {0}.""Do you really want to delete the {0}.");   
  39. 37   
  40. 38         }   
  41. 39   
  42. 40     }   
  43. 41 }  
  44. 42   
  45. 43   
  46. 复制代码 

ok,全部完成。同时你也可以完全集成与VS中利用VSX Vs扩展,可以参考明年我18 的VSX系列