Skip to main content
Code Review

Return to Revisions

4 of 4
replaced http://stackoverflow.com/ with https://stackoverflow.com/

Refactoring to avoid the use of dynamic

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 https://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?

Bobson
  • 1k
  • 5
  • 13
lang-cs

AltStyle によって変換されたページ (->オリジナル) /