【问题标题】:DataExport from DataGrid: Replace switch/case with something more genericDataGrid 中的 DataExport:用更通用的东西替换 switch/case
【发布时间】:2014-10-15 07:51:13
【问题描述】:

我有一个显示项目的数据网格。数据网格绑定到 ObservableCollection 类型的属性 DataGridItems。在代码中,我像这样动态实例化属性 DataGridItems:

this.DataGridItems = Db.Instance.RetrieveFoldingBoxes();

this.DataGridItems = Db.Instance.RetrieveLabels();

现在我想导出数据网格中显示(和过滤/排序)的数据。 我可以这样做:

    private void ExportData(ControlDataGrid dataGrid)
    {
        if (dataGrid == null) return;

        //items is type of Telerik.Windows.Data.DataItemCollection
        var items = dataGrid.GetFilteredCollection();

        switch (this.GetSelectedViewComboBoxItemName)
        {
            case "Folding Box":
                var exportItems1 = items.Cast<View_DataExport_FoldingBox>();
                this.GenericExport(exportItems1);
                break;

            //30 cases more...

            case "Label":
                var exportItems2 = items.Cast<View_DataExport_Label>();
                this.GenericExport(exportItems2);
                break;
        }
    }

    private void GenericExport<T>(IEnumerable<T> list) { ... }

但我真的不喜欢这样,因为这种冗余度很高。如果我能做这样的事情会更优雅:

    private void ExportData(ControlDataGrid dataGrid)
    {
        if (dataGrid == null) return;

        //items == Telerik.Windows.Data.DataItemCollection
        var items = dataGrid.GetFilteredCollection();

        //Getting the generic type in pseudo code
        //Also far from a good solution because I think CurrentItem could be null
        if(items.CurrentItem == null) return;
        var type = Type.GetType(items.CurrentItem);

        var exportItems = items.Cast<type>();

        this.GenericExport<type>(exportItems);
    }

我确信这是可能的,但目前我不知道如何。


编辑: 这是 GenericExport 方法的代码:

    private void GenericExport<T>(IEnumerable<T> list)
    {
        using (var excelPackage = new ExcelPackage())
        {
            var name = this.GetSelectedViewComboBoxItemName;

            excelPackage.Workbook.Properties.Company = "COMPANYNAME";
            excelPackage.Workbook.Properties.Author = Configuration.UserName;
            excelPackage.Workbook.Properties.Title = string.Concat("Export for ", name);
            excelPackage.Workbook.Properties.Category = "CATEGORY";

            var worksheet = excelPackage.Workbook.Worksheets.Add(name);

            worksheet.Cells["A1"].LoadFromCollection(list, true, TableStyles.Medium2);
            ExcelSheetFormatter.FormatWorksheet(worksheet, list);

            var fileName = this.GetSelectedViewComboBoxItemName;

            var fileDestination = DataExportHelper.ShowSaveFileDialog(fileName, false);

            if (fileDestination == null) return;

            try
            {
                excelPackage.SaveAs(fileDestination);
            }
            catch (InvalidOperationException)
            {
                throw new PulseException(ExceptionMessage.FileInUse, false);
            }

            DataExportHelper.OpenExportedFileDialog(fileDestination.FullName);
        }
    }

我正在使用 EPPlus 4.0 Beta 2 (epplus.codeplex.com/releases/view/118053) 将数据导出到 excel。

因此我绑定到 EPPlus 的 API,即:

    public ExcelRangeBase LoadFromCollection<T>(IEnumerable<T> Collection, ...);

【问题讨论】:

  • 你能把GenericExport 改成不是通用的吗? private void Export(IEnumerable items)
  • GenericExport&lt;T&gt; 中的代码是否因类型而异?
  • @LostInComputer:我正在使用 EPPlus 4.0 Beta 2 (epplus.codeplex.com/releases/view/118053) 将数据导出到 Excel。 EEPlus 期望和 IEnumerable 集合。方法签名是 public ExcelRangeBase LoadFromCollection(IEnumerable Collection)。
  • @Dennis:不,GenericExport 方法对于每种类型都是相同的。请参阅上面的编辑。

标签: c# .net wpf generics radgridview


【解决方案1】:

如果您无法更改GenericExport 签名,那么,恐怕,反射是您唯一的朋友。假设 items implement IList 包含相同类型的项目,并且不为空:

// make IEnumerable<YourType>
var itemType = items[0].GetType();
var castDef = typeof(Enumerable).GetMethod("Cast");
var cast = castDef.MakeGenericMethod(itemType);
var enumerable = cast.Invoke(null, new[] { items });

// call GenericExport<YourType>
var methodDef = typeof(Program).GetMethod("GenericExport", BindingFlags.Instance | BindingFlags.NonPublic);
var method = methodDef.MakeGenericMethod(itemType);

method.Invoke(this, new[] { enumerable });

【讨论】:

  • 我想我误解了你。我可以更改 GenericExport 方法,但不能更改 GenericExport 方法中使用的 LoadFromCollection。 LoadFromCollection 方法将 IEnumerable 作为参数。
  • @Joel: "但是我不能改变 LoadFromCollection" - 因此,你不能改变 GenericExport,因为最终你必须调用任何通用方法,无论是你自己的还是第三方的.
  • 感谢您的回答,它正在工作。我不得不说我不喜欢反思,如果有人提出“更好”的解决方案,我会等待 2-3 天。
猜你喜欢
  • 1970-01-01
  • 2017-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-28
  • 1970-01-01
  • 2019-05-14
  • 2013-11-12
相关资源
最近更新 更多