在我的项目中;我已经包含了下面给出的特定模式类。我不知道如何实现这一点。这些代码包含在之前的开发人员中。
public interface ISpecification<T>
{
Expression<Func<T, bool>> SpecExpression { get; }
bool IsSatisfiedBy(T obj);
}
public static class IExtensions
{
public static ISpecification<T> And<T>(
this ISpecification<T> left,
ISpecification<T> right)
{
return new And<T>(left, right);
}
public static ISpecification<T> Or<T>(
this ISpecification<T> left,
ISpecification<T> right)
{
return new Or<T>(left, right);
}
public static ISpecification<T> Negate<T>(this ISpecification<T> inner)
{
return new Negated<T>(inner);
}
}
public abstract class SpecificationBase<T> : ISpecification<T>
{
private Func<T, bool> _compiledExpression;
private Func<T, bool> CompiledExpression
{
get { return _compiledExpression ?? (_compiledExpression = SpecExpression.Compile()); }
}
public abstract Expression<Func<T, bool>> SpecExpression { get; }
public bool IsSatisfiedBy(T obj)
{
return CompiledExpression(obj);
}
}
public class And<T> : SpecificationBase<T>
{
ISpecification<T> left;
ISpecification<T> right;
public And(
ISpecification<T> left,
ISpecification<T> right)
{
this.left = left;
this.right = right;
}
// AndSpecification
public override Expression<Func<T, bool>> SpecExpression
{
get
{
var objParam = Expression.Parameter(typeof(T), "obj");
var newExpr = Expression.Lambda<Func<T, bool>>(
Expression.AndAlso(
Expression.Invoke(left.SpecExpression, objParam),
Expression.Invoke(right.SpecExpression, objParam)
),
objParam
);
return newExpr;
}
}
}
public class Or<T> : SpecificationBase<T>
{
ISpecification<T> left;
ISpecification<T> right;
public Or(
ISpecification<T> left,
ISpecification<T> right)
{
this.left = left;
this.right = right;
}
// OrSpecification
public override Expression<Func<T, bool>> SpecExpression
{
get
{
var objParam = Expression.Parameter(typeof(T), "obj");
var newExpr = Expression.Lambda<Func<T, bool>>(
Expression.OrElse(
Expression.Invoke(left.SpecExpression, objParam),
Expression.Invoke(right.SpecExpression, objParam)
),
objParam
);
return newExpr;
}
}
}
public class Negated<T> : SpecificationBase<T>
{
private readonly ISpecification<T> _inner;
public Negated(ISpecification<T> inner)
{
_inner = inner;
}
// NegatedSpecification
public override Expression<Func<T, bool>> SpecExpression
{
get
{
var objParam = Expression.Parameter(typeof(T), "obj");
var newExpr = Expression.Lambda<Func<T, bool>>(
Expression.Not(
Expression.Invoke(this._inner.SpecExpression, objParam)
),
objParam
);
return newExpr;
}
}
}
如何用一个简单的例子来实现上述规范?这个规范有什么用?
答案 0 :(得分:0)
正如我在评论中写的那样,这是借助Expression
实现的规范模式。
假设我们有以下域模型:
public class Person
{
public string Name { get; set; }
public DateTime BirthDate { get; set; }
public string Country { get; set; }
}
而且,我们还列出了这些:
List<Person> persons; // <-- initialized elsewhere
现在我们可以有两个规格。让那些住在Spain
的人和一个住在01/01/2000
public class SpainSpec : SpecificationBase<Person>
{
public override Expression<Func<Person, bool>> SpecExpression => person => person.Country == "Spain";
}
public class BornBefore2000 : SpecificationBase<Person>
{
public override Expression<Func<Person, bool>> SpecExpression => person => person.BirthDate < DateTime.Parse("2000-01-01");
}
现在我们可以用它来找到2000年以前出生的所有人:
ISpecification spec = new SpainSpec();
persons.Where (spec.IsSatisfiedBy);
你可以将他们联系起来,以便从2000年之前出生的西班牙人那里获得:
ISpecification spec = new SpainSpec().And(new BornBefore2000());
persons.Where (spec.IsSatisfiedBy);
这是一个非常简单的场景,你可以拥有更多,取决于你的模型和需求。
使用规格时要小心,这样你就不会失去对它的控制权,而且课程太多,或者发现自己正在重新发明轮子。