Using T4 to automatically generate your entities

Today I discovered something very interesting, namely how to automatically generate my entity classes (classes that also implement the INotifyPropertyChanged and IDataErrorInfo interfaces) using T4.

T4 is a text generation language built into Visual Studio 2005 and later, normally intended for DSL code generation. But we can also use it for generating any code we would like. I for one, I would like automatic properties to automatically implement INotifyPropertyChanged if the interface is on the class, but of course, life doesn’t work that way *sigh*. The real problem is that for each property you have, part of the implementation needs to raise an event using the property name. When you change the name of the property you also have to change this string, which is error prone…

Instead we can generate code using T4, and to be honest, it isn’t that difficult to use. First of all, go to tangible to download their free T4 intelli-sense tool.

Next add to your project a new text file, naming it Entity.tt (the extension is important!). Now add this content:

<#@ template language="C#" #> <#@ output extension="cs" #> <#@ import namespace="System.Collections" #> <#@ import namespace="System.Collections.Generic" #> // --------------------------------- // U2U Sample, use at your own risk! //        http://www.u2u.be // ---------------------------------  using System; using System.ComponentModel; using System.Collections.Generic;  namespace <#= this.Namespace #>  {     public partial class <#= this.ClassName #>      : INotifyPropertyChanged     , IDataErrorInfo     {     #region Private fields     <# for (int idx = 0; idx < this.properties.GetLength(0); idx++) { #>         private <#= this.properties[idx,0] #> _<#= this.properties[idx,1].ToLower() #>;<# }#>             #endregion          #region Properties     <# for (int idx = 0; idx < this.properties.GetLength(0); idx++) { #>         public <#= this.properties[idx,0] #> <#= this.properties[idx,1] #>     {               get       {                     return _<#= this.properties[idx,1].ToLower() #>;               }               set               {                     _<#= this.properties[idx,1].ToLower() #> = value;         OnPropertyChanged("<#= this.properties[idx,1]#>");               }        }     <#   }   #>           #endregion          #region INotifyPropertyChanged Members             public event PropertyChangedEventHandler PropertyChanged;          protected virtual void OnPropertyChanged(string propertyName)        {              if (PropertyChanged != null)                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));        }             #endregion          #region IDataErrorInfo Members          private string _error = null;          public string Error {       get       {          return _error;        }       set        {         _error = value;       }     }          private Dictionary<string,string> _columnErrors =       new Dictionary<string,string>();            public string this[string columnName]     {       get       {         if( _columnErrors != null && _columnErrors.ContainsKey(columnName))           return _columnErrors[columnName];         else           return null;       }       set       {         if( value != null ) // Insert error         {           if( _columnErrors == null )           {             _columnErrors = new Dictionary<string,string>();           }           _columnErrors[columnName] = value;         }         else // Clear error         {           _columnErrors.Remove(columnName);           if (_columnErrors.Count == 0)           {             _columnErrors = null;           }         }         // Notify validation that something has changed         OnPropertyChanged( columnName );       }     }     #endregion   } }  <#+       string Namespace = "Demo";       string ClassName = "DemoClass";       string[,] properties = {             {"int", "Property1"},             {"string", "Property2"}   };                #>

Building your project will generate a little DemoClass with these two properties. But that is of course not what you want; so add another file Category.tt:

<#       this.Namespace = "U2U.Samples";       this.ClassName = "Category";       this.properties = new string[,]   {             {"int"   , "CategoryID"}   , {"string", "CategoryName"}         , {"string", "Description"}         , {"byte[]", "Picture"}   };  #>  <#@ include file="Entity.tt" #>  

Building will now automatically generate a Category.cs file with code like this:

