Murgy
Murgy

Reputation: 25

How to allow multiple different IList to be called through a method

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

Answers (1)

Marcus H&#246;glund
Marcus H&#246;glund

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

Related Questions