Some Specification suggestions

Jan 21, 2009 at 2:38 PM
I've been implementing specifications myself, and have a couple of suggestions to make.

1. Make the specification base class abstract. This way the developer can decide if they want to provide a child class which allows a delegate to be passed into the constructor. Some people prefer that no ad-hoc specifications are allowed.
2. When returning the Func (not expression version) for execution, cache it locallly so you don't have to recompile. We keep singleton copies of our specs in IoC, and never have to recompile our expressions. e.g.
return _compiledPredicate ?? (_compiledPredicate = _predicate.Compile())(entity);
3. Add ISpecification<T0, T1>, ISpecification<T0, T1, T2> etc etc

keep up the good work!
Coordinator
Jan 27, 2009 at 1:36 PM
@mcintyre321:
I've modified the Specification class to store the compiled expression and use that for evaluation. The changes are in the trunk. [Rev: 30706]

As for making the Specification class abstract, you can do that right now by subclassing Specification<T> and providing a default ctor of :

public MySpecification(Func<T, bool> predicate) : base(new Expression<Func<T,bool>>(predicate) {}

Making the Specification class abstract or providing a abstract SpecificationBase class doesn't provide any added functionality over the current structure, it will lead to additional complexity though.

As for ISpecification<T0, T1> and so on, I havn't added that support yet as I'm trying to come up with alternatives that doesnt require multiple interfaces and multiple Specification implementations for those interfaces to accomodate multiple types. I may end up having to do what you suggested, but I'd rather do that as a last ditch effort :)

Jan 27, 2009 at 3:15 PM
Top banana!

The idea behind the abstract class is to stop people doing too many ad-hoc specifications using lambda and ending up duplicating existing code - while there exists the public Specification base class there is always the risk. I appreciate however this may not be a concern for everyone.

As far as the generic types go, I've created our project some FlattenedSpecification and ExpandedSpecification classes which can be used to add or remove a generic parameter, and And and Or extension methods that can be used to combine a Spec<T0> and a Spec<T0, T1> together for convenience. You're right it's not ideal though, how far should you go? Should you end up writing Specification<T0, ..., TN>?!? :)

e.g.
class ExpandedSpecification<T0, T1> : ISpecification<T0, T1>
{
private readonly ISpecification<T0> _spec;

public ExpandedSpecification(ISpecification<T0> spec)
{
_spec = spec;
}
public Func<T0, T1, bool>IsSatisfiedBy
{
get{
return (t0, t1) => _spec.IsSatisfiedBy(t0);
}
}
}
and this extension for combining two differently genericly typed paramters
public static ISpecification<T0, T1> And<T0, T1>(this ISpecification<T0> left, ISpecification<T0, T1> right)
{
return new AndSpecfication<T0, T1>(left.Expand<T0, T1>(), right);
}
Jan 31, 2009 at 6:40 PM
Is there a way to easily create a sub-class of Specification<T> that performs a well-known type of check? For example, what about a NotNullSpecification<T>, or a NotNullOrEmptySpecification<T>.

Something like:

var firstNameRequiredSpec = new NotNullOrEmptySpecification<Person>(p => p.FirstName);

I'm not quite sure how to go about writing this type of class given the current implementation. Is this possible?

Thanks