Jeff Sheldon

Mostly.NET
posts - 15, comments - 1, trackbacks - 0

More T4 Template Happiness!

So this is another post about T4 templates.   But not just ANY T4 templates, Preprocessed Text Template’s (oooooh, ahhhhh)

Long story short, these are templates you can embed in an application to execute at runtime rather than at design time.  There are some limitations compared to regular T4 templates, but needless to say, it sure makes generating code a breeze.

Back Story

I have this project I needed to work on that involved generating code from an Xsd.   This Xsd changed often, so I created a project that did it for me because I’m lazy.  So here’s how I did it.

1.  Created a Console Application that took some parameters, namely, the string value for the namespace, the file location for the output dll, and the file location of the input Xsd file.

2.  Inside of the project that used this file, I added a pre-build event that executed the generation of the dll.

3.  Profit!

So here’s a little bit on how I went about the code generating console application.

First off, I do a lot of Xml manipulation, parsing, etc at work.  But, like I said before, I’m lazy.  I prefer to do my Xml work in C#.  So in order to process an Xsd I (in my opinion) cheated.  I created a set of classes that allow me to simply deserialize the xsd into a class.

image

 

Notice XsdBase, there’s not much to this, it’s just a base class created to handle Xsd element types that have annotations, maxOccurs, and minOccurs.  It’s mostly there for extension method purposes.

Now with this in place, I can take the Xsd path, and simply deserialize it to the XsdSchema class.  yay!

   1: public static XsdSchema Parse(string filePath)
   2: {
   3:     var document = XDocument.Load(filePath);
   4:     var schema = Parse<XsdSchema>(document.Root);
   5:     schema.SetParent(null, null);
   6:     return schema;
   7: }
   8:  
   9: public static T Parse<T>(XElement element)
  10: {
  11:     using (var sr = new StringReader(element.ToString()))
  12:     {
  13:         using (var r = new XmlTextReader(sr))
  14:         {
  15:             var s = new XmlSerializer(typeof (T), "http://www.w3.org/2001/XMLSchema");
  16:             s.UnreferencedObject += (sender, e) => Console.WriteLine("Unreferenced Object: {0}", e.UnreferencedId);
  17:             s.UnknownElement += (sender, e) => Console.WriteLine("Encountered an unknown element on line {0}: {1}", e.LineNumber, e.Element.LocalName);
  18:             s.UnknownAttribute += (sender, e) => Console.WriteLine("Encountered an unknown attribute on line {0}: {1}.{2}", e.LineNumber, e.ObjectBeingDeserialized.GetType().Name, e.Attr.LocalName);
  19:             s.UnknownNode += (sender, e) => Console.WriteLine("Encountered an unknown node on line {0}: {1}", e.LineNumber, e.LocalName);
  20:             return (T) s.Deserialize(r);
  21:         }
  22:     }
  23: }

 

So now I have some T4 template, and some classes I can use with it, Now what?

Well, I start off by adding two parameters to the top of my T4 template for passing in some information. 

   1: <#@ parameter name="FilePath" type="System.String" #>
   2: <#@ parameter name="Namespace" type="System.String" #>

 

And I use them like so:

   1: var xsdSchema = XsdSchema.Parse(Session["FilePath"].ToString());
   2: var ns = Session["Namespace"].ToString();
 

Now my T4 template has access to those files, and it can do it’s thing.   But wait, how do I pass that into the T4 template in the first place?
Well I did it like this!
   1: var codeGen = new ClassGenerator
   2:             {
   3:                 Session = new Dictionary<string, object>
   4:                                                 {
   5:                                                     {"FilePath", xsdPath},
   6:                                                     {"Namespace", ns}
   7:                                                 }
   8:             };
   9:  
  10:  
  11:             var code = codeGen.TransformText();

 

 

And now the code variable has all my generated code in it.  Neat!
So that’s pretty much it.  I’ve attached the project for you so you can see the in’s and out’s.  Keep in mind though, it’s not quite production ready.  Overall it was written in a bit of a hurry, so I think there are some unused methods and cheesy code hacks in there.

Also, it won’t necessarily work for ANY xsd.  I tried to make it someone generic, but you might need to modify it some to work with your specific Xsd (I did).

Hrm, I think that’s all of the disclaimers I need.

Attachments:  GenerateFromXsd.IV.zip

Print | posted on Sunday, September 05, 2010 1:18 PM | Filed Under [ t4 Xsd code-generation ]

Feedback

Gravatar

# re: More T4 Template Happiness!

Very cool. This looks like just what I needed. Good work man!
6/8/2011 10:52 AM | Darrel Carver

Post Comment

Title  
Name  
Email
Url
Comment   
Please add 4 and 7 and type the answer here:

Powered by:
Powered By Subtext Powered By ASP.NET