I'm trying to implement a generic Excel Export.
I've created two Interfaces IData
and IDataList
. IData
provides a function to get the Data transformed to an array and IDataList
a function to get the corresponding names of the properties.
The interfaces
public interface IData
{
string[] GetData();
}
public interface IDataList<IData> : IList<IData>
{
string[] GetHeader();
}
The classes
public Data : IData
{
public string col1 { get; set; }
public string[] GetData()
{
return new [col1];
}
}
public DataList : List<Data>, IDataList<Data>
{
public string[] GetHeader()
{
return new ["col1"];
}
}
Trying to use it
public void CreateDocument(IDataList<IData> dataList)
{
// ...
worksheet.Import(dataList.GetHeader(), RowIdx++, ColIdx, false);
// ...
foreach (IData data in dataList)
{
worksheet.Import(data.GetData(), RowIdx++, ColIdx, false);
}
}
DataList data {get;set;} = new DataList();
// ... populate data
CreateDocument(data);
The project won't compile with the error message:
Error CS1503 Argument 1: cannot convert from 'DataList' to 'IDataList<IData>'
I was wondering if you could point me in the right direction?
Edit: This question has been marked a duplicate of Why an inherited interface can't be converted to its base interface in generic context?. While that question does explain why I can't call the function the way I've tried it does not help me resolve my issue.
I'm trying to implement the interfaces that I have designed in order to write a generic function WriteDocument()
. This means that I require access to the functions GetHeader()
and GetData()
. Some people have suggested to use IEnumerable
instead of IList
but I haven't been able to successfully implement that either.
What I have are multiple objects that all have to be written in the same style to an Excel file. The objects have different properties. With the help of GetData()
I can convert these properties to a string array which can easily be dumped to the excel file. The GetHeader()
function returns the names of these properties in the same order as GetData()
.
I'm open to a different approach however I'm not sure where to get started. It would be cool to have the WriteDocument()
function in a generic way so I don't have to duplicate the code for every object.
Edit2: Instead of trying to solve this with generics there's a much simpler solution. Rewrite CreateDocument—Function:
public void CreateDocument(string[] header, IEnumerable<string[]> data) { }
The classes and interface need a slight change
public interface IHasHeader { string[] GetHeader(); }
public class DataList : List<Data>, IHasHeader { }
public class Data : IData { }
The interfaces aren't actually required anymore at this point.
The function can then be used as follows:
public DataList data = new DataList();
// data.Add(new Data(){ ... })
CreateDocument(data.GetHeader(), data.Select(x => x.GetData()));
I don't have the required reputation to add a solution. If anyone were to convert it to a solution I'd be willing to accept.