2012-01-09 16 views
7

मैं वस्तुओं के कुछ वर्ग के लिए एक सरल सत्यापन प्रणाली बनाना चाहते, मूल रूप सेनिम्नलिखित नियम डिजाइन के लिए अन्य समाधान क्या हैं?

public interface IMyClassRule { 
    bool IsValid(MyClass obj, Context someAdditionalData) 
} 

नियमों की सूची ऑटो की खोज की डि ढांचे का उपयोग करने और पहले से नियत नहीं है।

मान लें कि मेरे पास VeryGeneralDefaultRuleAboutAllObjects : IMyClassRule और SpecificCaseWhenGeneralRuleDoesNotApply : IMyClassRule है। मैं इस समाधान को सामान्य तरीके से कैसे संभाल सकता हूं (मूल रूप से कुछ मामलों में किसी भी नियम द्वारा किसी भी नियम के ओवरराइड की इजाजत देता है)?

समाधान मैं माना:

  1. नियम या नियम के लिए सांख्यिक प्राथमिकता परिणाम

    प्रो: सरल समझते हैं और लागू करने के लिए।
    कॉन्ट्रा: मुझे मूल नियम की प्राथमिकता जानने/अनुमान लगाने की आवश्यकता होगी। स्पष्ट नहीं है कि प्राथमिकता पहले (1 या 1000) है? ऐसी स्थिति के लिए कुछ "देखभाल न करें" नियम परिणाम की आवश्यकता है जहां विशिष्ट मामला लागू नहीं होता है।

  2. प्रकार आधार पर प्राथमिकता (मूल रूप से .Before<VeryGeneralRule>)

    प्रो: विशेष रूप से घोषणा करता है कि आप क्या हासिल करना चाहते हैं।
    कॉन्ट्रा: मूल नियम के स्पष्ट संदर्भ की आवश्यकता है। ऑर्डरिंग तर्क जटिल होगा। ऐसी स्थिति के लिए कुछ "देखभाल न करें" नियम परिणाम की आवश्यकता है जहां विशिष्ट मामला लागू नहीं होता है।

क्या कोई अन्य/बेहतर विकल्प हैं?

+1

बहुत कष्टप्रद समस्या। मैंने घंटों तक इस पर बहस की है, और एक संतोषजनक समाधान नहीं आया है। – CodesInChaos

+2

ऑटो-डिस्कवरी छोड़ने और प्राथमिकता क्रम में मैन्युअल रूप से नियमों की केंद्रीय सूची बनाने पर विचार करें। – CodesInChaos

+0

वेब नियम (http://rule.codeeffects.com) की अवधारणा को देखें। मुझे लगता है कि आप जो कुछ करते हैं उसके समान कुछ ढूंढ रहे हैं। – Kizz

उत्तर

0

नियम उदाहरणों में कुछ शर्तों को इंजेक्ट करने की क्षमता जोड़ने के बारे में, उदाहरण के लिए, IRuleApplicability इंटरफ़ेस के उदाहरण। आप इसे # 2 के समान कुछ जोड़ सकते हैं, और नियम लागू करने से पहले प्रयोज्यता की जांच के लिए सभी नियमों की आधार श्रेणी का उपयोग कर सकते हैं।

2

मुझे लगता है कि यह बहुत से परियोजना के दायरे पर निर्भर करेगा और आपको कितनी कम आवश्यकता होगी। मैं व्यवसाय के नियमों के आसपास बहुत सारे काम करता हूं, और उन्हें यथासंभव एक्स्टेंसिबल होने की आवश्यकता है। अगर नियमों की थोड़ी सी मात्रा भी हो, तो मैं खुद को एक सामान्य नियम प्रणाली से नहीं जोड़ूंगा, या उनका आदेश भी दूरस्थ रूप से जटिल है। मुझे लगता है कि नियमों की ऑटो-डिस्कवरी/वायरिंग पूरी तरह से यहां जाने का तरीका है।

मेरी राय में, इस तरह की स्थिति की कुंजी यह है कि सामान्य मामले के नियम उनके दायरे से संबंधित तर्क की अनुपस्थिति से परिभाषित नहीं हैं। सामान्य केस नियमों में विशिष्ट केस नियमों के समान विशिष्ट दायरे तर्क होना चाहिए। वे 100 गुना में से 99 गुना हो सकते हैं, लेकिन उन्हें अभी भी विशिष्ट स्कोप तर्क होना चाहिए।

निम्नलिखित है कि मैं इस बात से कैसे संपर्क करूंगा। मैं इनरस्कोप() से सीधे रोमांचित नहीं हूं, लेकिन सीधे आप एक साधारण सूची पर विचार कर रहे हैं, मुझे लगता है कि तर्क या तो प्रबंधनीय और अपेक्षाकृत स्थैतिक है, या आप उस तर्क के लिए एक प्रतिनिधि को इंजेक्ट कर सकते हैं।

फ्रेमवर्क इंटरफेस

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; 
    } 
} 

आईओसी तारों (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<>)); 
     }); 
    } 
} 
+0

मैंने हाल ही में ऐसा कुछ लागू किया है जो इस तरह से बहुत अधिक दिखता है, (अधिक) परिष्कृत संरचना मैप वायरिंग को घटाता है। मुझे यह जवाब पसंद है क्योंकि यह मान्य करता है कि मैंने जो किया है वह कम से कम एक अन्य व्यक्ति द्वारा समुदाय में देखा जाता है। –

संबंधित मुद्दे