2012-03-09 19 views
5

बनाने के लिए मैं एक अमूर्त वर्ग सत्यापनकर्ता कहा जाता है:फैक्टरी सामान्य कक्षाओं

public abstract class Validator<T> where T : IValidatable 
{ 
    public abstract bool Validate(T input); 
} 

और मैं कुछ ठोस कार्यान्वयन है। एक AccountValidator है:

public class AccountCreateValidator : Validator<IAccount> 
{ 
    public override bool Validate(IAccount input) 
    { 
     //some validation 
    } 
} 

एक और LoginValidator होगा:

public class LoginValidator : Validator<IAccount> 
{ 
    public override bool Validate(IAccount input) 
    { 
     //some different validation 
    } 
} 

मैं अब एक कारखाने एक सत्यापनकर्ता कार्यान्वयन का एक उदाहरण वापस जाने के लिए बनाना चाहते हैं। कुछ की तरह:

public static class ValidatorFactory 
{ 
    public static Validator GetValidator(ValidationType validationType) 
    { 
     switch (validationType) 
     { 
      case ValidationType.AccountCreate: 
       return new AccountCreateValidator(); 
     } 
    } 
} 

मैं तो लाइन हालांकि यह (वापसी नई AccountCreateValidator पसंद नहीं है यह कैसा

Validator myValidator = ValidatorFactory.GetValidator(ValidationType.AccountCreate); 

फोन करने के लिए) चाहते हैं, या तथ्य यह है मैं के रूप में myValidator की घोषणा कर रहा हूँ वैलिडेटर और Validator<SomeType> नहीं। किसी भी मदद की सराहना की जाएगी।

+0

आपके पास जो कोड मिला है वह वर्तमान में अमान्य है - विधि का अंत पहुंच योग्य है। कृपया एक छोटा लेकिन पूरा कार्यक्रम दिखाएं जो समस्या का प्रदर्शन करता है। –

+0

क्या आप एनम पर आधारित 'IValidatable' के प्रकार के आधार पर एक वैधकर्ता नहीं प्राप्त करेंगे? तो फिर तुम एक 'सत्यापनकर्ता ' लौट सकते हैं और 'GetValidator' विधि में एक' T' लेने के लिए और '' T' IValidatable' –

+0

'वर्ग सत्यापनकर्ता का होना जहां टी प्रतिबंधित किया जा सकता है: IValidatable', आपको लगता है कि नहीं है बस 'कक्षा सत्यापनकर्ता: IValidatable' चाहते हैं? – vulkanino

उत्तर

2

ऐसा लगता है कि आप एक ठोस सत्यापन कार्यान्वयन में एक enum तर्क का अनुवाद करने के लिए कारखाने का उपयोग कर रहे हैं। लेकिन मैं कल्पना करता हूं कि हालांकि कॉलर वैधकर्ता के ठोस प्रकार के बारे में नहीं जानता या उसकी परवाह नहीं करता है, लेकिन संभवतः यह उस प्रकार को जानता है जिसे वह सत्यापित करना चाहता है। इसका मतलब यह चाहिए कि यह GetValidator विधि एक सामान्य विधि बनाने के लिए उचित है:

public static Validator<TypeToValidate> GetValidator<TypeToValidate>(ValidationType validationType) where TypeToValidate : IValidatable 
फिर

कोड बुला इस प्रकार दिखाई देगा: Validator<IAccount> validator = ValidatorFactory.GetValidator<IAccount>(ValidationType.AccountCreate)

+0

+1 यह एक बेहतर तरीका है, जब तक आप जानते हैं कि आप –

+0

को किस प्रकार सत्यापित करने जा रहे हैं, आप सही हैं, यह पर्याप्त है टाइप करें जिसे हम प्रमाणित करना चाहते हैं। क्या आप कृपया मुझे दिखा सकते हैं कि मैं एक वैधकर्ता का उदाहरण कैसे वापस करूँगा? आपके कोड में बदल गया है लेकिन संकलक मेरे रिटर्न स्टेटमेंट से खुश नहीं है: नया खाता क्रिएट वैलिडेटेटर(); – jfc37

+0

समस्या यह है कि आप एक वैधकर्ता लौट रहे हैं जो केवल किसी विशेष प्रकार के टाइपटॉलिडेट के लिए मान्य है। मुझे लगता है कि आप या तो इस फैक्ट्री को एक प्रकार के टाइपोवालिडेट के लिए बनाना चाहते हैं, यानी इसे एक अकाउंट वैलिडेटेटर फैक्ट्री बनाएं, या यदि आप इसे सामान्य बनाना चाहते हैं, तो पूरे कारखाने को टाइपटॉवालिडेट पर जेनेरिक बनाएं और प्रमाणीकरण टाइप वैल्यू के खिलाफ ठोस सत्यापनकर्ताओं को पंजीकृत करने के लिए एक तंत्र रखें । – Foo42

1

