一直想写一个Code生成系列,但写到CodeSimth,发觉在TerryLee 和努力学习的小熊 两位大牛的博客里讲很详尽,所以就像写些示例方面的,但是苦于没有想到写些什么。最近Artech写了两篇从数据到代码——通过代码生成机制实现强类型编程--上篇和下篇,大牛写得是CodeDom的,今天我就想借借大牛的示例写个CodeSimth版的,希望Artech不要怪我,呵呵。我的Code生成技术已经写了CodeDom的见CodeDom系列目录,欢迎各位园友指教。
好直接到主题。首先是数据实体MessageEntry(我到老A的基础上添加了description属性作为代码字段描述):
namespace Wolf
{
public class MessageEntry
{
public string Id { get; private set; }
public string Value { get; private set; }
public string Description { get; private set; }
public MessageEntry(string id, string value)
{
this.Id = id;
this.Value = value;
}
public MessageEntry(string id, string value, string description)
{
this.Id = id;
this.Value = value;
this.Description = description;
}
public string Format(params object[] args)
{
return string.Format(this.Value, args);
}
}
}
在我的机子上的COdeSimth是2..0版本的所以不能使用Linq命名空间,我又想利用这个空间,比较快捷,所以我就在先3.0转化为
Dictionary >实体再传入模板:
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace Wolf
{
public class MessageCodeGenerator
{
public Dictionary
> GeneratorCode(string path)
{
return GeneratorCode(XElement.Load(path));
}
public Dictionary
> GeneratorCode(XElement root)
{
var elemts = root.Elements("message").GroupBy(e => ((XAttribute)e.Attribute("category")).Value);
Dictionary
> dict = new Dictionary
>();
foreach (var item in elemts)
{
List
list = new List
();
foreach (var g in item)
{
if (g.Attribute("description") != null)
{
list.Add(new MessageEntry(((XAttribute)g.Attribute("id")).Value, ((XAttribute)g.Attribute("value")).Value, ((XAttribute)g.Attribute("description")).Value));
}
else
{
list.Add(new MessageEntry(((XAttribute)g.Attribute("id")).Value, ((XAttribute)g.Attribute("value")).Value));
}
}
dict.Add(item.Key.ToString(), list);
}
return dict;
}
}
}
这下几可开始写模板了,见下Code:
<%@ CodeTemplate Language="C#" TargetLanguage="Text" Src="" Inherits="" Debug="False" Description="Template description here." %>
<%@ Import NameSpace="System" %>
<%@ Import NameSpace="System.Xml" %>
<%@ Import NameSpace="System.Text" %>
<%@ Import NameSpace="System.Collections.Generic" %>
<%@ Import NameSpace="Wolf" %>
<%@ Assembly Name="Wolf" %>
//Copyright (C) Wolf. All rights reserved.
<%= GeneratorCode()%>
很简单,就不说了,如果有问题请留言,其中命名空间完全可以以属性方式传入。
XMl实体用的是老A的:
我想脱离CodeSimth工具,所以在建立了一个控制台程序,引用CodeSmith.Engine.dll程序集。
Code:
static void Main(string[] args)
{
// Wolf.Message.Messages.Confirmation.ReallyDelete.Value
// test();
CodeTemplate template = CompileTemplate(@"E:/MyApp/LinqTest/ConsoleApplication1/MessageCodeGenerator.cst",s=>Console.WriteLine(s));
if (template != null)
{
template.SetProperty("_MessageFilePath", "");
Wolf.MessageCodeGenerator gen = new MessageCodeGenerator();
Dictionary
> dict = gen.GeneratorCode(@"E:/MyApp/LinqTest/ConsoleApplication1/Sample.xml");
template.SetProperty("Generator", dict);
template.RenderToFile("gen.cs", true);
// System.Diagnostics.Process.Start("gen.cs");
}
// Console.Read();
}
public static CodeTemplate CompileTemplate(string templateName,Action
errorWriter)
{
CodeTemplateCompiler compiler = new CodeTemplateCompiler(templateName);
compiler.Compile();
if (compiler.Errors.Count == 0)
{
return compiler.CreateInstance();
}
else
{
for (int i = 0; i < compiler.Errors.Count; i++)
{
errorWriter(compiler.Errors[i].ToString());
}
return null;
}
}
生成后的代码:
//Copyright (C) Wolf. All rights reserved.
using Wolf;
using System;
using System.Collections.Generic;
namespace Wolf.Message
{
public class Messages
{
public class Validation
{
///
///description
///
public static Wolf.MessageEntry MandatoryField = new MessageEntry("MandatoryField",
"The {0} is mandatory.", "The {0} is mandatory.");
///
///description
///
public static Wolf.MessageEntry GreaterThan = new MessageEntry("GreaterThan",
"The {0} must be greater than {1}.", "The {0} must be greater than {1}.");
}
public class Confirmation
{
///
///description
///
public static Wolf.MessageEntry ReallyDelete = new MessageEntry("ReallyDelete",
"Do you really want to delete the {0}.", "Do you really want to delete the {0}.");
}
}
}
ok,全部完成。同时你也可以完全集成与VS中利用VSX Vs扩展,可以参考明年我18 的VSX系列