Based on the answer to my question on StackOverflow, I have ended up with the following code:
public class ColumnDataBuilder<T>
{
public abstract class MyListViewColumnData
{
public string Name { get; protected set; }
public int Width { get; protected set; }
public ColumnType Type { get; protected set; }
public delegate TOUT FormatData<out TOUT>(T dataIn);
protected abstract dynamic GetData(T dataRow);
public string GetDataString(T dataRow)
{
dynamic data = GetData(dataRow);
switch (Type)
{
case ColumnType.String:
case ColumnType.Integer:
case ColumnType.Decimal:
return data.ToString();
case ColumnType.Date:
return data.ToShortDateString();
case ColumnType.Currency:
return data.ToString("c");
break;
case ColumnType.Boolean:
var b = (bool)data;
if (b) return "Y";
else return "N";
default:
throw new ArgumentOutOfRangeException();
}
}
}
public class MyListViewColumnData<TOUT> : MyListViewColumnData
{
public MyListViewColumnData(string name, int width, ColumnType type, FormatData<TOUT> dataFormater)
{
DataFormatter = x => dataFormater(x); // Per http://stackoverflow.com/a/1906850/298754
Type = type;
Width = width;
Name = name;
}
public Func<T, TOUT> DataFormatter { get; protected set; }
protected override dynamic GetData(T dataRow)
{
return DataFormatter(dataRow);
}
}
}
This is called from a factory method (in ColumnDataBuilder) as
public MyListViewColumnData Create<TOUT>(string name, int width, ColumnType type, MyListViewColumnData.FormatData<TOUT> dataFormater)
{
return new MyListViewColumnData<TOUT>(name, width, type, dataFormater);
}
public MyListViewColumnData Create(string name, int width, MyListViewColumnData.FormatData<DateTime> dataFormater)
{
return new MyListViewColumnData<DateTime>(name, width, ColumnType.Date, dataFormater);
}
...
That, in turn, is called from my code as:
builder.Create("Date", 40, x => x.createdDate);
and
private ListViewItem CreateListViewItem<TDATA>(IEnumerable<ColumnDataBuilder<TDATA>.MyListViewColumnData> columns, TDATA rowData)
{
var item = new ListViewItem();
foreach (var col in columns)
{
item.SubItems.Add(col.GetDataString(rowData));
}
item.SubItems.RemoveAt(0); // We generate an extra SubItem for some reason.
return item;
}
How can I refactor this so that I'm not using dynamic, but still preserve the syntax as it currently exists in the code?
dynamic, that'd be good to know too... but I'm pretty sure it isn't. – Bobson Dec 3 '12 at 16:52Tcome from? – Jeff Vanzella Dec 3 '12 at 17:19public abstract class MyListViewColumnDatahas no generic parameters while it hasdelegate TOUT FormatData<out TOUT>(T dataIn)declared. Please make sure you post a compilable code here – almaz Dec 3 '12 at 17:30