यदि आप इसे सामान्य रूप से जेनेरिक पैरामीटर निर्दिष्ट किए बिना इस्तेमाल किया जाना चाहते हैं तो आप एक गैर सामान्य इंटरफेस घोषित कर सकते हैं और आपको वैलिडेटर अमूर्त वर्ग को कार्यान्वित कर सकते हैं। इन पंक्तियों के साथ untested लेकिन कुछ:

public interface IValidator 
{ 
    bool Validate(object input); 
} 

public abstract class Validator<T> : IValidator where T : IValidatable 
{ 
    public abstract bool Validate(T input); 

    public bool Validate (object input) 
    { 
     return Validate ((T) input); 
    } 
} 

public static class ValidatorFactory 
{ 
    public static IValidator GetValidator(ValidationType validationType) 
    { 
     switch (validationType) 
     { 
      case ValidationType.AccountCreate: 
       return new AccountCreateValidator(); 
     } 
    } 
} 

तो यह कोड:

IValidator myValidator = ValidatorFactory.GetValidator(ValidationType.AccountCreate); 

ठीक काम करना चाहिए।

+1

के विरुद्ध मान्य होंगे बेहतर दिख रहे हैं, हालांकि संकलक शिकायत करता है कि वैलिडेटर IValidator को लागू नहीं करता है। वैध (ऑब्जेक्ट इनपुट) – jfc37

+0

मैंने उस समाधान के साथ उत्तर अपडेट किया, दुर्भाग्य से जब आप जेनेरिक छोड़ देते हैं पैरामीटर हर जगह परिभाषित किया गया है, तो आपको क्या करना होगा यदि आपको गलत प्रकार के तर्क के साथ बुलाया जाता है ... मुझे लगता है कि आपका समाधान इस बात पर निर्भर करेगा यदि आप जानते हैं कि कॉल साइट पर सत्यापन प्रकार क्या है। यदि आप करते हैं तो Foo42 का समाधान बेहतर होता है क्योंकि यह मजबूत टाइपिंग को बरकरार रखता है। यदि आप नहीं करते हैं तो आपको इस समाधान के साथ समझौता करना पड़ सकता है जैसे –

0

आम तौर पर मैं एक कारखाने जो एक के रूप में एक Type स्वीकार कर लिया होता पैरामीटर ताकि फैक्ट्री एक अद्वितीय व्युत्पन्न प्रकार का निर्माण करे। लेकिन क्योंकि आपके पास एकाधिक सत्यापनकर्ता हैं जो वैध करने के लिए उसी प्रकार की ऑब्जेक्ट को स्वीकार करते हैं (इस मामले में IAccount) मुझे लगता है कि आपको अपने कारखाने के लिए जेनेरिक पैरामीटर प्रदान करना होगा और साथ ही किस प्रकार का सत्यापनकर्ता बनाना होगा:

public static class ValidatorFactory 
{ 
    public static Validator<T> GetValidator<T>(ValidationType validationType) 
     where T : IValidatable 
    { 
     switch (validationType) 
     { 
      case ValidationType.AccountCreate: 
       return new AccountCreateValidator() as Validator<T>; 
        // etc... 
     } 
    } 
} 

मैं बुला की कोशिश की है:

var value = ValidatorFactory.GetValidator<IAccount>(ValidationType.AccountCreate) 

और यह अब सही Validator<IAccount> प्रकार के लिए एक AccountCreateValidator डाली देता है।

यह बिल्कुल आदर्श नहीं है क्योंकि अब आपको यह जानने की ज़रूरत है कि आप कौन सा वैधकर्ता चाहते हैं और यह किस इनपुट को स्वीकार करता है, लेकिन आपको स्पष्ट रूप से एक जटिल त्रुटि प्राप्त होनी चाहिए क्योंकि गलत इनपुट प्रकार को पार करने के कारण मैंने जोड़ा है, उदा। ValidatorFactory.GetValidator<IUser>(ValidationType.AccountCreate) विफल होना चाहिए।

संपादित करें: टिप्पणी की वजह से कह यह संकलन नहीं होगा, मैं new AccountCreateValidator() as Validator<T> के रूप में कास्ट करने के लिए ऊपर कोड स्निपेट संपादित किया है। मैंने सोचा कि इसे किसी भी तरह से डाला जा सकता है, लेकिन स्पष्ट रूप से नहीं (हालांकि यकीन नहीं है कि क्यों)। मैंने LINQPad में यह काम सत्यापित कर लिया है और मैं एक सत्यापनकर्ता से परिणाम प्राप्त कर सकता हूं।

मैं यह भी मानना ​​है संभवतः एक संकलन त्रुटि हो रही है, तो आप गलत सामान्य प्रकार में पारित के बारे में मेरी पिछली टिप्पणी नहीं रह गया है as कीवर्ड का उपयोग सिर्फ null वापसी होगी अगर यह यह करने में असमर्थ था कास्टिंग के रूप में खड़ा है।

+0

धन्यवाद लेकिन यह मुझे निम्न त्रुटि देता है: 'AccountCreateValidator' को 'Validator ' – jfc37

+0

में कनवर्ट नहीं किया जा सकता है, इसके बारे में क्षमा करें, इसे सुधारने के लिए मेरा उत्तर संपादित किया है –