// --------------------------------- // U2U Sample, use at your own risk! //        http://www.u2u.be // ---------------------------------  using System; using System.ComponentModel; using System.Collections.Generic;  namespace U2U.Samples {   public partial class Category     : INotifyPropertyChanged     , IDataErrorInfo   {     #region Private fields      private int _categoryid;     private string _categoryname;     private string _description;     private byte[] _picture;      #endregion      #region Properties      public int CategoryID     {       get       {         return _categoryid;       }       set       {         _categoryid = value;         OnPropertyChanged("CategoryID");       }     }      public string CategoryName     {       get       {         return _categoryname;       }       set       {         _categoryname = value;         OnPropertyChanged("CategoryName");       }     }      public string Description     {       get       {         return _description;       }       set       {         _description = value;         OnPropertyChanged("Description");       }     }      public byte[] Picture     {       get       {         return _picture;       }       set       {         _picture = value;         OnPropertyChanged("Picture");       }     }      #endregion      #region INotifyPropertyChanged Members      public event PropertyChangedEventHandler PropertyChanged;      protected virtual void OnPropertyChanged(string propertyName)     {       if (PropertyChanged != null)         PropertyChanged(this, new PropertyChangedEventArgs(propertyName));     }      #endregion      #region IDataErrorInfo Members      private string _error = null;      public string Error     {       get       {         return _error;       }       set       {         _error = value;       }     }      private Dictionary<string, string> _columnErrors =       new Dictionary<string, string>();      public string this[string columnName]     {       get       {         if (_columnErrors != null && _columnErrors.ContainsKey(columnName))           return _columnErrors[columnName];         else           return null;       }       set       {         if (value != null) // Insert error         {           if (_columnErrors == null)           {             _columnErrors = new Dictionary<string, string>();           }           _columnErrors[columnName] = value;         }         else // Clear error         {           _columnErrors.Remove(columnName);           if (_columnErrors.Count == 0)           {             _columnErrors = null;           }         }         // Notify validation that something has changed         OnPropertyChanged(columnName);       }     }     #endregion   } }  So to change/add/remove a property, we edit the Category.tt file and all the rest is done automatically.  Now for some feedback, what is your way of implementing IDataErrorInfo?

December 7. 2011 01:14 PM

ugg boots outlet

Is indeed a good idea, and I very much agree with what you think! Great features:Irrespective of trademark conflicts<p>(
<em><a title="ugg boots outlet" href="http://www.uggbootsshoes-outlets.com/">ugg boots outlet</a></em>
<em><a title="ugg boots" href="http://www.uggbootsshoes-outlets.com/">ugg boots</a></em>
<em><a title="cheap ugg boots" href="www.uggbootsshoes-outlets.com/">cheap ugg boots</a></em>

<em><a title="ugg boots outlet" href="http://www.uggboots-outletonline.net/">ugg boots outlet</a></em>) the Deckers Outdoors Corporation has established the UGG Australia Boot a loved ones title., and UGG? Australia was obtained by Deckers Outside Corporation (<em><a title="discount ugg boots" href="www.discount-uggboots-outlet.com/">discount ugg boots</a></em>
<em><a title="discount ugg boots" href="www.discount-uggbootsclearance.org/">discount ugg boots</a></em>
).UGG Australia is usually a brand name title for fashionable. discount ugg bootsugg boots<p><em><a title="ugg boots sale" href="http://www.uggbootsshoes-outlets.com/">ugg boots sale</a></em><p>
<em><a title="cheap ugg boots" href="http://www.cheapuggsboots-uk.org/">cheap ugg boots</a></em><p>
<em><a title="ugg boots" href="http://www.cheapuggsboots-uk.org/">ugg boots</a></em><p>
<em><a title="ugg boots outlet" href="http://www.cheapuggsboots-uk.org/">ugg boots outlet</a></em>


ugg boots outlet

Add comment

  Country flag

biuquote
  • Comment
  • Preview
Loading

Download the U2U brochure

Download Brochure

Receive the U2U Newsletter. Submit your email address:
 
 


 


Search

rss  RSS

Recent posts

None

Archive