2012-07-04 13 views
8

शायद यह आसान है, लेकिन यह इंटरनेट पर खोज कर पहले से ही मुझे एक सिर दर्दकैसल विंडसर - कैसे निर्माता इंजेक्शन नाम दिया गया है उदाहरण मैप करने के लिए

यहाँ समस्या है दे:

interface IValidator 
{ 
    void Validate(object obj); 
} 

public class ValidatorA : IValidator 
{ 
    public void Validate(object obj) { } 
} 

public class ValidatorB : IValidator 
{ 
    public void Validate(object obj) { } 
} 


interface IClassA { } 
interface IClassB { } 

public class MyBaseClass 
{ 
    protected IValidator validator; 

    public void Validate() 
    { 
     validator.Validate(this); 
    } 
} 

public class ClassA : MyBaseClass, IClassA 
{ 
    //problem: validator should ValidatorA 
    public ClassA(IValidator validator) { } 
} 

public class ClassB : MyBaseClass, IClassB 
{ 
    //problem: validator should ValidatorB 
    public ClassB(IValidator validator) { } 
} 

public class OtherClass 
{ 
    public OtherClass(IClassA a, IClassB b) { } 
} 


//on Main 
var oc = container.Resolve<OtherClass>(); 

किसी भी विचार?

संपादित

मैं Named साथ ValidatorA और ValidatorB पंजीकृत, अब समस्या यह है कि महल विंडसर ClassA और ClassB करने के लिए उन सत्यापनकर्ता ठीक से इंजेक्षन कर सकते हैं, वहाँ है कि करने के लिए एक तरीका है? या कोई बेहतर समाधान है?

अगर कोई सोचता है कि मेरी कक्षा का डिज़ाइन गलत है, तो मैं किसी भी सलाह के लिए खोलता हूं। अब तक मुझे लगता है कि यह सही है। हां, वैधकर्ता के पास विशिष्ट वर्ग के लिए विशिष्ट विन्यास है। लेकिन इसके कारण हैं:

  1. वैलिडेटर एक जटिल वस्तु है, कभी-कभी डेटाबेस से कनेक्ट होना चाहिए, इसलिए मुझे यूनिट परीक्षण कारण के लिए कन्स्ट्रक्टर के कार्यान्वयन के बजाय इंटरफ़ेस पास करना होगा।
  2. कोई रास्ता नहीं सत्यापनकर्ता से किसी के लिए अलग इंटरफेस का उपयोग करने, क्योंकि एकमात्र तरीका है कि मैं का इस्तेमाल किया Validate
  3. है मुझे लगता है कि MyBaseClass.Validate() एक आम टेम्पलेट विधि पैटर्न नहीं है यह?
+2

समस्या का आपका विवरण सार तत्व है। –

+2

यदि कक्षा ए को IValidator के विशिष्ट कार्यान्वयन की आवश्यकता है, तो डिज़ाइन गलत है, क्योंकि इंटरफ़ेस कोई उपयोगी अमूर्तता प्रदान नहीं करता है। –

+0

@ जेसेक ग्रोगन, मुझे केवल 'मान्य' विधि की आवश्यकता नहीं है, वास्तव में क्लास और क्लासबी का बेसक्लास है जिसे 'मान्य' विधि कहा जाता है। लेकिन मैं इसे जटिलता को छिपाने के लिए यहां नहीं लिखता हूं। – ktutnik

उत्तर

9

अपनी चुनी वास्तुकला बस विंडसर कंटेनर विन्यास पर ध्यान केंद्रित कर के विवरण में जाने के बिना:

आप किसी दिए गए इंटरफ़ेस (IValidator), आप जो आप उपयोग करना चाहते हैं निर्दिष्ट कर सकते हैं करने के लिए कई नामित कार्यान्वयन पंजीकृत हैं, तो एक 012 के साथ एक ValidatorA और ClassB उदाहरण के साथ

