2010-07-07 18 views
7

पर उठाया गया है मैं एक अंतरफलक iStore रूप में परिभाषित किया, दो तरीकों के साथ है:सी # - इंटरफेस/सार वर्ग - घटना सुनिश्चित विधि

public interface IStore<TEntity> 
{ 
    TEntity Get(object identifier); 
    void Put(TEntity entity); 
} 

मैं चाहता हूँ एक घटना रखो की सफलता पर उठाया जा (के लिए संदर्भ, रखें एक DB में एक पंक्ति की दुकान सकता है, या फाइल सिस्टम आदि पर फ़ाइल ...)

तो, एक वर्ग उत्पाद के प्रकार के लिए iStore को लागू करने के लिए इस तरह एक सा दिखेगा:

class MyStore : IStore<Product> 
{ 
    public Product Get(object identifier) 
    { 
     //whatever 
    } 

    public void Put(Product entity) 
    { 
     //Store the product in db 
     //RAISE EVENT ON SUCCESS 
    } 
} 

मैं क्या कर रहा हूं, यह सुनिश्चित करने का एक तरीका है कि आईएसटीओआर के हर कार्यान्वयन ने घटना को बढ़ाया - क्या मेरे पास इसके बजाय एक अमूर्त वर्ग होना चाहिए, या साथ ही इंटरफेस भी होना चाहिए?

उत्तर

9

मेरे सुझाव:

public abstract class Store<TEntity> 
{ 
    public abstract TEntity Get(object identifier); 
    public void Put(TEntity entity) 
    { 
     //Do actions before call 
     InternalPut(entity); 
     //Raise event or other postprocessing 
    } 

    protected abstract void InternalPut(TEntity entity); 
} 

तो अपनी कक्षा में InternalPut ओवरराइड

+1

यह मेरा जवाब होने वाला था। कुछ स्तर पर, जब आप विधियों को ओवरराइड करने की अनुमति देते हैं तो आप हमेशा अनुबंध को समझने वाले लोगों पर निर्भर रहते हैं। लेकिन इस तरह एक ढांचा प्रदान करने से आप आदेशों के बारे में कुछ नियंत्रण करने की अनुमति देते हैं। – unholysampler

1

हाँ, आप एक अमूर्त वर्ग के बजाय एक इंटरफेस का उपयोग करना चाहिए।

आप अपने इंटरफेस को लागू करने एक अमूर्त वर्ग का उपयोग करने का निर्णय लेते हैं, यह इंटरफेस है, जो अंततः घटना से आगे नहीं बढ़ेगी के अपने स्वयं के संस्करण को लागू करने से अन्य developpers नहीं रोकेगा।

कहा जा रहा है, यहां तक ​​कि एक अमूर्त वर्ग का उपयोग कर, अपने विधि का उपयोग करने के लिए अन्य developpers मजबूर नहीं होगा के रूप में वे इसे अधिलेखित सकता है।

मुझे लगता है कि सबसे अच्छा तरीका एक टेम्पलेट विधि का उपयोग करने होगा:

public abstract class AbstractStore<TEntity> 
{ 
    public TEntity Get(object identifier); 
    public sealed void Put(TEntity entity) 
    { 
     if (DoPut(entity)) 
     { 
      // raise event 
     } 
    } 

    protected abstract bool DoPut(TEntity entity); 
} 

असली दुकान DoPut विधि लागू करने के लिए, एक बूलियन यदि रखें आपरेशन सफल रहा था यह दर्शाता है लौटने होगा। घटना पुट विधि से उठाई जाएगी, जो सार्वजनिक रूप से दिखाई दे रही है।

+0

यह व्यवहार को ओवरराइड करने से कक्षाओं को विरासत में नहीं रोकता है, या तो। इस व्यवहार की गारंटी देने का कोई वास्तविक तरीका नहीं है। –

3

वास्तव में यह सुनिश्चित करना कि iStore के हर कार्यान्वयन एक घटना को जन्म देती है का कोई रास्ता नहीं है। आपके पास एक अमूर्त वर्ग हो सकता है जिसमें पुल विधि हो, लेकिन इसका अभी भी मतलब यह नहीं है कि आप अमूर्त वर्ग के उप-वर्ग में एक पुट विधि रख सकते हैं जो पूरी तरह से अमूर्त वर्ग की विधि को अनदेखा करता है।

अंत में, को को प्रोत्साहित करने का सबसे अच्छा तरीका घटना को बढ़ाने के लिए डेवलपर को एक अमूर्त वर्ग के माध्यम से उपयोग करने के तरीके को लिखना है। इस तरह, वे अपने रास्ते से हट जाना है नहीं उपयोग करने के लिए यह

2

आप रखो विधि को लागू करने अमूर्त वर्ग की आवश्यकता है अपने इंटरफेस से। इसके अलावा, आप इस तरह PutImpl की तरह अमूर्त विधि, कुछ जोड़ सकते हैं:

public abstract class MyStoreBase : IStore<TEntity> 
{ 
    public abstract TEntity Get(object identifier); 

    public abstract void PutImpl(TEntity entity); 

    public void Put(TEntity entity) 
    { 
     // Each inheritor will implement this method. 
     PutImpl(entity); 

     // But event is fired in base class. 
     FireEvent(); 
    } 
} 
0

तुम सच में एक अंतरफलक का उपयोग करने के, तो नए PostSharp 2 पहलू विरासत क्या कर सकते हैं की जरूरत है। दुर्भाग्य से, उस सुविधा को पाने के लिए आपको $ 200 पर कम से कम एक व्यक्तिगत लाइसेंस खरीदने की आवश्यकता है।

इस तरह के एक पहलू के साथ

, आप इसे विधि अपने इंटरफेस में घोषित पर जगह होता है, और अपने इंटरफेस के सभी कार्यान्वयन यह वारिस होगा।

0
abstract class Store<TEntity> 
{ 
    public abstract TEntity Get(object identifier); 
    protected abstract void Put(TEntity entity); 
    public void PutBase(TEntity entity) 
    { 
     Put(entity); 
     //Raise event here 
    } 

} 

कुछ टिप्पणी: मैं के रूप में तो संरक्षित सभी व्युत्पन्न वर्ग इसे लागू करना होगा, लेकिन एक ग्राहक कोड यह आह्वान नहीं कर सकते हैं रखो था।

0

PutInner -like विधि को लपेटने के लिए एक अमूर्त वर्ग लिखना इस तरह से संपर्क करने का बिल्कुल सही तरीका है, जैसा कि अन्य ने पहले ही सुझाव दिया है।

मैं सिर्फ जोड़ना होगा कि यदि आप IStore<TEntity>बढ़ाने के लिए हमेशा एक घटना के किसी भी लागू करने के लिए चाहते हैं जब Put कहा जाता है, मैं भी सिफारिश करेंगे इंटरफेस से कहा घटना जोड़ने:

public interface IStore<TEntity> 
{ 
    event EventHandler<EntityEventArgs<TEntity>> EntityAdded; 

    TEntity Get(object identifier); 
    void Put(TEntity entity); 
} 

public EntityEventArgs<TEntity> : EventArgs 
{ 
    public TEntity Entity { get; set; } 
} 

यह नहीं करता है टी बल कुछ भी करने के लिए कार्यान्वयनकर्ता; लेकिन यह स्पष्ट रूप से एक उम्मीद स्थापित करता है कि EntityAdded सफल Put पर उठाया जाएगा।

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