【问题标题】:Passing object to a function to use common functionality among distinct C# classes将对象传递给函数以使用不同 C# 类之间的通用功能
【发布时间】:2013-07-30 07:58:53
【问题描述】:

我在 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 属性,它们都实现了一个接口,然后我在我的主代码中使用该接口,但这似乎不起作用。原因是 DetailsView 和 GridView 的 Rows 的返回类型不同,这两种返回类型都继承自 IEnumerable,但任何实现该接口的类都需要使其 Row 属性也返回一个 IEnumerable,使用泛型绕过此限制,但随后在我的调用代码中失败它抱怨我的实现 GridView 和 DetailsView 的对象无法转换为 Interface 类型。

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

我正在尝试找到一种可以避免重复代码的好方法。

谢谢

【问题讨论】:

  • 因为它们不共享基类(Object 除外),就像你说的那样,真的没有办法用相同的方法处理代码。我认为您已通过将逻辑提取到 Use 方法中来尽可能地简化它。这样,您复制的唯一代码就是循环,这在 IMO 中非常公平。

标签: c# asp.net


【解决方案1】:

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

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

您必须将 Rows 传递给函数:

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

【讨论】:

    【解决方案2】:

    怎么样:

    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() 方法。

    【讨论】:

      【解决方案3】:

      一个选项 - 创建“提取器”界面,该界面将处理从其中任何一个获取信息。添加 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));
      

      【讨论】:

        猜你喜欢
        • 2010-09-20
        • 2021-01-01
        • 2015-02-01
        • 2012-05-01
        • 1970-01-01
        • 2013-09-21
        • 2013-08-23
        • 2017-07-21
        • 2018-04-06
        相关资源
        最近更新 更多