Code generation tools are already standard equipment for the
developers these days.
The main motivation to use code generation techniques is that
most of theprojects share similar development tasks. It is
possibleto automate the execution these tasks by using special
tools -code generators.
The sample proposed here demonstrates some .NET features
for language independent code generation. The sample its self
should not be considered as a complete code generator
architecture.The development scenario, automated in this
sample is whenthe developer have a sample xml file, which
should be deserializedas a native .NET class , processed
somehow and serialized back to xml content.
The sample implements a class called XmlCodeGenerator,
which generates C# source files from given Xml file.Each
generated source file contains a C# class for each unique xml
element contained in the xml file. It automatically recognize if
the xml element should be mapped to as class or class member.
Due to the missing information about the actual data types all
xml elements mapped to simlpe class members are implemented
as System.String. Generated classes may be compiled and used
with System.Xml.Serialization.XmlSerializer class
If we have the following xml file:
<?xml version="1.0" encoding="utf-8" ?> <employeeList> <employee memberOf="Managers"> <names>Peter</names> <birthDate>1.1.1967</birthDate> <contact> <town>Sofia</town> <address>1000 Mladost</address> <phone>0887435234</phone> </contact> </employee> </employeeList>
|
XmlCodeGenerator will map the xml content to 3 classes in the
following way:
Xml element | .NET class |
employeeList | EmployeeList |
employee | Employee |
contact | Contact |
The rest of the elements and attributes within the xml content
will be mapped as class members
This core functionality is wrapped around the
System.CodeDomname space. In general
it contains classes that can be used to represent the elements and structure of a source code document.In order to create a .NET class declaration for the root xml element
"employeeList" we will have the following code:
uses Microsoft.CSharp; uses System.CodeDom; uses System.CodeDom.Compiler; CodeTypeDeclaration classDeclaration = new CodeTypeDeclaration("EmployeeList"); classDeclaration.IsClass = true; //make it public constructor.Attributes= MemberAttributes.Public; //add constructor CodeConstructor constructor = new CodeConstructor(); classDeclaration.Members.Add(constructor); //add class level XmlRoot attribute classDeclaration.CustomAttributes.Add(new CodeAttributeDeclaration("System.Xml.Serialization.XmlRoot",new CodeAttributeArgument(new CodePrimitiveExpression("employeeList"))));
|
Next, we should add some class members. In our case
"employeeList" element has one sub-element named
"emlpoyee". It will appear as a class member called Employee
of type Employee. The following code may be used to create
this class member:
uses Microsoft.CSharp; uses System.CodeDom; uses System.CodeDom.Compiler; //create field CodeMemberField field = new CodeMemberField("Employee","m_employee"); //embed field into the class declaration classDeclaration.Members.Add(field) //create property CodeMemberProperty property = new CodeMemberProperty(); property.Name = "Employee"; property.Type = new CodeTypeReference("Employee"); property.Attributes = MemberAttributes.Public; //add XmlElement attribute for serialziation support property.CustomAttributes.Add(new CodeAttributeDeclaration("System.Xml.Serialization.XmlElement",new CodeAttributeArgument(new CodePrimitiveExpression("employee")))); property.HasGet = true; property.HasSet = true; property.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(),field.Name))); property.SetStatements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(),field.Name), new CodePropertySetValueReferenceExpression())); //embed property into the class declaration classDeclaration.Members.Add(property)
|
Having this class declaration we have to generate the C# code.
We may do it by using the following code:
uses Microsoft.CSharp; uses System.CodeDom; uses System.CodeDom.Compiler; //obtain C# code provider CSharpCodeProvider provider = new CSharpCodeProvider(); //get the proper code generator .ICodeGenerator generator = provider.CreateGenerator(); //create namespace to place our class declaration into CodeNamespace _namespace = new CodeNamespace(Namespace); _namespace.Types.Add((CodeTypeDeclaration)classDeclaration); //generate code CodeGeneratorOptions options = new CodeGeneratorOptions(); options.BlankLinesBetweenMembers = true; System.IO.StreamWriter sw = System.IO.File.CreateText("D:\\work\\employeeList.cs"); generator.GenerateCodeFromNamespace(_namespace,sw,options) sw.Close();
|
As you may see having this type of class declaration our code
generator is not limited to C# code generation only.
Let's wrap up these code snipsets...To be continued