简化了大量重用代码

时间:2018-01-30 15:43:03

标签: c#

我有一个类似

的对象
public class Foo
{
    public string PassChoiseInfo { get; set; }
    public string FailChoiceInfo { get; set; }
    public string NAChoiceInfo { get; set; }
}

我有一个方法,用适当的数据返回对象,如下所示:

public Foo GetInfo(TestName testNames)
{
   int testNameId = testNames.TestId;
   Foo foo = new Foo();
   switch (testNameId)
   {
     case 3:
        var passRecord = testNames.TestItems.Where(ex => ex.TestNamesId == 3 && ex.TestItemName == "Pass")
              .Select(r => new
               {
                  r.TestItemId,
                  r.TestItemName,
                  r.TestItemDirectory
                }).FirstOrDefault();

         foo.PassChoiseInfo = $"{passRecord.TestItemId},{passRecord.TestItemName},{passRecord.TestItemDirectory}";

         var failRecord = testNames.TestItems.Where(ex => ex.TestNamesId == 3 && ex.TestItemName == "Fail")
               .Select(r => new
                {
                   r.TestItemId,
                   r.TestItemName,
                   r.TestItemDirectory
                 }).FirstOrDefault();

          foo.FailChoiceInfo = $"{failRecord.TestItemId},{failRecord.TestItemName},{failRecord.TestItemDirectory}";

          var naRecord = testNames.TestItems.Where(ex => ex.TestNamesId == 3 && ex.TestItemName == "N/A")
                .Select(r => new
                 {
                    r.TestItemId,
                    r.TestItemName,
                    r.TestItemDirectory
                  }).FirstOrDefault();

           foo.NAChoiceInfo = $"{naRecord.TestItemId},{naRecord.TestItemName},{naRecord.TestItemDirectory}";
                break;
            case 4:
                break;
            case 5:
                break;
            case 7:
                break;

                //6 more cases
        }

        return foo;
    }
}

正如您在我的GeTInfo方法中所看到的,我继续使用相同的代码来更改.where条件,我必须在很多情况下执行此操作。有人能告诉我实现这一目标的最佳方法是什么?

4 个答案:

答案 0 :(得分:2)

我将查询提取到另一个返回所需描述字符串的方法。

public Foo GetInfo(TestName testNames)
{
   string GetItemDescriptionShortcut(string testItemName)
   {
      return this.GetItemDescription(testNames, testItemName);
   }

   Foo foo = new Foo
   {
      PassChoiseInfo = GetItemDescriptionShortcut("Pass"),
      FailChoiceInfo = GetItemDescriptionShortcut("Fail"),
      NAChoiceInfo = GetItemDescriptionShortcut("N/A")
   }

   return foo;

}

private string GetItemDescription (TestName testNames, string testItemName)
{
    var item = testNames.TestItems
        .Where(ex => ex.TestNamesId == testNames.TestId && ex.TestItemName == testItemName)
        .Select(r => new
        {
          r.TestItemId,
          r.TestItemName,
          r.TestItemDirectory
        }).FirstOrDefault();

    if (item == null) return null; // or empty string

    return $"{item.TestItemId},{item.TestItemName},{item.TestItemDirectory}";
}

答案 1 :(得分:1)

您可以解决的一点重复代码是传递给Select()的代理:

r => new
{
    r.TestItemId,
    r.TestItemName,
    r.TestItemDirectory
}

目前,您正在制作此委托的三个匿名实例。相反,您可以创建一次委托并将其另存为Func<TypeOfR, Foo>类型的局部变量,然后将该变量传递给Select()

Func<TypeOfR, Foo> select = r => new { ... };
// ...
...Select(select).FirstOrDefault();

再远一点,你的三次重复中唯一真正改变的是Where子句。因此,您可以定义一个执行样板的函数,并将Where子句或委托作为形式参数:

Foo GetObject(TestName testNames, Func<TypeOfEx, bool> predicate)
{
    return testNames.TestItems
        .Where(predicate)
        .Select(r => new
            {
                r.TestItemId,
                r.TestItemName,
                r.TestItemDirectory
            }).FirstOrDefault();
}

然后这样称呼:

var failRecord = GetObject(testNames, ex => ex.TestNamesId == 3 && ex.TestItemName == "Fail");

请为方法命名比GetObject更合适的方法,但如果不了解更多背景信息,我就无法建议一个好名字:)

现在,如果您的Where表达式始终采用相同的格式,您可以再向前迈一步,将TestNamesIdTestItemName应作为参数保存的值传递给您的方法代表:

Foo GetObject(TestName testNames, string id, string name)
{
    return testNames.TestItems
        .Where(ex => ex.TestNamesId == id && ex.TestItemName == name)
        .Select(r => new
            {
                r.TestItemId,
                r.TestItemName,
                r.TestItemDirectory
            }).FirstOrDefault();
}

答案 2 :(得分:0)

它是委托风格的解决方案。你可以将它重构为纯方法。

switch

也可以删除NullPointerException语句并使代码更通用。

答案 3 :(得分:-1)

您应该创建一个包含重复代码的辅助函数。

private static dynamic GetDataWithName(TestName testNames, string name)
{
    return testNames.TestItems.Where(ex => ex.TestNamesId == testNames.TestId && ex.TestItemName == name)
    .Select(r => new
    {
        r.TestItemId,
        r.TestItemName,
        r.TestItemDirectory
    }).FirstOrDefault();    
}

public Foo GetInfo(TestName testNames)
{
    int testNameId = testNames.TestId;
    Foo foo = new Foo();
    switch (testNameId)
    {
         case 3:
              var passRecord = GetDataWithName(testNames, "PASS");

          foo.PassChoiseInfo = $"{passRecord.TestItemId},{passRecord.TestItemName},{passRecord.TestItemDirectory}";

          var failRecord = GetDataWithName(testNames, "FAIL");

           foo.FailChoiceInfo = $"{failRecord.TestItemId},{failRecord.TestItemName},{failRecord.TestItemDirectory}";

           var naRecord = GetDataWithName(testNames, "N/A");

            foo.NAChoiceInfo = $"{naRecord.TestItemId},{naRecord.TestItemName},{naRecord.TestItemDirectory}";
                 break;
             case 4:
                 break;
             case 5:
                 break;
             case 7:
                 break;

                 //6 more cases
         }

         return foo;
     }
 }