6

次のようなサービス層コードの行を書くのに少しうんざりしています。

以下のコードは、読者向けの単なる例です。そのため、エラーやタイプミスがある可能性があります。申し訳ありません:)

//ViewModel
public class EntityIndexFilterPartial
{
    public int? Id { get; set; }
    public DateTime? StartDate { get; set; }
    public DateTime? EndDate { get; set; }
    public IEnumerable<SelectListItem> StatusList { get; set; }
    public int? StatusID { get; set; }
}


//Service Layer method
//Method parameters are reperesents view model properties
public IQueryable<Entity> FilterBy(int? id, DateTime? startDate, DateTime? endDate, int? statusId)
{
    var filter = _db.Entities.AsQueryable();
    if (id.HasValue)
        filter = filter.Where(x => x.Id == id.Value);
    if (startDate.HasValue)
        filter = filter.Where(x => x.StartDate >= startDate.Value);
    if (endDate.HasValue)
        filter = filter.Where(x => x.EndDate <= endDate.Value);
    if (statusId.HasValue)
        filter = filter.Where(x => x.EntityStatus.StatusID == statusId);
    return filter;
}

私はいくつかのスマートに設計されたコードを十分に検索します。私はDynamic LINQ ライブラリについて知っており、それも使用しています。しかし、強く型付けされたフィルタリングを探しています。私は魔法の文字列などを書きたくありません。

したがって、基本的にはいくつかの解決策を見つけましたが、よく書かれたスマートコードについてこのコミュニティから聞きたいです。もちろん、何十もの解決策があるかもしれませんが、厳密に型指定されたフィルタリング サービス レイヤー コードをどのように記述しますか。何か案は...

ここに私の解決策のいくつかがあります:

解決策 1: 同じ FilterBy メソッドですが、パラメーターが異なり、式リストを取得するようになりました。これは、コントローラーで predicateList を作成して、ここに送信することを意味します。

public IQueryable<Entity> FilterBy(List<Expression<Func<Entity,bool>>> predicateList)
{
    var filter = _db.Entities.AsQueryable();
    foreach (var item in predicateList)
    {
        filter = filter.FilterBy(item);
    }
    return filter;
}

解決策 2: アプリケーション サービス レイヤー (ドメイン サービスではない) のパラメーターとして EntityIndexFilterPartial を取得する FilterBy メソッド。このデザインにはいくつか問題があると思いますが、皆さんの意見を聞きたいです。

public IQueryable<Entity> FilterBy(EntityIndexFilterPartial filterPartial)
{
    //I'm calling the domain service layer FilterBy method such as like in solution 1.
}

解決策 3: これは他のものよりもはるかに優れていると思いますが、もっとシンプルで優れたコードを考えています。

//helper class
public static class FilterByHelper
{
    public static IQueryable<T> If<T>(this IQueryable<T> filter, bool condition, Expression<Func<T, bool>> predicate)
    {
        if (condition)
            return filter.FilterBy(predicate);
        return filter;
    }

    public static IQueryable<T> FilterBy<T>(this IQueryable<T> filter, Expression<Func<T, bool>> predicate)
    {
        return filter.Where(predicate);
    }
}


public IQueryable<Entity> FilterBy(int? id, DateTime? startDate, DateTime? endDate, int? statusId)
{
    return _db.Entities
        .If(id.HasValue, x => x.Id == id.Value)
        .If(startDate.HasValue, x => x.StartDate >= startDate.Value)
        .If(endDate.HasValue, x => x.EndDate <= endDate.Value)
        .If(statusId.HasValue, x => x.EntityStatus.StatusID == statusId);
}

少し長い質問になってしまいましたが、聞きたいことをはっきりと聞いていただければ幸いです。

簡単な質問ですが、これらのフィルタリング コードの同じ行を書かなくて済むように、スマートに設計されたコードをご存知ですか?

ところで、私はデザインパターンの解決策や巨大な答えを探しているわけではありません.いくつかの例を挙げたり、より良いパスを見つける方法で十分だと言うことができます.

もちろん、あなたが完全に説明された応答を書いたら、私は適用されます。

ありがとうございました。

4

3 に答える 3

2

こんにちは Yusuf この投稿はあなたにとって役立つかもしれません。

http://amitech.co/amitech-lab/item/dynamically-add-conditions-in-linq

それが役に立てば幸い

于 2013-08-03T07:10:15.193 に答える