C# 简化大量重复使用的代码

C# 简化大量重复使用的代码,c#,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 t

我有一个物体,有点像

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
条件,在很多情况下我都必须这样做。有人能告诉我实现这一目标的最佳方式是什么吗

您可以修复的一位重复代码是传递给
Select()
的委托:

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

那么就这样称呼它:

var failRecord = GetObject(testNames, ex => ex.TestNamesId == 3 && ex.TestItemName == "Fail");
请给该方法命名一个比
GetObject
更合适的名称,但如果不了解更多上下文,我就不能推荐一个好名称:)

现在,如果
Where
表达式的形式始终相同,则可以更进一步,将
TestNamesId
TestItemName
应作为参数而不是委托传递给方法:

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();
}

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

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;
     }
 }

这是代表式的解决方案。您可以将其重构为纯方法

public Foo GetInfo(TestName testNames)
{
    int testNameId = testNames.TestId;
    Foo foo = new Foo();
        Func<TestItem, dynamic> dynamicBuilder = r => new { r.TestItemId, r.TestItemName, r.TestItemDirectory };
        Func<string, int, TestItem> filteringMethod = (name, nameId) => testNames.TestItems.Where(ex => ex.TestNamesId == nameId && ex.TestItemName == name).Select(dynamicBuilder).FirstOrDefault();
        Func<TestItem, string> formatMethod = record => $"{record.TestItemId},{record.TestItemName},{record.TestItemDirectory}";

        switch (testNameId)
        {
            case 3:
                foo.PassChoiseInfo = formatMethod(filteringMethod("Pass", 3));
                foo.FailChoiceInfo = formatMethod(filteringMethod("Fail", 3));
                foo.NAChoiceInfo = formatMethod(filteringMethod("N/A", 3));
            break;
        case 4:
            break;
        case 5:
            break;
        case 7:
            break;

            //6 more cases
    }

    return foo;
}
publicfoogetinfo(TestName testNames)
{
int testNameId=testNames.TestId;
Foo-Foo=新的Foo();
Func dynamicBuilder=r=>new{r.TestItemId,r.TestItemName,r.TestItemDirectory};
Func filteringMethod=(name,nameId)=>testNames.TestItems.Where(ex=>ex.testnameid==nameId&&ex.TestItemName==name)。选择(dynamicBuilder.FirstOrDefault();
Func formatMethod=record=>$“{record.TestItemId},{record.TestItemName},{record.TestItemDirectory}”;
开关(testNameId)
{
案例3:
foo.PassChoiseInfo=formatMethod(filteringMethod(“Pass”,3));
foo.FailChoiceInfo=formatMethod(filteringMethod(“Fail”,3));
foo.NAChoiceInfo=formatMethod(filteringMethod(“N/A”,3));
打破
案例4:
打破
案例5:
打破
案例7:
打破
//还有6例
}
返回foo;
}

也可以删除
switch
语句,使代码更通用。

我将把查询提取到另一个方法,该方法返回您需要的描述字符串

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}";
}

你能为
GetInfo
应该做的事情添加一个快速可读的版本吗?对于初学者,你可以使用where子句的字符串参数将查询提取到一个方法中。请你详细说明一下,因为我对代理的了解不是最丰富的,为什么要使用
Func
,因为它与3个检查中的2个检查完全相同
在哪里
s?我只需要请求
TestNamesId
TestItemName
作为parameters@Code“委托”是指引用方法的变量。在C中,您可以将其称为函数指针。您的
r=>…
表达式是一个“lambda表达式”,用于创建一个匿名委托,该委托由
Select()
调用。在这里,我将展示如何只创建一次代理,并在多个调用中重用它。谢谢,我将尝试一下,并让您知道我是如何得到代理的on@CamiloTerevinto当然,你可以这样做,我把它编辑成了答案。我试图显示从最小到最大的步骤。
GetDataWithName
表示返回
YourType
,但它返回一个匿名对象,因此这不需要编译。您需要更正
GetDataWithName
方法
ex.TestNamesId==3
应该是
ex.TestNamesId==testNames.TestId
如何将
GetDataWithName
的返回类型从
Foo
更改为
dynamic
?这需要是静态的吗?@krs没有理由不。
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;
     }
 }
public Foo GetInfo(TestName testNames)
{
    int testNameId = testNames.TestId;
    Foo foo = new Foo();
        Func<TestItem, dynamic> dynamicBuilder = r => new { r.TestItemId, r.TestItemName, r.TestItemDirectory };
        Func<string, int, TestItem> filteringMethod = (name, nameId) => testNames.TestItems.Where(ex => ex.TestNamesId == nameId && ex.TestItemName == name).Select(dynamicBuilder).FirstOrDefault();
        Func<TestItem, string> formatMethod = record => $"{record.TestItemId},{record.TestItemName},{record.TestItemDirectory}";

        switch (testNameId)
        {
            case 3:
                foo.PassChoiseInfo = formatMethod(filteringMethod("Pass", 3));
                foo.FailChoiceInfo = formatMethod(filteringMethod("Fail", 3));
                foo.NAChoiceInfo = formatMethod(filteringMethod("N/A", 3));
            break;
        case 4:
            break;
        case 5:
            break;
        case 7:
            break;

            //6 more cases
    }

    return foo;
}
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}";
}