在IQueryable中分解WHERE子句
本文关键字:WHERE 子句 分解 IQueryable | 更新日期: 2023-09-27 18:09:55
我恢复了一些意大利面条代码,我必须重构它。我不想要一个超过200行的方法,对我来说它不是面向对象的编程。我正在考虑这个问题,想听听你的建议。
这是我的代码:
第18行
if (searchCriteria.EventReference != null)
{
query = query.Search(x = > x.EventReference, searchCriteria.EventReference);
}
if (searchCriteria.PendingEvent == false)
{
query = query.Where(x = > x.EventStatusId != EventStatus.Pending);
}
if (searchCriteria.VerifiedEvent == false)
{
query = query.Where(x = > x.EventStatusId != EventStatus.Verified);
}
if (searchCriteria.CanceledEvent == false)
{
query = query.Where(x = > x.EventStatusId != EventStatus.Canceled);
}
第237行
if (searchCriteria.RemitterId != null)
{
query = query.Where(x = > x.Trade.RemitterId == searchCriteria.RemitterId);
}
这个对我来说似乎是多余的(但我猜这是评论中出现的多态性),但无论如何,它就是:
我们从接口开始:
public interface IQueryFilter
{
IQueryable<Whatever> Filter(IQueryable<Whatever> query, SearchCriteria searchCriteria);
}
然后实现公共属性:
public abstract class AQueryFilter<T> : IQueryFilter
{
public AQueryFilter(Func<SearchCriteria, T> criteria)
{
Criteria = criteria;
}
protected Func<SearchCriteria, T> Criteria { get; }
public abstract IQueryable<Whatever> Filter(IQueryable<Whatever> query, SearchCriteria searchCriteria);
}
最后,所有具体的东西:
public class WhereEventStatusQueryFilter : AQueryFilter<bool>
{
private EventStatus _toTest;
public WhereEventStatusQueryFilter(Func<SearchCriteria, bool> criteria, EventStatus toTest)
: base(criteria)
{
_toTest = toTest;
}
public override IQueryable<Whatever> Filter(IQueryable<Whatever> query, SearchCriteria searchCriteria)
{
return (Criteria(searchCriteria) ? query : query.Where(x => x.EventStatusId != _toTest));
}
}
public class SearchQueryFilter : AQueryFilter<object>
{
Func<Whatever, object> _searchFor;
public SearchQueryFilter(Func<SearchCriteria, object> criteria, Func<Whatever, object> searchFor)
: base(criteria)
{
_searchFor = searchFor;
}
public override IQueryable<Whatever> Filter(IQueryable<Whatever> query, SearchCriteria searchCriteria)
{
return (Criteria(searchCriteria) == null ? query : query.Search(x => _searchFor(x), Criteria(searchCriteria)));
}
}
public class WhereEqualQueryFilter : AQueryFilter<object>
{
Func<Whatever, object> _searchFor;
public WhereEqualQueryFilter(Func<SearchCriteria, object> criteria, Func<Whatever, object> searchFor)
: base(criteria)
{
_searchFor = searchFor;
}
public override IQueryable<Whatever> Filter(IQueryable<Whatever> query, SearchCriteria searchCriteria)
{
return (Criteria(searchCriteria) == null ? query : query.Where(x => _searchFor(x) == Criteria(searchCriteria)));
}
}
用法:
var filters = new IQueryFilter[]
{
new WhereEventStatusQueryFilter(x => x.PendingEvent, EventStatus.Pending),
new WhereEventStatusQueryFilter(x => x.VerifiedEvent, EventStatus.Verified),
new SearchQueryFilter(x => x.EventReference, x => x.EventReference),
new WhereEqualQueryFilter(x => x.RemittedId, x => x.Trade.RemittedId),
...
};
foreach (var filter in filters)
query = filter.Filter(query, searchCriteria);
但是这个解决方案隐藏了很多逻辑。如果有人想添加一些东西,他必须阅读所有以前的过滤器类,以了解是否已经有一个可以完成工作,或者他是否必须编写另一个。
嗯,我不认为这真的更好,但你可以这样做:
var searchDict = new Dictionary<Func<bool>, Func<IQueryable<?>>>()
{
{ () => searchCriteria.EventReference != null, query.Search(x = > x.EventReference, searchCriteria.EventReference) },
{ () => searchCriteria.VerifiedEvent == false, query.Where(x = > x.EventStatusId != EventStatus.Verified) },
{ () => searchCriteria.RemitterId != null, query.Where(x = > x.Trade.RemitterId == searchCriteria.RemitterId) },
...
};
foreach (var item in seachDict)
if (item.First())
query = item.Second();
或者(取决于你想在哪里以及如何创建你的字典):
var searchDict = new Dictionary<Func<SearchCriteria, bool>, Func<IQueryable<?>, IQueryable<?>>>()
{
{ c => c.EventReference != null, q => q.Search(x = > x.EventReference, searchCriteria.EventReference)},
{ c => c.VerifiedEvent == false, q => q.Where(x = > x.EventStatusId != EventStatus.Verified) },
{ c => c.RemitterId != null, q => q.Where(x = > x.Trade.RemitterId == searchCriteria.RemitterId) },
...
};
foreach (var item in seachDict)
if (item.First(searchCriteria))
query = item.Second(query);