将对象传递给函数以使用不同 C# 类之间的通用功能

本文关键字:之间 功能 函数 对象 | 更新日期: 2023-09-27 18:25:29

我在 ASP.NET 网页中有一个GridView和一个DetailsView,我需要提取其中一个以获取其信息,我已经为此创建了一个函数。GridView 和 DetailsView 都有一个名为 Rows 的属性,这是我需要在函数中使用的属性。

所以在代码中我有如下内容:

// Where dv is DetailsView and gv is GridView
if(someBool) 
   foo(dv); 
else
   foo(gv);

其中 foo 如下所示:

void foo(SomeBaseClassOrInterface dv) {
    foreach(var row in dv.Rows) {
       Use(row.Cells[2].Text); // Simply read each row
     }
}

与其制作两个不同的函数,我想我可以使用同一个函数,因为 DetailsViewRowCollection 和 GridViewRowCollection 的操作是彼此的镜像。问题是我没有看到共享 Rows 属性的基类。

我尝试创建两个继承自 DetailsView 和 GridView 的类,并仅使用其父级的 Row 属性,两者都实现了一个接口,然后我在主代码中使用,但这似乎不起作用。原因是详细信息视图和网格视图的行的返回类型不同,两种返回类型都继承自 IEnumerable,但实现接口的任何类都需要使其 Row 属性也返回 IEnumerable,使用泛型绕过此限制,但随后在我的调用代码中失败,该代码抱怨实现 GridView 和 DetailsView 的对象无法转换为接口类型。

我觉得我缺少一个非常简单的解决方案。也许在这种情况下复制代码可能更容易?

我正在尝试找到一种理想情况下避免重复代码的好方法。

谢谢

将对象传递给函数以使用不同 C# 类之间的通用功能

您可以定义接受 IEnumerable 的函数,并且由于 GridViewRow 和 DetailsViewRow 派生自 TableRow,因此可以使用 TableRow 作为枚举变量:

void foo(IEnumerable enumerable) {
    foreach(TableRow row in enumerable) {
       Use(row.Cells[2].Text); // Simply read each row
     }
}

您必须将行传递给函数:

if(someBool) 
   foo(dv.Rows); 
else
   foo(gv.Rows);

怎么样:

if(someBool) 
   Use(dv.SelectMany(x => x.Rows).SelectMany(x => x.Cells[2].Text));
else
   Use(gv.SelectMany(x => x.Rows).SelectMany(x => x.Cells[2].Text));

并将Use()方法更改为接受IEnumerable<string>而不是单个字符串。

看起来仍然违反 DRY,但您已经删除了foo()方法。

一个选项 - 创建"提取器"接口,该接口将处理从其中任何一个获取信息。添加 2 个实现 - 一个用于GridView,另一个用于DetailsView

class CellType
{
   // some fields that are interesting like
   public string Text {get;set;}
}
class Row {
   public List<CellType> Cells {get;set}
}
interface IRowExtractor
{ 
     IEnumerable<Row> Rows {get};
}
class GVRowExtractor : IRowExtractor
{
   List<Rows> rows;
   public GVRowExtractor(GridView gv)
   {
        // fill Rows from gv
   }
   public IEnumerable<Row> Rows {get {return rows;}};
}
class DVRowExtractor : IRowExtractor ....
void foo(IRowExtractor dv) {
  foreach(var row in dv.Rows) {
     Use(row.Cells[2].Text); // Simply read each row
 }
}

用法:

foo(new DVRowExtractor(dv));