Reputation: 25
I have a method which requires an IList to be defined when calling. It works great, however, as the project has expanded, we have continuously copy/pasted the code, and changed the type of the list, as these are coming from Models. Is there a simple way without defining it as dynamic to streamline the process so we can just re-use this method?
We tried dynamic but the tech lead is against using dynamic.
private int ReportDataWriter(ExcelWorksheet worksheet, IList<ReportGridColumnModel> headerColumns, IList<CoolModel> modelData, int rowIndex)
{
var dataHeaderCount = headerColumns.Count();
var totalItems = modelData.Count;
var lineIndex = rowIndex;
for (var i = 0; i < totalItems; i++)
{
var colIndex = 1;
foreach (var dataHeader in headerColumns)
{
worksheet.DataWriter(dataHeader, rowIndex, colIndex, colIndex);
using (var cell = worksheet.Cells[rowIndex, colIndex++])
{
var valueToWrite = GetColumnValue(dataHeader.Field, modelData[i]);
cell.Value = valueToWrite;
worksheet.Column(colIndex - 1).AutoFit();
if (modelData[i].IsCatRow)
{
worksheet.SetBackGroundColor(ExcelFillStyle.Solid, Color.LightGray, rowIndex,
dataHeaderCount, 1);
}
}
}
rowIndex++;
}
if (modelData[0].CategoryTitle == ReportConstants.Total)
{
worksheet.SetBottomBorder(ExcelBorderStyle.Thin, Color.Black, lineIndex, dataHeaderCount, 1);
}
return rowIndex;
}
Upvotes: 0
Views: 157
Reputation: 16801
You could make it generic with constraints on the generic types.
public int DataWriter<THeader, TModel>(ExcelWorksheet worksheet, IList<THeader> headerColumns, IList<TModel> modelData, int rowIndex)
where THeader: IHeader
where TModel: IModel
{
var dataHeaderCount = headerColumns.Count();
var totalItems = modelData.Count;
var lineIndex = rowIndex;
for (var i = 0; i < totalItems; i++)
{
var colIndex = 1;
foreach (var dataHeader in headerColumns) {
worksheet.DataWriter(dataHeader, rowIndex, colIndex, colIndex);
using (var cell = worksheet.Cells[rowIndex, colIndex++]) {
var valueToWrite = GetColumnValue(dataHeader.Field, modelData[i]);
cell.Value = valueToWrite;
worksheet.Column(colIndex - 1).AutoFit();
if (modelData[i].IsCatRow) {
worksheet.SetBackGroundColor(ExcelFillStyle.Solid, Color.LightGray, rowIndex,
dataHeaderCount, 1);
}
}
}
rowIndex++;
}
if (modelData[0].CategoryTitle == ReportConstants.Total) {
worksheet.SetBottomBorder(ExcelBorderStyle.Thin, Color.Black, lineIndex, dataHeaderCount, 1);
}
return rowIndex;
}
The interfaces
public interface IHeader
{
string Field { get; }
}
public interface IModel
{
string CategoryTitle { get; }
bool IsCatRow { get; }
}
To use it, make sure all header column classes implements the IHeader
interface and each model implements IModel
.
Usage example:
var headers = new List<ReportGridColumnModel>();
var models = new List<CoolModel>();
var worksheet = new ExcelWorksheet();
var r = DataWriter(worksheet, headers, models);
Another option is, instead of using interfaces, use abstract classes which implements the properties and all derived classes could then use the method the same way.
Upvotes: 1