This project is read-only.

Question about relative paths... using a config file

Apr 3, 2009 at 4:53 PM
Hi all,

I'm trying to sort out how to generate some sql based on a config file that I have been given to parse.  I wanted to put the config file in my project and then have the template generate the sql, but the template is not executing relative to my project directory.  Any clues or hints?  What am I missing?

<#@ template language="C#" debug="True" #>
<#@ output extension=".sql" #>
<#@ include file="T4Toolbox.tt" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Collections.ObjectModel" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#
    MyTemplate template = new MyTemplate();
    template.Render();
#>
<#+
public class MyTemplate : Template
{
private readonly Regex _inputRegex = new Regex(
@"^(?<table>ref_\w+),(?<column>\w+)\s+$",
RegexOptions.Multiline | RegexOptions.Compiled | RegexOptions.IgnoreCase);
   
private Dictionary<string, Collection<string>> _tables;

public void ParseInputFile(string file)
{
// Open input file
using (StreamReader streamReader = File.OpenText(file))
{
string text = streamReader.ReadToEnd();
MatchCollection matches = _inputRegex.Matches(text);

if (matches.Count > 0)
{
_tables = new Dictionary<string, Collection<string>>();

foreach (Match match in matches)
{
string table = match.Groups["table"].Value;

if (!_tables.ContainsKey(table))
{
Collection<string> columns = new Collection<string>();
Console.WriteLine(@"Table: {0}", table);
_tables.Add(table, columns);
columns.Add(match.Groups["column"].Value);
}
else
{
_tables[table].Add(match.Groups["column"].Value);
}
}
}
}
}

protected override void RenderCore()
{
ParseInputFile(@"InputFile.txt");

PushIndent("\t");
/*
foreach (Column column in table.Columns)
{
WriteLine("@" + column.Name + " " + column.DataType.Name);
}
*/
PopIndent();
}
}
#>
Apr 3, 2009 at 5:56 PM
You need to use the following code to convert relative file path to an absolute path before accessing the file:

string absolutePath = TransformationContext.Host.ResolvePath(relativePath);
Apr 3, 2009 at 6:31 PM
Just curious... is there also a way to use a type created within the same project.

For example, I want my template to use some type that I'm creating elsewhere in the project.

Thanks,
Fred
Apr 3, 2009 at 7:45 PM
Yes, here is an example: http://www.olegsych.com/2008/07/t4-template-for-generating-sql-view-from-csharp-enumeration/. If you can't use CodeModel, you can use Introspection: http://www.olegsych.com/2007/12/how-to-use-t4-to-generate-decorator-classes/. Reflection will work, but will make T4 lock the compiled files.
Apr 3, 2009 at 8:15 PM
Thanks for all your help