eye*_*aul 7 c# sorting pagination entity-framework specification-pattern
我已经选择了一个使用规范模式的项目,这是我之前没有使用的模式,我不得不去研究模式.我注意到它没有orderby和skip/take功能,我找不到任何显示如何用模式实现它的地方.
我正在努力思考如何最好地将其添加到规范模式中.但我遇到了问题,比如规范处理"表达式",而我认为我不能将它与orderby等一起存储
基本上有一个这样的类:
public class Specification<T> : ISpecification<T>
{
public Expression<Func<T, bool>> Predicate { get; protected set; }
public Specification(Expression<Func<T, bool>> predicate)
{
Predicate = predicate;
}
public Specification<T> And(Specification<T> specification)
{
return new Specification<T>(this.Predicate.And(specification.Predicate));
}
public Specification<T> And(Expression<Func<T, bool>> predicate)
{
return new Specification<T>(this.Predicate.And(predicate));
}
public Specification<T> Or(Specification<T> specification)
{
return new Specification<T>(this.Predicate.Or(specification.Predicate));
}
public Specification<T> Or(Expression<Func<T, bool>> predicate)
{
return new Specification<T>(this.Predicate.Or(predicate));
}
public T SatisfyingItemFrom(IQueryable<T> query)
{
return query.Where(Predicate).SingleOrDefault();
}
public IQueryable<T> SatisfyingItemsFrom(IQueryable<T> query)
{
return query.Where(Predicate);
}
}
Run Code Online (Sandbox Code Playgroud)
这允许创建一个规范,传入一个where子句.它还允许使用"And","Or"来链接规则.例如:
var spec = new Specification<Wave>(w => w.Id == "1").And(w => w.WaveStartSentOn > DateTime.Now);
Run Code Online (Sandbox Code Playgroud)
如何为"OrderBy"和"Take"添加方法?
由于这是现有代码,我不能做任何会影响现有代码的更改,重构它将是一项相当大的工作.所以任何解决方案都需要很好地发挥作用.
怎么样
public class Specification<T> : ISpecification<T>
{
public Expression<Func<T, bool>> Predicate { get; protected set; }
public Func<IQueryable<T>, IOrderedQueryable<T>> Sort {get; protected set; }
public Func<IQueryable<T>, IQueryable<T>> PostProcess {get; protected set;
public Specification<T> OrderBy<TProperty>(Expression<Func<T, TProperty>> property)
{
var newSpecification = new Specification<T>(Predicate) { PostProcess = PostProcess } ;
if(Sort != null) {
newSpecification.Sort = items => Sort(items).ThenBy(property);
} else {
newSpecification.Sort = items => items.OrderBy(property);
}
return newSpecification;
}
public Specification<T> Take(int amount)
{
var newSpecification = new Specification<T>(Predicate) { Sort = Sort } ;
if(PostProcess!= null) {
newSpecification.PostProcess= items => PostProcess(items).Take(amount);
} else {
newSpecification.PostProcess= items => items.Take(amount);
}
return newSpecification;
}
public Specification<T> Skip(int amount)
{
var newSpecification = new Specification<T>(Predicate) { Sort = Sort } ;
if(PostProcess!= null) {
newSpecification.PostProcess= items => PostProcess(items).Skip(amount);
} else {
newSpecification.PostProcess= items => items.Skip(amount);
}
return newSpecification;
}
}
Run Code Online (Sandbox Code Playgroud)
去做:
然后你的满意方法变成:
private IQueryable<T> Prepare(IQueryable<T> query)
{
var filtered = query.Where(Predicate);
var sorted = Sort(filtered);
var postProcessed = PostProcess(sorted);
return postProcessed;
}
public T SatisfyingItemFrom(IQueryable<T> query)
{
return Prepare(query).SingleOrDefault();
}
public IQueryable<T> SatisfyingItemsFrom(IQueryable<T> query)
{
return Prepare(query);
}
Run Code Online (Sandbox Code Playgroud)
TODO:检查"准备"方法中Sort&PostProcess是否为空
用法:
var spec = new Specification<Wave>(w => w.Id == "1")
.And(w => w.WaveStartSentOn > DateTime.Now)
.OrderBy(w => w.WaveStartSentOn)
.Skip(20)
.Take(5);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3257 次 |
| 最近记录: |