Penso che molto dipenderà dallo scopo del progetto e quanto si debba essere accoppiati liberamente. Lavoro molto sulle regole aziendali e devono essere il più estensibili possibile. Non mi legherei a un sistema di regole ordinali se c'è anche il minimo volume di regole, o il loro ordinamento è persino remotamente complesso. Penso che l'auto-scoperta/il cablaggio delle regole sia assolutamente il modo per andare qui.
La chiave per questo tipo di situazione, a mio avviso, è che le regole generali del caso sono non definite da un'assenza di logica correlata al loro ambito. Le regole del caso generale devono avere una logica dell'ambito tanto specifica quanto le regole del caso specifico. Possono essere inclusi 99 volte su 100, ma devono ancora avere una logica specifica per l'ambito.
Quanto segue è approssimativamente come mi avvicinerei a questo. Non sono entusiasta del fatto che WithinScope() sia collegato direttamente a IRule, ma dato che stai considerando una lista ordinale, presumo che la logica sia gestibile e relativamente statica, o che tu possa iniettare un delegato per quella logica.
Interfacce Framework
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();
}
Generico Validator e regola fabbrica
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());
}
}
regole di esempio
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 cablaggio (Usando 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<>));
});
}
}
fonte
2012-02-07 17:29:55
problema molto fastidioso. Ne ho discusso per ore e non ho trovato una soluzione soddisfacente. – CodesInChaos
Considerare di rinunciare all'individuazione automatica e creare manualmente un elenco centrale di regole in ordine di priorità. – CodesInChaos
Guarda il concetto di regola Web (http://rule.codeeffects.com). Penso che tu stia cercando qualcosa di simile a quello che fanno. – Kizz