This simple T4 example shows how to generate a C# enum class from an external resource, in this case a SQL database.
First of all, let’s create our database:
USE [master]
GO
CREATE DATABASE [T4Demo]
GO
USE [T4Demo]
GO
CREATE TABLE [dbo].[AssetClass](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Description] [varchar](50) NOT NULL,
CONSTRAINT [PK_AssetType] PRIMARY KEY CLUSTERED ( [Id] ASC )
)
GO
INSERT [AssetClass] VALUES ('Equity');
INSERT [AssetClass] VALUES ('Fixed Income');
INSERT [AssetClass] VALUES ('Cash');
GO
Next we’ll create a C# console application and add a T4 text template file:
<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Data" #>
<#@ import namespace="System.Data.SqlClient" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#@ import namespace="System.IO" #>
public enum <#= Path.GetFileNameWithoutExtension(Host.TemplateFile) #>
{
<#
if(Validate())
{
BuildEnum();
}
#>
}
<#+
private bool Validate()
{
if(string.IsNullOrEmpty(Server)) { Error("No server was specified"); }
if(string.IsNullOrEmpty(Database)) { Error("No database was specified"); }
if(!IntegratedSecurity)
{
if(string.IsNullOrEmpty(User)) { Error("No user id was specified"); }
if(string.IsNullOrEmpty(Pwd)) { Error("No password was specified"); }
}
if(string.IsNullOrEmpty(Table)) { Error("No table was specified"); }
if(string.IsNullOrEmpty(ValueColumn)) { Error("The value column was specified"); }
if(string.IsNullOrEmpty(TextColumn)) { Error("The text column was specified"); }
return !this.Errors.HasErrors;
}
private void BuildEnum()
{
using (SqlConnection conn = new SqlConnection(BuildConnStr()))
{
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = string.Format(
"select {0}, {1} from {2}",
ValueColumn,
TextColumn,
Table);
cmd.CommandType = System.Data.CommandType.Text;
conn.Open();
SqlDataReader rdr = cmd.ExecuteReader();
PushIndent("\t");
while (rdr.Read())
{
string enm = string.Format("{0} = {1},",
CreateValidIdentifier(rdr[TextColumn].ToString()),
rdr[ValueColumn].ToString());
WriteLine(enm);
}
WriteLine("Unknown = 0");
PopIndent();
rdr.Close();
conn.Close();
}
}
// Strips spaces and full stops
private string CreateValidIdentifier(string input)
{
string pattern = @"[\.\[\]\s]";
Regex regex = new Regex(pattern, RegexOptions.None);
return regex.Replace(input, "");
}
private string BuildConnStr()
{
SqlConnectionStringBuilder csb = new SqlConnectionStringBuilder();
csb.DataSource = Server;
csb.InitialCatalog = Database;
csb.IntegratedSecurity = IntegratedSecurity;
if(!IntegratedSecurity)
{
csb.UserID = User;
csb.Password = Pwd;
}
return csb.ConnectionString;
}
private string Server = ".";
private string Database = "T4Demo";
private bool IntegratedSecurity = true;
private string User = "";
private string Pwd = "";
private string Table = "dbo.AssetClass";
private string ValueColumn = "Id";
private string TextColumn = "Description";
#>
Now save the file and you'll have your own up-to-date enum class driven from your database:
public enum AssetClass
{
Equity = 1,
FixedIncome = 2,
Cash = 3,
Unknown = 0
}
You can also set up Visual Studio to always regenerate the file on each build if you prefer.
Source code: http://stevenhollidge.com/blog-source-code/T4CodeGenerationEnums.zip
No comments:
Post a Comment