निम्नलिखित कंटेनर विन्यास प्रदाताओं ClassA उदाहरण के साथ एक OtherClass: जब ServiceOverrides उपयोग करने के साथ उपभोक्ता वर्गों (ClassA, ClassB) दर्ज की:

var container = new WindsorContainer(); 

container.Register(Component.For<IClassA>().ImplementedBy<ClassA>() 
    .DependsOn(ServiceOverride.ForKey<IValidator>().Eq("ValidatorA"))); 
container.Register(Component.For<IClassB>().ImplementedBy<ClassB>() 
    .DependsOn(ServiceOverride.ForKey<IValidator>().Eq("ValidatorB"))); 

container.Register(Component.For<IValidator>().ImplementedBy<ValidatorA>() 
    .Named("ValidatorA")); 
container.Register(Component.For<IValidator>().ImplementedBy<ValidatorB>() 
    .Named("ValidatorB")); 

container.Register(Component.For<OtherClass>().ImplementedBy<OtherClass>()); 

var oc = container.Resolve<OtherClass>(); 
+0

धन्यवाद, मैं यही चाहता हूं। मामला समाप्त – ktutnik

1

ऐसा लगता है कि आप तंग जोड़ों (ClassAValidatorA, ClassB साथ ValidatorB के साथ) एक आम कंटेनर में स्वतंत्र प्रकार के रूप में डाल करने के लिए कोशिश कर रहे हैं। यह निराधार है। यदि आपको इस तरह तंग युग्मन पर भरोसा करना चाहिए, तो इस संबंध में निर्भरता इंजेक्शन को भूलें और केवल प्रकारों को संदर्भित करें।

यदि आप सभी वर्गों के लिए एक सामान्य वैधकर्ता को कार्यान्वित कर सकते हैं तो इससे अधिक समझदारी होगी। उदाहरण के लिए, सत्यापन नियम प्रदान करने के लिए कक्षाएं जिम्मेदार बनाएं, और Validator नियमों को लागू करें। या शायद अपनी कक्षाओं के अंदर पूरी मान्यता शामिल करें, जो शायद यहां सबसे समझदार परिदृश्य है।

MyBaseClass.Validate() नियंत्रण में उलझन की तरह दिखता है, लेकिन टेम्पलेट विधि की तरह नहीं।

+0

प्रतिक्रिया के लिए धन्यवाद, हाँ कक्षा कक्षा थी, लेकिन प्रक्रिया दोहराई गई है, वास्तव में 'MyBaseClass.Validate() 'में कार्य हैं: 1.' validator.Validate (this) ', 2. प्रेषण से त्रुटियां प्राप्त करें। 'DataErrorEvent' 3.' HasError' प्रॉपर्टी बदलें, (Thats क्यों मैं इसे tempalte विधि कहते हैं) उन सभी कार्यों को एसिंक्रोन तरीके से किया जाना चाहिए। प्रत्येक कक्षा और कक्षा बी में इसे करने का बुरा विचार होगा? – ktutnik

+0

यदि ऐसा है तो '' मान्य करें() '' वास्तव में टेम्पलेट विधि है। फिर भी, घटक विधि क्यों न डालें, '' कक्षा 'में '' वैधता' यदि यह दोहराया गया है, तो इसे 'MyBaseClass'' में रखें। 'वैलिडेटर' वर्ग निकालने से अधिक जटिलता और बाधा स्पष्टता बढ़ जाती है। –

+0

यदि मैं msitaken नहीं हूं, तो आप 'क्लासए' के ​​अंदर 'वैलिडेटर ए' को तत्काल चालू कर सकते हैं और नई विधि 'ValidateCore' बना सकते हैं, फिर 'MyBaseClass.Validate()' दाएं से' ValidateCore 'को कॉल करें। मुझे लगता है कि मैं ऐसा नहीं कर सकता क्योंकि यूनिट परीक्षण करना असंभव होगा जहां किसी भी मामले में 'ValidatorA' या' ValidatorB' डेटाबेस से कनेक्ट होना चाहिए। – ktutnik