我正在尝试实现通用的Excel导出。
我已经创建了两个接口IData
和IDataList
。 IData
提供了将数据转换为数组的功能,IDataList
提供了获取属性的相应名称的功能。
接口
public interface IData
{
string[] GetData();
}
public interface IDataList<IData> : IList<IData>
{
string[] GetHeader();
}
课程
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"];
}
}
尝试使用它
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);
该项目将不会与错误消息一起编译:
Error CS1503 Argument 1: cannot convert from 'DataList' to 'IDataList<IData>'
我想知道你能否指出正确的方向?
编辑:此问题已被标记为Why an inherited interface can't be converted to its base interface in generic context?的重复项。尽管该问题确实说明了为什么我不能以尝试的方式调用该函数,但这并不能帮助我解决问题。
我正在尝试实现为编写通用函数WriteDocument()
而设计的接口。这意味着我需要访问功能GetHeader()
和GetData()
。有人建议使用IEnumerable
代替IList
,但我也未能成功实现。
我所拥有的是多个对象,所有对象都必须以相同的样式写入Excel文件。这些对象具有不同的属性。借助GetData()
,我可以将这些属性转换为字符串数组,可以轻松将其转储到excel文件中。 GetHeader()
函数以与GetData()
相同的顺序返回这些属性的名称。
我对其他方法持开放态度,但是我不确定从哪里开始。以通用的方式使用WriteDocument()
函数会很酷,因此我不必为每个对象重复编写代码。
Edit2 :与其尝试使用泛型来解决这个问题,还没有一个简单得多的解决方案。重写CreateDocument-函数:
public void CreateDocument(string[] header, IEnumerable<string[]> data) { }
类和接口需要稍作更改
public interface IHasHeader { string[] GetHeader(); }
public class DataList : List<Data>, IHasHeader { }
public class Data : IData { }
此时,实际上不再需要接口了。
该函数可以如下使用:
public DataList data = new DataList();
// data.Add(new Data(){ ... })
CreateDocument(data.GetHeader(), data.Select(x => x.GetData()));
我没有添加解决方案所需的声誉。如果有人将其转换为解决方案,我将愿意接受。
答案 0 :(得分:0)
您可以编写一个方法来接受任何列表,方法是告诉它得到一个IEnumerable
,基本类型List<T>
和IEnumerable<T>
。这是一个非泛型类型。如果您在这里输入IList<SomeType>
,则需要明确指定类型。
请参见下面的示例,如何在方法中使用IEnumerable并进行检查:
private class MyClass { }
private class MyClassWithInterface : IMyClass { }
private interface IMyClass { }
static void Main(string[] args)
{
ITakeLists(new List<MyClass>()); // it is
ITakeLists(new List<MyClassWithInterface>()); // isInstanceOf
ITakeLists(new List<int>()); // it is not
//ITakeLists(new MyClass()); // Error, is not derived from IEnumerable
}
private static void ITakeLists(IEnumerable myList)
{
if (myList is List<MyClass>)
Console.WriteLine("it is");
else if(typeof(IMyClass).IsAssignableFrom(myList.GetType().GetGenericArguments()[0]))
Console.WriteLine("isInstanceOf");
else
Console.WriteLine("it is not :(");
}