Most developers that have used Entity Framework will surely have noticed some special files in the project that end in ".tt". These files serve as blueprints for the code that is generated from the Entity Framework mappings which are stored in an xml file ending in ".edmx".
A ".tt" template is similar to the ".cshtml" files used in Asp .Net MVC but instead of rendering html content it renders C# code. By editing these files we can customize how the generated code will look and behave.
For example the partial ".tt" template bellow for each column in a table in the database it generates a property that implements the INotifyPropertyChanged interface to notify subscribers that the object has changed:
This is applied for each column in every table. Using this code we can bind our objects directly to a Windows Presentation Foundation interface after fetching them from the database.
We can also generated backing fields for that property using the following template bellow:
The generated properties along with the generated fields and class will look like this:
You can mix C# code which will get executed in a template with declarative content that will appear as it is in the generated C# code:
The C# code that is executed when the template is evaluated has to be encompassed in special "<#" and "#>" markings. This C# code is separate from the generated C# code and is actually used to output C# code.
If the code returns a simple string value we can use "<#=" to include the string value directly in the generated C# code. Other text that is not encompassed in the special markings mentioned above will appear as it is.
Loops can be used to generate code multiple times. You can have declarative code inside an actual foreach loop in C# code. The declarative code will get multiplied for each element. Bellow you can see an example but it looks a bit confusing at first:
Additionally you can generate multiple files for each table. You can for example generate an abstract data access layer with interfaces that include CRUD methods. So for each table you will have some kind of repository interface like "ITableRepository". And then for these interfaces you can generate actual classes which implement them and return data from the database.
There are probably other ways you can use these templates. Also a downside is that Visual Studio by default does not include syntax highlighting support and actually proper IDE support for editing them.
A ".tt" template is similar to the ".cshtml" files used in Asp .Net MVC but instead of rendering html content it renders C# code. By editing these files we can customize how the generated code will look and behave.
For example the partial ".tt" template bellow for each column in a table in the database it generates a property that implements the INotifyPropertyChanged interface to notify subscribers that the object has changed:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public string Property(EdmProperty edmProperty) | |
{ | |
return string.Format( | |
CultureInfo.InvariantCulture, | |
"{0} {1} {2} {{ {3}get {{ return _{5}; }} {4}set {{ _{5} = value; OnPropertyChanged(); }} }}", | |
Accessibility.ForProperty(edmProperty), | |
_typeMapper.GetTypeName(edmProperty.TypeUsage), | |
_code.Escape(edmProperty), | |
_code.SpaceAfter(Accessibility.ForGetter(edmProperty)), | |
_code.SpaceAfter(Accessibility.ForSetter(edmProperty)), | |
_code.Escape(edmProperty).ToLower()); | |
} |
We can also generated backing fields for that property using the following template bellow:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public string BackingField(EdmProperty edmProperty) | |
{ | |
return string.Format( | |
CultureInfo.InvariantCulture, | |
"{0} {1} _{2};", | |
"private", | |
_typeMapper.GetTypeName(edmProperty.TypeUsage), | |
_code.Escape(edmProperty).ToLower()); | |
} | |
The generated properties along with the generated fields and class will look like this:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public partial class Calibru : INotifyPropertyChanged | |
{ | |
public event PropertyChangedEventHandler PropertyChanged; | |
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) | |
{ | |
var handler = PropertyChanged; | |
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); | |
} | |
private int _id; | |
public int Id { get { return _id; } set { _id = value; OnPropertyChanged(); } } | |
private int _reperid; | |
public int ReperId { get { return _reperid; } set { _reperid = value; OnPropertyChanged(); } } | |
private string _nume; | |
public string Nume { get { return _nume; } set { _nume = value; OnPropertyChanged(); } } | |
private string _valoare; | |
public string Valoare { get { return _valoare; } set { _valoare = value; OnPropertyChanged(); } } | |
public virtual Reper Repere { get; set; } | |
} |
You can mix C# code which will get executed in a template with declarative content that will appear as it is in the generated C# code:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<#=codeStringGenerator.UsingDirectives(inHeader: false)#> | |
<#=codeStringGenerator.EntityClassOpening(entity)#> | |
{ | |
public event PropertyChangedEventHandler PropertyChanged; | |
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) | |
{ | |
var handler = PropertyChanged; | |
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); | |
} | |
<# |
The C# code that is executed when the template is evaluated has to be encompassed in special "<#" and "#>" markings. This C# code is separate from the generated C# code and is actually used to output C# code.
If the code returns a simple string value we can use "<#=" to include the string value directly in the generated C# code. Other text that is not encompassed in the special markings mentioned above will appear as it is.
Loops can be used to generate code multiple times. You can have declarative code inside an actual foreach loop in C# code. The declarative code will get multiplied for each element. Bellow you can see an example but it looks a bit confusing at first:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public <#=code.Escape(complex)#>() | |
{ | |
<# | |
foreach (var edmProperty in propertiesWithDefaultValues) | |
{ | |
#> | |
this.<#=code.Escape(edmProperty)#> = <#=typeMapper.CreateLiteral(edmProperty.DefaultValue)#>; | |
<# | |
} | |
foreach (var complexProperty in complexProperties) | |
{ | |
#> | |
this.<#=code.Escape(complexProperty)#> = new <#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>(); | |
<# | |
} | |
#> | |
} |
Additionally you can generate multiple files for each table. You can for example generate an abstract data access layer with interfaces that include CRUD methods. So for each table you will have some kind of repository interface like "ITableRepository". And then for these interfaces you can generate actual classes which implement them and return data from the database.
There are probably other ways you can use these templates. Also a downside is that Visual Studio by default does not include syntax highlighting support and actually proper IDE support for editing them.
Comments
Post a Comment