我想這很大程度上取決於項目的範圍,以及您需要的鬆散耦合程度。我在業務規則方面做了很多工作,他們需要儘可能地擴展。如果規則數量微乎其微,或者它們的排序甚至非常複雜,我都不會將自己與有序的規則系統聯繫起來。我認爲規則的自動發現/佈線絕對是這裏的方法。
在我看來,這種情況的關鍵是,一般情況下的規則是而不是,這是由於缺少與其範圍相關的邏輯定義的。一般案例規則必須具有與特定案例規則相同的範圍邏輯。他們可能在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