2012-11-28 30 views
9

में आंतरिक संपत्ति सेटर्स मैं इस दृष्टिकोण के लिए एक अच्छा तरीका जानने की कोशिश कर रहा हूं। मेरे पास एक ग्राहक वर्ग है जो आईसी कस्टमर इंटरफ़ेस लागू करता है। इस इंटरफ़ेस में गुण की एक संख्या है:सी #

public interface ICustomer 
{ 

    string FirstName {get; set;} 
    string LastName {get; set;} 
} 

मैं केवल कुछ वर्गों लेकिन उन गुणों को सेट करने की क्षमता है करना चाहते हैं; अर्थात्, परियोजना में उन वर्गों। इसलिए मैं सेटर internal बनाने के बारे में सोचा:

public class Customer : ICustomer 
{ 

    string FirstName {get; internal set;} 
    string LastName {get; internal set;} 
} 

मैं इंटरफ़ेस तथापि में आंतरिक रूप में है कि सेटर को चिह्नित करना चाहते, इसलिए वहाँ कोई मौका नहीं किसी ICustomer लागू करता है और विधानसभा के बाहर किसी उन गुणों को संशोधित करता है। क्या ऐसा करने का कोई अच्छा तरीका है?

उत्तर

16

इंटरफ़ेस में गुण केवल पढ़ा जाना चाहिए। यह कंक्रीट क्लास के लिए स्वीकार्य है जो इंटरफ़ेस में कोई भी परिभाषित नहीं होने पर भी एक सेटटर रखने के लिए इंटरफ़ेस लागू करता है।

public interface ICustomer 
{ 
    string FirstName { get; } 
    string LastName { get; } 
} 

public class Customer : ICustomer 
{ 
    public string FirstName { get; internal set; } 
    public string LastName { get; internal set; } 
} 

यदि यह वास्तव में महत्वपूर्ण है कि सेटर, एक अंतरफलक के माध्यम से उजागर किया बल्कि इंटरफेस होने पूरी तरह से केवल पढ़ने के लिए है, तो आप कुछ इस तरह उपयोग कर सकते हैं किया जा रहा से है:

public interface IReadCustomer 
{ 
    string FirstName { get; } 
    string LastName { get; } 
} 

internal interface IWriteCustomer 
{ 
    string FirstName { set; } 
    string LastName { set; } 
} 

internal interface IReadWriteCustomer : IReadCustomer, IWriteCustomer 
{ } 

public class Customer : IReadWriteCustomer 
{ 
    private string _firstName; 
    private string _lastName; 

    public string FirstName 
    { 
     get { return _firstName; } 
     internal set { _firstName = value; } 
    } 
    public string LastName 
    { 
     get { return _lastName; } 
     internal set { _lastName = value; } 
    } 

    string IReadCustomer.FirstName 
    { 
     get { return FirstName; } 
    } 

    string IReadCustomer.LastName 
    { 
     get { return LastName; } 
    } 

    string IWriteCustomer.FirstName 
    { 
     set { FirstName = value; } 
    } 

    string IWriteCustomer.LastName 
    { 
     set { LastName = value; } 
    } 
} 
+0

सहायता के लिए धन्यवाद। अगर मैं ऐसा करता हूं, और उपभोग करने वाला वर्ग आईसी कस्टमर का उपयोग करता है तो यह सेटटर तक नहीं पहुंच सकता है। – larryq

+2

@larryq यह पूरा बिंदु है, क्योंकि इंटरफ़ेस सेटटर को नहीं कर रहा है। यदि आप एक दूसरा आंतरिक इंटरफ़ेस लागू करना चाहते हैं जो सेटटर जोड़ता है तो आप कर सकते हैं। मेरे पास अक्सर इंटरफ़ेस की एक श्रृंखला होती है: यह एक वास्तविक उदाहरण है: 'IDimensionedMap' केवल 2 डी इकाई के आयामों के लिए प्रतिबद्ध है; पठनीय गुणों के साथ 'आईआरएडमैप', 'आईआरएडमैप: आईडीमिनेटेड मैप' केवल पढ़ने या गणना किए गए मानचित्रों के लिए, और फिर 'IWriteMap: IReadMap'। लेकिन यह विस्तार योग्य उपयोगिता वर्गों का एक जटिल परिवार है। (ये 2 डी हिल्बर्ट रिक्त स्थान हैं, शब्दकोश नहीं, यदि आप उत्सुक हैं।) – SAJ14SAJ

