我想为某类对象制作一个简单的验证系统,基本上是
public interface IMyClassRule {
bool IsValid(MyClass obj, Context someAdditionalData)
}
使用DI框架自动发现规则列表,而不是事先修复。
假设我有VeryGeneralDefaultRuleAboutAllObjects : IMyClassRule
和SpecificCaseWhenGeneralRuleDoesNotApply : IMyClassRule
。如何以通用方式处理此解决方案(在某些情况下基本上允许通过任何其他规则覆盖任何规则)?
我考虑过的解决方案:
规则或规则结果的数字优先级
Pro :易于理解和实施 反对:我需要知道/猜测原规则的优先级。不明显哪个优先(1或1000)?对于特定情况不适用的情况,需要一些“不关心”的规则结果。
基于类型的优先级(基本上为.Before<VeryGeneralRule>
)
Pro :具体说明您想要达到的目标 Contra :需要明确引用原始规则。订购逻辑将很复杂。对于特定情况不适用的情况,需要一些“不关心”的规则结果。
还有其他/更好的选择吗?
答案 0 :(得分:2)
我认为这很大程度上取决于项目的范围以及您需要的松散耦合程度。我围绕业务规则做了很多工作,他们需要尽可能地扩展。如果有最轻微的规则,或者它们的排序甚至是非常复杂的话,我也不会把自己绑在一个有序规则系统上。我认为规则的自动发现/接线绝对是这里的方法。
在我看来,这种情况的关键在于,一般案例规则不是由缺少与其范围相关的逻辑定义的。一般案例规则必须具有与特定案例规则一样具体的范围逻辑。它们可能在100次中的范围99中,但它们仍然需要具有特定的范围逻辑。
以下是我接近这个的方法。我很不喜欢直接连接到IRule的WithinScope(),但考虑到你正在考虑一个序数列表,我假设逻辑是可管理的和相对静态的,或者你可以为该逻辑注入一个委托。
框架界面
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<>));
});
}
}
答案 1 :(得分:0)
如何在规则实例中添加注入某些条件的功能,例如IRuleApplicability
接口的实例。您可以将其与类似于#2的内容组合,并在应用规则之前使用所有规则的基类来检查适用性。