一般这些Code Wizards在生成源代码时都是通过设置模板文件,然后根据这些模板文件生成源代码。有很多Code Wizards只能生成固定的语言(如java、C#等)。虽然有一些Code Wizards可以生成多种语言,但也只是固定的几种。而且生成源代码部分都是显示地固定在程序中。这样非常不易扩展。如CodeSmith系统,这是一个非常不错的Code Wizard。它使用一个扩展名为cst的文件来设置模板。这个模板文件的格式类似于Asp.net。如果想生成C#源代码,必须要在其中显示地标明,并且模板的固定部分要使用C#语言编写。如果这样的话,同样功能要生成不同语言的代码,如C#和VB.net。就要编写两个模板文件。这是非常不方便的。
从以上的描述来看, Code Wizard所面临的一个重要问题就是如何使用一个模版文件来生成不同语言的源代码。幸好Microsoft提供了一种解决方案,这就是CodeDOM技术。CodeDOM的全称是代码文档对象模型(Code Document Object Model)。整个CodeDOM就是一张对象图(object graph)。它用这张图中的所有对象描述了面向对象语言中的几乎所有的语法现象,如类、接口、方法、属性等。CodeDOM通过对象模型对语言进行了抽象,然后利用具体语言所提供的生成源代码的机制来生成源代码,并可调用相应的编译器将源码生成*.dll或*.exe。从而可以达到与语言无关的目的。图1描述了使用CodeDOM生成和编译源代码的过程。

<item id = "01 " name = "Bill "/>
<item id = "02" name = "Mike" />
</MyTable>
<id type = "System.Int32"/>
<name type = "System.String"/>
</MyTable>
三、CodeDOM的结构
private CodeNamespace m_CodeNameSpace;
private CodeTypeDeclaration m_Class;
private void InitCodeDom()
{
m_CodeCompileUnit = new CodeCompileUnit();
m_CodeNameSpace = new CodeNamespace("xml.tables");
m_CodeCompileUnit.Namespaces.Add(m_CodeNameSpace);
m_Class = new CodeTypeDeclaration(m_ClassName);
m_CodeNameSpace.Types.Add(m_Class);
}
{
// 产生 "private XmlDocument m_xml = new XmlDocument();"
CodeMemberField xml = new CodeMemberField("System.Xml.XmlDocument", "m_xml");
CodeObjectCreateExpression createxml = new CodeObjectCreateExpression("System.Xml.XmlDocument");
xml.InitExpression = createxml;
m_Class.Members.Add(xml);
// 产生 "private String m_XmlFile;"
CodeMemberField xmlfile = new CodeMemberField("System.String", "m_XmlFile");
m_Class.Members.Add(xmlfile);
// 根据模板文件产生保存字段值的变量
String fieldname = "", fieldtype = "";
foreach (XmlNode xn in m_Xml.DocumentElement.ChildNodes)
{
fieldname = "m_" + ;
fieldtype = xn.Attributes["type"].Value;
CodeMemberField field = new CodeMemberField(fieldtype, fieldname);
m_Class.Members.Add(field);
}
// 产生 "private bool m_AddFlag;"
CodeMemberField addflag = new CodeMemberField("System.Boolean", "m_AddFlag");
m_Class.Members.Add(addflag);
}
using System.CodeDom.Compiler;
{
String fieldname = "", fieldtype = "";
foreach (XmlNode xn in m_Xml.DocumentElement.ChildNodes)
{
fieldname = ;
fieldtype = xn.Attributes["type"].Value;
CodeMemberProperty property = new CodeMemberProperty();
property.Attributes = MemberAttributes.Public | MemberAttributes.Final;
= fieldname;
property.Type = new CodeTypeReference(fieldtype);
property.HasGet = true;
property.HasSet = true;
CodeVariableReferenceExpression field = new CodeVariableReferenceExpression("m_" + fieldname);
// 产生 return m_property
CodeMethodReturnStatement propertyReturn = new CodeMethodReturnStatement(field);
property.GetStatements.Add(propertyReturn);
// 产生 m_property = value;
CodeAssignStatement propertyAssignment = new CodeAssignStatement(field,
new CodePropertySetValueReferenceExpression());
property.SetStatements.Add(propertyAssignment);
m_Class.Members.Add(property);
}
}
private CodeVariableReferenceExpression m_XmlExpression;
private CodeVariableReferenceExpression m_AddFlagExpression;
private void InitVariants()
{
m_XmlFileExpression = new CodeVariableReferenceExpression("m_XmlFile");
m_XmlExpression = new CodeVariableReferenceExpression("m_xml");
m_AddFlagExpression = new CodeVariableReferenceExpression("m_AddFlag");
}
{
// 定义构造函数
CodeConstructor constructor = new CodeConstructor();
constructor.Parameters.Add(new CodeParameterDeclarationExpression("System.String", "xmlFile"));
constructor.Attributes = MemberAttributes.Public;
// 产生 "m_XmlFile = xmlFile;"
CodeAssignStatement assignXmlFile = new CodeAssignStatement(m_XmlFileExpression,
new CodeVariableReferenceExpression("xmlFile"));
// 产生 "m_xml.LoadXml("…");"
CodeMethodInvokeExpression invokeLoadXml = new CodeMethodInvokeExpression(m_XmlExpression, "LoadXml",
new CodePrimitiveExpression("<?xml version=\"1.0\" encoding=\"gb2312\" ?><" + m_Xml.
+ "></" + m_Xml. + ">"));
// 产生 "m_xml.Save(m_XmlFile);"
CodeMethodInvokeExpression invokeSave = new CodeMethodInvokeExpression(m_XmlExpression, "Save",
m_XmlFileExpression);
CodeStatementCollection statements = new CodeStatementCollection();
statements.Add(invokeLoadXml);
statements.Add(invokeSave);
// 产生if语句: "if (System.IO.File.Exists(m_XmlFile))
else
"CodeConditionStatement ifStatement = new CodeConditionStatement(new CodeMethodInvokeExpression(
new CodeVariableReferenceExpression("System.IO.File"), "Exists", m_XmlFileExpression), new CodeStatement[] { } ,
new CodeStatement[] { statements[0], statements[1] });
// 产生 "m_xml.Load(m_XmlFile);"
CodeMethodInvokeExpression invokeLoad = new CodeMethodInvokeExpression(m_XmlExpression, "Load",
m_XmlFileExpression);
// 产生 "m_AddFlag = false;"
CodeAssignStatement assignAddFalse = new CodeAssignStatement(m_AddFlagExpression,
new CodePrimitiveExpression(false));
constructor.Statements.Add(assignXmlFile);
constructor.Statements.Add(ifStatement);
constructor.Statements.Add(invokeLoad);
constructor.Statements.Add(assignAddFalse);
m_Class.Members.Add(constructor);
}
{
CodeTypeReference voidReference = new CodeTypeReference("System.void");
//产生Add方法
CodeMemberMethod add = new CodeMemberMethod();
add.ReturnType = voidReference;
= "add";
add.Attributes = MemberAttributes.Public | MemberAttributes.Final;
CodeAssignStatement assignAddTrue = new CodeAssignStatement(m_AddFlagExpression,
new CodePrimitiveExpression(true));
add.Statements.Add(assignAddTrue);
m_Class.Members.Add(add);
//产生Save方法
CodeMemberMethod save = new CodeMemberMethod();
save.ReturnType = voidReference;
= "save";
save.Attributes = MemberAttributes.Public | MemberAttributes.Final;
System.Collections.Generic.List<CodeStatement> ifStatements =
new System.Collections.Generic.List<CodeStatement>();
//产生 "XmlNode xn = m_xml.CreateNode(XmlNodeType.Element, "item", "");"
CodeVariableDeclarationStatement xmlNode = new CodeVariableDeclarationStatement("System.Xml.XmlNode", "xn");
CodeMethodInvokeExpression createNode = new CodeMethodInvokeExpression(m_XmlExpression, "CreateNode",
new CodeExpression[] {new CodeVariableReferenceExpression("System.Xml.XmlNodeType.Element"),
new CodePrimitiveExpression("item"),
new CodePrimitiveExpression("") });
xmlNode.InitExpression = createNode;
ifStatements.Add(xmlNode);
//产生 "XmlAttribute xa = null; "
CodeVariableDeclarationStatement xmlAttr = new CodeVariableDeclarationStatement("System.Xml.XmlAttribute", "xa");
xmlAttr.InitExpression = new CodePrimitiveExpression(null);
ifStatements.Add(xmlAttr);
//产生字段属性
CodeStatementCollection statements = new CodeStatementCollection();
foreach (XmlNode xn in m_Xml.DocumentElement.ChildNodes)
{
CodeMethodInvokeExpression createAttribute = new CodeMethodInvokeExpression(m_XmlExpression,
"CreateAttribute", new CodePrimitiveExpression());
CodeAssignStatement assignxa = new CodeAssignStatement(
new CodeVariableReferenceExpression("xa"), createAttribute);
CodeMethodInvokeExpression invokeToString = new CodeMethodInvokeExpression(
new CodeVariableReferenceExpression("m_" + ), "ToString");
CodeAssignStatement assignValue = new CodeAssignStatement(
new CodeVariableReferenceExpression("xa.Value"), invokeToString);
CodeMethodInvokeExpression invokeAppend = new CodeMethodInvokeExpression(
new CodeVariableReferenceExpression("xn.Attributes"),
"Append", new CodeVariableReferenceExpression("xa"));
statements.Add(invokeAppend);
ifStatements.Add(assignxa);
ifStatements.Add(assignValue);
ifStatements.Add(statements[0]);
}
// 产生 "m_xml.DocumentElement.AppendChild(xn);"
CodeMethodInvokeExpression invokeAppendChild = new CodeMethodInvokeExpression(new
CodeVariableReferenceExpression("m_xml.DocumentElement"), "AppendChild",
new CodeVariableReferenceExpression("xn"));
statements.Clear();
statements.Add(invokeAppendChild);
ifStatements.Add(statements[0]);
// 产生 "m_xml.Save(m_XmlFile);"
CodeMethodInvokeExpression invokeSave = new CodeMethodInvokeExpression(m_XmlExpression,
"Save", m_XmlFileExpression);
statements.Clear();
statements.Add(invokeSave);
ifStatements.Add(statements[0]);
// 产生 "m_AddFlag = false;"
CodeAssignStatement assignAddFalse = new CodeAssignStatement(m_AddFlagExpression,
new CodePrimitiveExpression(false));
ifStatements.Add(assignAddFalse);
// 产生if语句: "if (m_AddFlag)"
CodeConditionStatement ifStatement = new CodeConditionStatement(m_AddFlagExpression,
ifStatements.ToArray());
save.Statements.Add(ifStatement);
m_Class.Members.Add(save);
}
public void SaveCSharp(String filename)
{
IndentedTextWriter tw = new IndentedTextWriter(new StreamWriter(filename, false), " ");
CodeDomProvider provide = new CSharpCodeProvider();
provide.GenerateCodeFromCompileUnit(m_CodeCompileUnit, tw, new CodeGeneratorOptions());
tw.Close();
}
{
CompilerParameters cp = new CompilerParameters(new String[] { "System.Xml.dll" }, targetFile, false);
CodeDomProvider provider = new CSharpCodeProvider();
cp.GenerateExecutable = false;
// 调用编译器
CompilerResults cr = provider.CompileAssemblyFromFile(cp, sourcefile);
if (cr.Errors.Count > 0)
{
// 显示编译错误
foreach (CompilerError ce in cr.Errors)
System.Windows.Forms.MessageBox.Show(ce.ToString());
}
}
- 使用CodeDomProvider调用编译器时也需要传递相应的参数,如在本例中将System.Xml.dll
- 在调用编译器后,如果出现错误,可使用cr.Errors获得错误信息。
《银河系列原创教程》发布
















