次のようなサービス層コードの行を書くのに少しうんざりしています。
以下のコードは、読者向けの単なる例です。そのため、エラーやタイプミスがある可能性があります。申し訳ありません:)
//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);
}
少し長い質問になってしまいましたが、聞きたいことをはっきりと聞いていただければ幸いです。
簡単な質問ですが、これらのフィルタリング コードの同じ行を書かなくて済むように、スマートに設計されたコードをご存知ですか?
ところで、私はデザインパターンの解決策や巨大な答えを探しているわけではありません.いくつかの例を挙げたり、より良いパスを見つける方法で十分だと言うことができます.
もちろん、あなたが完全に説明された応答を書いたら、私は適用されます。
ありがとうございました。