我需要复杂的多类型 (<TLeft,TRight>)规范,如:
public class AndSopecification<TLeft,TRight>
{
public AndSpecification(ISpecification<TLeft> leftSide, ISpecification<TRight> rightSide)
{
}
.
.
.
}但是,我看到的所有规范示例都实现了单类型 (<T>),如:
public sealed class AndSpecification<T> : CompositeSpecification<T>
{
public AndSpecification(ISpecification<T> leftSide, ISpecification<T> rightSide)
{
}
.
.
.
}如果我创建复杂的规范(如:
new AndSpecification<Foo,Bar>(new FooSpecification(),new BarSpecification()).SatisfiedBy();因此,我可以在不同的情况下重用彼此内部的所有规范,然后我可以有一个唯一的流程点,它们可以是更复杂的规范树的组合单元。
但我找不到这样的实现。
我在正确的道路上吗?
编辑:
我正在将客户使用的每一个条件句翻译成一个specification,并在任何地方重用它们--客户重复使用这个句子
(在所有相关的logic、query predicate、business rule validation、.中,我认为这些specifications在每种情况下都是自然相同的)
和客户一样,我创建了composite specifications,
但在每一种情况下,我都使用不同的基础设施访问它们(query predicate,business rule validation,.)
发布于 2015-03-26 19:14:47
我有一个实现,在这里我可以执行以下操作,它使我能够根据自己的需要重用规范。
public class Composite
{
public Foo _foo;
public Bar _bar;
}
var fooSpec = new Specification<Foo>(f => f.IsActive);
var barSpec = new Specification<Bar>(f => f.IsActive);
var comSpec = new Specification<TheComposite>(c => true);
comSpec = comSpec.And(c => c.Foo, fooSpec)
.And(c => c.Bar, barSpec); 如果这就是你要找的,我就是这么做的。
public class Specification<TEntity>
{
private readonly Expression<Func<TEntity, bool>> _expression;
public static Specification<TEntity> Create<TNestedEntity>(Expression<Func<TEntity, TNestedEntity>> propertyExpression, ISpecification<TNestedEntity> spec)
{
var replacer = new ParameterReplaceVisitor(spec.EvalExpression.Parameters.First(), propertyExpression.Body);
var newExpression = replacer.Visit(spec.EvalExpression.Body);
var exp = Expression.Lambda<Func<TEntity, bool>>(newExpression, propertyExpression.Parameters);
return new Specification<TEntity>(exp);
}
public virtual bool IsSatisfiedBy(TEntity e)
{
return EvalFunc(e);
}
public ISpecification<TEntity> And(ISpecification<TEntity> other)
{
return new Specification<TEntity>(EvalExpression.And(other.EvalExpression));
}
public ISpecification<TEntity> And<TNestedEntity>(Expression<Func<TEntity, TNestedEntity>> property, ISpecification<TNestedEntity> spec)
{
return And(Create(property, spec));
}
...
}
private class ParameterReplaceVisitor : ExpressionVisitor
{
private readonly Expression _replacementExpression;
private readonly ParameterExpression _parameter;
public ParameterReplaceVisitor(ParameterExpression parameter, Expression replacementExpression)
{
_parameter = parameter;
_replacementExpression = replacementExpression;
}
protected override Expression VisitParameter(ParameterExpression node)
{
// If the node is the parameter we are trying to replace,
// return the expression that should replace it.
return (node == _parameter) ? _replacementExpression : node;
}
}ExpressionVisitor是System.Linq.Expressions的一部分
当然,您也可以实现或()
我希望这是你正在寻找的,这是有帮助的。
发布于 2016-01-13 11:46:50
创建一个与特定对象类型无关的规范会违背目的。Evans说:“规范是一个谓词,它决定一个对象是否满足某些条件。因此,您总是必须根据实例对规范进行评估。复合规范用于组合与同一类对象相关的规范。
规范与业务规则不是一回事。您可以有一个业务规则--使用多个规范。例句:如果顾客想买一辆大轿车,那么他需要在他的银行账户里存一些钱。
var bigCar = new Specification<Car>(car => car.Size == "big");
var accountHasMoney = new Specification<Account>(account => account.Balance > 0);
// This rule takes a car and an account
public bool CanBuyBigCar(Car car, Account account) {
return bigCar.IsSatisfiedBy(car) && accountHasMoney.IsSatisfiedBy(account)
}如果您想在sql查询中重用这些规范,那么可以使用隐式运算符,以便更容易地在IQueryables中使用:
public static implicit operator Expression<Func<T, bool>>(Specification<T> specification)
{
return specification.Expression;
}
public static implicit operator Func<T, bool>(Specification<T> specification)
{
return specification.IsSatisfiedBy;
}现在,规范可以由所有IQueryables、IEnumerables和所有其他类型的集合直接查询。
您可以在这里找到一个现成的实现:https://github.com/jnicolau/NSpecifications/tree/master/Nspecifications。
发布于 2019-10-25 13:18:24
我觉得搞不懂为什么您需要在多个类型上指定。但你没有理由不能这么做。从技术上讲,您可以使用元组规范。
var spec = new Spec<(int num, string text)>(x => x.num == 1 && x.text == "a");https://stackoverflow.com/questions/26439718
复制相似问题