+1

@larryq जबकि मुझे यकीन नहीं है कि आपको इसकी आवश्यकता है या नहीं, मैंने एक वैकल्पिक कार्यान्वयन जोड़ा है जिसमें इंटरफ़ेस एक आंतरिक सेट विधि को परिभाषित करता है। – Servy

6

मैं था इंटरफ़ेस में उस सेटटर को आंतरिक के रूप में चिह्नित करना पसंद है, इसलिए कोई भी मौका नहीं है कि कोई व्यक्ति आईसी कस्टमर लागू करता है और असेंबली के बाहर कोई व्यक्ति उन गुणों को संशोधित करता है। क्या ऐसा करने का कोई अच्छा तरीका है?

सं संपत्ति सदस्यों हमेशा सार्वजनिक कर रहे हैं, दुर्भाग्य से। इसके अतिरिक्त, उन गुणों पर पहुंच स्तर के साथ गड़बड़ करना जहां इंटरफेस पर इसका हिस्सा निर्दिष्ट है, दर्दनाक, आईआईआरसी।

public interface ICustomer 
{ 
    string FirstName { get; } 
    string SecondName { get; } 
} 

internal interface ICustomerWithSetMethods : ICustomer 
{ 
    void SetFirstName(string name); 
    void SetLastName(string name); 
} 

public class Customer : ICustomerWithSetMethods 

फिर बाहर से यह गौर करेंगे की तरह Customer केवल ICustomer लागू करता है, लेकिन से के अंदर अपना कोड है कि यह लागू करता ICustomerWithSetMethods देखेंगे: क्या आप क्या कर सकते हैं यह है।

दुर्भाग्य है कि अच्छी तरह से खेलने नहीं करता है कि आपके API भी सार्वजनिक तरीकों जहां की तरह सिर्फ ICustomer की वापसी प्रकार की घोषणा करने के वास्तव मेंचाहते घोषित करने के लिए की जरूरत है, लेकिन आप वास्तव में पता चल जाएगा कि यह हमेशा है ICustomerWithSetMethods

सकता है मान लिया जाये कि आप अभी भी एकाधिक कार्यान्वयन की अनुमति देना चाहते हैं, तो आप संभवतः के बजाय एक अमूर्त वर्ग के लिए जाना:

public abstract class CustomerBase 
{ 
    public abstract string FirstName { get; } 
    public abstract string LastName { get; } 

    internal abstract void SetFirstName(string name); 
    internal abstract void SetLastName(string name); 
} 

अब हम मामूली विषमता है कि विधानसभा के बाहर कोई अपने CustomerBase विस्तार कर सकते हैं, वहाँ क्योंकि सार तरीकों वे ओवरराइड करने के लिए है कि वे भी नहीं देख सकता होगा रहे हैं - लेकिन यह है कि आप अपने एपीआई में हर जगह CustomerBase उपयोग कर सकते हैं मतलब है।

यह दृष्टिकोण है कि हमने अंत में कैलेंडर सिस्टम के लिए Noda Time में लिया - I blogged about it जब मैं पहली बार योजना के साथ आया था। मैं आम तौर पर अमूर्त वर्गों के लिए इंटरफेस पसंद करते हैं, लेकिन यहां लाभ महत्वपूर्ण था।

+0

आपने फर्स्टनाम और सेकेंडनाम –

+0

@JonB पर प्रकार और दायरे को याद किया: तो मैंने किया। फिक्स्ड, धन्यवाद। –

+0

@ जोनस्केट मैं आपके दृष्टिकोण से सहमत हूं, लेकिन आम तौर पर समय के साथ बनाए रखने योग्यता के दौरान मैं इंटरफ़ेस और सार आधार दोनों कक्षाओं को लागू करता हूं। यह अतिरिक्त टाइपिंग का थोड़ा सा है, लेकिन Resharper जैसे टूल इसे आसान बनाते हैं, और इसका मतलब है कि आपके पास ऑब्जेक्ट्स का एक जटिल परिवार होने पर एक से अधिक अमूर्त कार्यान्वयन हो सकता है, शायद वह आपके कोड लाइब्रेरी के बाहर बढ़ाया जाएगा। – SAJ14SAJ