![](/img/trans.png)
[英]Overloading a method that takes a generic list with different types as a parameter
[英]Method that takes a list as input parameter where each item is a different generic type
注意:請在鎖定之前幫助我更好地格式化這個問題——我可能不夠精明,無法按照 StackOverflow 標准制定這個問題。 我將根據需要編輯帖子以進行澄清。
如何創建接收列表的方法,其中列表中的每個項目都屬於不同的泛型類型? 我已經嘗試了很多排列,但似乎找不到有效的方法。 我正在使用 OpenXml SDK 創建電子表格以在 Excel 中打開。 這個想法是創建一個單個文檔,該文檔接受具有 T 類型不同行數據的多個工作表作為配置。我的 api 看起來像這樣:
OpenXmlHelpers.Spreadsheet.CreateDocument(new ArrayList{
new SheetConfig<Foo> { Name = "Foo sheet", RowData = ..., Columns = ...},
new SheetConfig<Bar> { Name = "Bar sheet", RowData = ..., Columns = ...},
});
其中Foo
和Bar
是我想在 Excel 文檔的每張紙上輸出為行數據的任何模型。 而SheetConfig
就像:
public class SheetConfig<T>
{
/// <summary>
/// Name of the sheet (shown in the tab)
/// </summary>
public string Name { get; set; }
/// <summary>
/// Objects to display in the sheet
/// </summary>
public IList<T> RowData { get; set; }
/// <summary>
/// Field names to extract from the RowData and use as header names
/// </summary>
public List<ColumnConfig> Columns { get; set; }
}
和ColumnConfig
就像:
public class ColumnConfig
{
/// <summary>
/// Header text
/// </summary>
public string Title { get; set; }
/// <summary>
/// Object property to use under header
/// </summary>
public string FieldName { get; set; }
}
到目前為止,我的Spreadsheet
類看起來像:
public class Spreadsheet
{
public static void CreateDocument(IEnumerable<SheetConfig<T>> configs)
{
using (OpenXml.SpreadsheetDocument spreadsheetDocument = OpenXml.SpreadsheetDocument.Create("file.path.here", OpenXml.SpreadsheetDocumentType.Workbook))
{
// OpenXml stuff...
OpenXml.Sheets sheets = new OpenXml.Sheets();
foreach (var s in configs)
{
sheets.AppendChild(CreateSheet(s));
}
}
}
private static OpenXml.Sheet CreateSheet<T>(SheetConfig<T> config)
{
// OpenXML stuff...
return new OpenXml.Sheet { Name = config.Name };
}
}
第一個問題是它抱怨CreateDocument
不像CreateDocument<T>
並且我認為IEnumerable<SheetConfig<T>>
輸入不完全正確,因為列表不是完全相同的類型T
而是任意數量的類型,像Foo
和Bar
。
解決方案是確保所有模型類都有一個公共基類,我在下面的示例代碼中將其稱為ModelBase
。 這很像 Open XML SDK 中的OpenXmlElement
類,它是 SDK 提供的所有強類型類的基類。
public class ModelBase
{
private readonly Dictionary<string, object> _values = new Dictionary<string, object>();
public object GetValue(string fieldName)
{
return _values.TryGetValue(fieldName, out object value) ? value : null;
}
public void SetValue(string fieldName, object value)
{
_values[fieldName] = value;
}
}
public class Foo : ModelBase
{
public string First
{
get => (string) GetValue(nameof(First));
set => SetValue(nameof(First), value);
}
public int Second
{
get => (int) GetValue(nameof(Second));
set => SetValue(nameof(Second), value);
}
}
public class Bar : ModelBase
{
public string One
{
get => (string)GetValue(nameof(One));
set => SetValue(nameof(One), value);
}
public DateTime Two
{
get => (DateTime) GetValue(nameof(Two));
set => SetValue(nameof(Two), value);
}
}
上面的示例代碼定義了兩個模型類Foo
和Bar
,它們都派生自ModelBase
。 后者還提供了由Dictionary<string, object>
支持的“通用”getter 和 setter 方法,可用於按字段名稱存儲值。
根據上面的代碼,您將修改您的SheetConfig<T>
如下所示,即通過添加約束where T : ModelBase
。
public class SheetConfig<T> where T : ModelBase
{
/// <summary>
/// Name of the sheet (shown in the tab)
/// </summary>
public string Name { get; set; }
/// <summary>
/// Objects to display in the sheet
/// </summary>
public IList<T> RowData { get; set; }
/// <summary>
/// Field names to extract from the RowData and use as header names
/// </summary>
public List<ColumnConfig> Columns { get; set; }
}
public class ColumnConfig
{
/// <summary>
/// Header text
/// </summary>
public string Title { get; set; }
/// <summary>
/// Object property to use under header
/// </summary>
public string FieldName { get; set; }
}
最后,您的代碼沒有編譯,因為您應該編寫CreateDocument<T>(...)
而不是僅僅CreateDocument(...)
。 但是,不再需要 type 參數,因為您現在可以使用IEnumerable<SheetConfig<ModelBase>> configs
作為形式參數。 總的來說, Spreadsheet
類可以更改如下:
public class Spreadsheet
{
public static void CreateDocument(IEnumerable<SheetConfig<ModelBase>> configs)
{
using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create("file.path.here", SpreadsheetDocumentType.Workbook))
{
// OpenXml stuff...
var sheets = new Sheets();
foreach (SheetConfig<ModelBase> s in configs)
{
sheets.AppendChild(CreateSheet(s));
}
}
}
private static Sheet CreateSheet(SheetConfig<ModelBase> config)
{
// OpenXML stuff...
return new Sheet { Name = config.Name };
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.