3

I'm trying to implement a method that will accept DataTable with StringTemplate and return string representation of data.

I found how to do this here and here, but it doesn't work for me.

Example code:

// Here can be any table with any number of columns.
var table = new DataTable();
table.Columns.Add("StrCol", typeof(string));
table.Columns.Add("IntCol", typeof(int));
table.Rows.Add(new object[] { "Row1String", 1 });
table.Rows.Add(new object[] { "Row2String", 2 });

var data = from dataRow in table.AsEnumerable()
           select dataRow;

var st = new StringTemplate("$items:{$it.StrCol$ $it.IntCol$}$");
st.SetAttribute("items", data);
Console.Write(st.ToString());

Result:

Class DataRow has no such attribute: StrCol in template context [anonymous anonymous]
Class DataRow has no such attribute: IntCol in template context [anonymous anonymous]
Class DataRow has no such attribute: StrCol in template context [anonymous anonymous]
Class DataRow has no such attribute: IntCol in template context [anonymous anonymous]

UPD:

I have to use Antlr3.StringTemplate.dll version 3.1.0 of StringTemplate. I decided to try on another version and downloaded Antlr3.StringTemplate.dll version 3.3.0. Everything works fine. So, is there any way to apply template on DataTable using old library?

Community
  • 1
  • 1
kyrylomyr
  • 12,192
  • 8
  • 52
  • 79

2 Answers2

1

The possible workaround to use string templates on DataTable is to convert rows to collection of dictionaries, so it will be possible to access rows cells by column names:

var columns = table.Columns.Cast<DataColumn>().Select(col => col.ColumnName);
var data = from DataRow row in table.Rows
           select columns.ToDictionary(col => col, col => row[col]);

var st = new StringTemplate("$items:{$it.StrCol$ $it.IntCol$\n}$");
st.SetAttribute("items", data);

With newer version of StringTemplate library that works with DataTable:

var st = new StringTemplate("$items:{$it.StrCol$ $it.IntCol$\n}$");
st.SetAttribute("items", table.Rows);
kyrylomyr
  • 12,192
  • 8
  • 52
  • 79
0

either shape your datarow:

select new { StrCol = dataRow["StrCol"], IntCol = dataRow["IntCol"] }

or adapt your StringTemplate (not sure if that works though)

var st = new StringTemplate("$items:{$it[0]$ $it[1]}$");   
rene
  • 41,474
  • 78
  • 114
  • 152
  • 1
    The issue that I can't hardcode anonymous type that way because my code should work with **any** `DataTable`. – kyrylomyr Jan 03 '12 at 14:44