简体   繁体   English

将两种方法合并为一种

[英]Merge two methods into one

How can i merge methods below? 我如何合并以下方法? and should i actually do this? 我应该这样做吗?

public IQueryable<ItemDTO> RepGetMonthItems(string inOut, string planFact, int month)
{
    return GetItemsWithCategory().
            Where(i => i.InOut.Equals(inOut)).
            Where(i => i.PlanFact.Equals(planFact)).
            Where(i => i.DateTime.Month.Equals(month));
}

public IQueryable<ItemDTO> RepGetYearItems(string inOut, string planFact, int year)
{
    return GetItemsWithCategory().
            Where(i => i.InOut.Equals(inOut)).
            Where(i => i.PlanFact.Equals(planFact)).
            Where(i => i.DateTime.Year.Equals(year));
}

No, you shouldn't. 不,你不应该。 The three answers I see all break the "do one thing" rule by Robert "Uncle Bob" Martin. 我看到的三个答案都打破了罗伯特“叔叔鲍勃”马丁的“做一件事”规则。 Read about it here . 在这里阅读它。

I agree with the 'do one thing' principle. 我同意“做一件事”的原则。 But I also believe in DRY. 但我也相信DRY。

So.. extension methods to the rescue! 所以..扩展方法来救援!

Have the main function do one thing (get report items) and extension methods filter by year or month. 让主要功能做一件事(获取报告项目)和扩展方法按年或月过滤。

Declare an extension method class like this: 声明一个像这样的扩展方法类:

    public static class QueryExtensions
    {
        public static IQueryable<ItemDTO> ForYear(this IQueryable<ItemDTO> query, int year)
        {
            return query.Where(i => i.DateTime.Year.Equals(year));
        }

        public static IQueryable<ItemDTO> ForMonth(this IQueryable<ItemDTO> query, int month)
        {
            return query.Where(i => i.DateTime.Month.Equals(month));
        }
    }

The create a cut-down RepGetItems method like this: 创建一个简化的RepGetItems方法,如下所示:

    public IQueryable<ItemDTO> RepGetItems(string inOut, string planFact)
    {
        return GetItemsWithCategory().
            Where(i => i.InOut.Equals(inOut)).
            Where(i => i.PlanFact.Equals(planFact));
    }

Usage then looks like this: 用法然后如下所示:

 var yearResults = originalQuery.RepGetItems(input, fact).ForYear(2015);
 var monthResults = originalQuery.RepGetItems(input, fact).ForMonth(10);

or even: 甚至:

 var yearMonthResults = originalQuery.RepGetItems(input, fact).ForYear(2015).ForMonth(10);

Total flexibility, no loss of 'single purpose' principle. 灵活性,不损失“单一目的”原则。

Maybe you could use Nullable<int> for year and month: 也许你可以使用Nullable<int>来表示年份和月份:

public IQueryable<ItemDTO> RepGetItems(string inOut, string planFact, int? year, int? month)
{
    return GetItemsWithCategory().
        Where(i => i.InOut.Equals(inOut)).
        Where(i => i.PlanFact.Equals(planFact)).
        Where(i => !year.HasValue  || i.DateTime.Year.Equals(year.Value)).
        Where(i => !month.HasValue || i.DateTime.Month.Equals(month.Value));
}

The .Where conditions can be easily added to a query. .Where条件可以轻松添加到查询中。

public IQueryable<ItemDTO> RepGetYearItems(string inOut, string planFact, int monthyear, bool useMonth)
{
    var query = GetItemsWithCategory().
        Where(i => i.InOut.Equals(inOut)).
        Where(i => i.PlanFact.Equals(planFact));

    if (useMonth)
    {
        query = query.Where(i => i.DateTime.Month.Equals(monthyear));
    }
    else
    {
        query = query.Where(i => i.DateTime.Year.Equals(monthyear));
    }

    return query;
}

or using int? 还是用int?

public IQueryable<ItemDTO> RepGetYearItems(string inOut, string planFact, int? year, int? month)
{
    var query = GetItemsWithCategory().
        Where(i => i.InOut.Equals(inOut)).
        Where(i => i.PlanFact.Equals(planFact));

    if (year != null)
    {
        query = query.Where(i => i.DateTime.Year.Equals(year.Value));
    }

    if (month != null)
    {
        query = query.Where(i => i.DateTime.Month.Equals(month.Value));
    }

    return query;
}

Note that this version is different from the one of @TimSchmelter... It isn't fixed (it depends on the "type" of SQL) what happens if you have in a query some "dead code" (pieces of query that aren't "active" because some parameters have a certain value, like int his query). 请注意,此版本与@TimSchmelter的版本不同...它不是固定的(它取决于SQL的“类型”)如果您在查询中有一些“死代码”(查询的片段)会发生什么't'活动“因为某些参数有一定的值,比如他的查询中的int。 His query clearly contains some "dead code" (the whole i => !year.HasValue || i.DateTime.Year.Equals(year.Value) ). 他的查询显然包含一些“死代码”(整个i => !year.HasValue || i.DateTime.Year.Equals(year.Value) )。 If possible I prefer to omit it. 如果可能的话我宁愿省略它。

How about using optional parameter here: 在这里使用可选参数怎么样:

public IQueryable<ItemDTO> RepGetMonthItems(string inOut, string planFact, int month, int year = -1)
    {
        return GetItemsWithCategory().Where(i => i.InOut.Equals(inOut) 
          && i.PlanFact.Equals(planFact)) && year == -1? 
            i.DateTime.Month.Equals(month) : i.DateTime.Year.Equals(year));
    }

Take a look at this example : 看看这个例子:

在此输入图像描述

As you can see each time you call method Where() you make a lot of extra work. 正如你可以看到每次调用方法Where()时你做了很多额外的工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM