我想这很大程度上取决于项目的范围,以及您需要的松散耦合程度。我在业务规则方面做了很多工作,他们需要尽可能地扩展。如果规则数量微乎其微,或者它们的排序甚至非常复杂,我都不会将自己与有序的规则系统联系起来。我认为规则的自动发现/布线绝对是这里的方法。
在我看来,这种情况的关键是,一般情况下的规则是而不是,这是由于缺少与其范围相关的逻辑定义的。一般案例规则必须具有与特定案例规则相同的范围逻辑。他们可能在100次的范围内99次,但他们仍然需要具有特定的范围逻辑。
以下是我如何处理这个问题。我并不满意将WithinScope()直接附加到IRule,但考虑到您正在考虑一个序列列表,我假设这个逻辑要么是可管理的,要么是相对静态的,或者您可以为该逻辑注入一个委托。
框架接口
public interface IRule<in T>{
bool IsValid(T obj);
bool WithinScope();
}
public interface IValidator<in T>{
bool IsValid(T obj);
}
public interface IRuleFactory<in T>{
IEnumerable<IRule<T>> BuildRules();
}
通用验证和规则厂
public class GenericValidator<T> : IValidator<T>
{
private readonly IEnumerable<IRule<T>> _rules;
public GenericValidator(IRuleFactory<T> ruleFactory){
_rules = ruleFactory.BuildRules();
}
public bool IsValid(T obj){
return _rules.All(p => p.IsValid(obj));
}
}
public class GenericRuleFactory<T> : IRuleFactory<T>
{
private readonly IEnumerable<IRule<T>> _rules;
public GenericRuleFactory(IEnumerable<IRule<T>> rules){
_rules = rules;
}
public IEnumerable<IRule<T>> BuildRules(){
return _rules.Where(x => x.WithinScope());
}
}
样品规则
public class VeryGeneralDefaultRuleAboutAllObjects : IRule<IMyClass>
{
private readonly Context _context;
public VeryGeneralDefaultRuleAboutAllObjects(Context context){
_context = context;
}
public bool IsValid(IMyClass obj){
return !obj.IsAllJackedUp;
}
public bool WithinScope(){
return !_context.IsSpecialCase;
}
}
public class SpecificCaseWhenGeneralRuleDoesNotApply : IRule<IMyClass>
{
private readonly Context _context;
public VeryGeneralDefaultRuleAboutAllObjects(Context context){
_context = context;
}
public bool IsValid(IMyClass obj){
return !obj.IsAllJackedUp && _context.HasMoreCowbell;
}
public bool WithinScope(){
return _context.IsSpecialCase;
}
}
IoC的接线(使用StructureMap)
public static class StructureMapBootstrapper
{
public static void Initialize()
{
ObjectFactory.Initialize(x =>
{
x.Scan(scan =>
{
scan.TheCallingAssembly();
scan.AssembliesFromApplicationBaseDirectory();
scan.AddAllTypesOf(typeof (IRule<>));
});
x.For(typeof(IValidator<>))
.Use(typeof(GenericValidator<>));
x.For(typeof(IRuleFactory<>))
.Use(typeof(GenericRuleFactory<>));
});
}
}
非常恼人的问题。我已经讨论了这个问题几个小时了,还没有找到一个令人满意的解决方案。 – CodesInChaos 2012-01-09 23:00:41
考虑放弃自动发现并按优先级顺序手动创建中央规则列表。 – CodesInChaos 2012-01-09 23:27:42
看看Web规则的概念(http://rule.codeeffects.com)。我认为你正在寻找类似于他们所做的事情。 – Kizz 2012-01-09 23:35:42