2014-09-18 8 views
5

कल्पना कीजिए कि आपके पास निम्नानुसार परिभाषित कक्षा है।सी # संदर्भ; सदस्यों को छिपाना

public class SomeClass 
{ 
    public Manager m { get; protected set; } 
    public SpecialData data { get; protected set; } 

    //More methods and member code here... 
} 

मुझे किसी भी तरह से मेरे प्रबंधक वर्ग की आवश्यकता है जो किसी विशेष रूप से स्पेशलडाटा सदस्य के लिए सेट संदर्भ को बदलने में सक्षम हो। मैं इसे C++ में डबल पॉइंटर या मित्र कक्षाओं के साथ कर सकता हूं, लेकिन यह विकल्प दुखद रूप से सी # में उपलब्ध नहीं है। जब मैं प्रबंधक वर्ग को सेटिंग पर नियंत्रण की अनुमति देता हूं, तब भी मैं इसे सेट करने वाले बाहरी उपयोगकर्ताओं से स्पेशलडाटा को कैसे सुरक्षित रखूं? मैं इसे आंतरिक खोजशब्द के साथ कर सकता हूं, लेकिन यह अविश्वसनीय रूप से सुरक्षित या साफ नहीं लगता है ...

किसी भी मदद की बहुत सराहना की जाती है।

+2

क्या आप समझा सकते हैं कि आप क्यों मानते हैं कि 'आंतरिक' असुरक्षित या अशुद्ध है? क्या आपका मतलब यह है कि यह सामान्य रूप से सामान्य है, या आप सुझाव दे रहे हैं कि यह आपके विशिष्ट डिजाइन के अनुकूल नहीं है? मैं कहूंगा कि यह एक आदर्श समाधान है, हालांकि सच कहा जाता है कि मुझे यकीन नहीं है कि आप इसे पहले स्थान पर क्यों करना चाहते हैं। – decPL

उत्तर

4

प्रबंधक वर्ग SomeClass रूप में एक ही विधानसभा का हिस्सा है, सदस्य बनाने internal सेटर तक पहुँचने के लिए एक ही विधानसभा में कक्षाओं के लिए यह संभव बनाने चाहते हैं:

public SpecialData data { get; protected internal set; } 

इस में friend का उपयोग कर के समान है सी ++, अपवाद के साथ कि "दोस्ती" एक ही असेंबली के सभी सदस्यों को बढ़ा दी गई है।

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

+0

मैंने आंतरिक कीवर्ड का उल्लेख किया था। मुझे एहसास है कि यह एक विकल्प है, लेकिन क्या यह एक अच्छा है? मैं चिंतित था कि कोई व्यक्ति एक डिजाइन दोष हो सकता है। यदि नहीं, तो यह निश्चित रूप से काम करेगा। यह एक बड़ी परियोजना है, इसलिए इन्हें एक साथ जोड़ना एक बड़ा मुद्दा हो सकता है ... – guitar80

+0

@ user3812869 हां, 'आंतरिक' एक अच्छा विकल्प है। यह इस तरह की स्थितियों के लिए डिज़ाइन किया गया है, जब आप संबंधित वर्गों का एक पैकेज तैयार करते हैं जो आंतरिक प्रतिनिधित्व के ज्ञान को साझा करते हैं। .NET आपके पुस्तकालय के बाहर इस ज्ञान को रिसाव न करने के लिए सावधानी बरतता है। संभवतः, आपके कोड को उन लोगों से सुरक्षित रखने का कोई तरीका नहीं है जो आपकी असेंबली को संशोधित कर सकें। – dasblinkenlight

+0

वैसे इस मामले में मैं कंकों को काम करने की कोशिश करूंगा। डिजाइन सिर्फ मेरे लिए थोड़ा अजीब लगता है। हकीकत में मेरे पास एक स्टेट मैनेजर और स्प्राइट एक गेम ऑब्जेक्ट में निहित है। राज्य प्रबंधक में राज्य शामिल हैं। इन राज्यों को स्प्राइट फ़ील्ड को संपादित करने की आवश्यकता है। – guitar80

1

एक वर्ग है कि SomeClass विरासत है और इस तरह का लग रहा है बनाएँ:

internal class SomeClassDecorator : SomeClass 
{ 
    public void SetSpecialData(SpecialData value) 
    { 
     data = value; 
    } 
} 

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

1

यह वही नहीं हो सकता है जो आप खोज रहे हैं, लेकिन internal वर्णित कीवर्ड here उसी असेंबली के भीतर पहुंच को नियंत्रित कर सकता है; यह C12+ में friend कीवर्ड जैसा ही एक समान उद्देश्य प्रतीत होता है।

1

आप संपत्ति internal बना सकते हैं। इससे संपत्ति एक ही असेंबली के भीतर दिखाई देगी। वैकल्पिक रूप से आप उस संपत्ति तक विशिष्ट असेंबली तक पहुंचने के लिए InternalsVisibleToAttribute का उपयोग कर सकते हैं।

एक और दृष्टिकोण एक interface के उपयोग है कि संपत्ति को छिपाने के लिए है:

public interface ISomeClass 
{ 
    Manager m { get; } 
    SpecialData data { get; set; } 
} 

public class SomeClass : ISomeClass 
{ 
    public Manager m { get; protected set; } 
    SpecialData ISomeClass.data { get; set; } 

    //More methods and member code here... 
} 

इस तरह, data केवल इंटरफ़ेस संदर्भ से दिख रहा है।

तो यह काम नहीं करता है:

SomeClass c = new SomeClass(); 
c.data; 

लेकिन इस करता है:

ISomeClass c = new SomeClass(); 
c.data; 
3

क्या एक RequestChangeSpecialData घटना की तरह कुछ Manager वर्ग पर एक घटना बनाने, के बारे में। Manager ईवेंट को सक्रिय करता है, और SomeClassSpecialData उदाहरण बदल देगा।

public class SomeClass 
{ 
    private Manager _m; 

    public Manager M 
    { 
     get { return _m} 
     set 
     { 
      // register/unregister event on property assignment 
      if(_m != null) 
       _m.RequestChangeSpecialData -= RequestChangeSpecialData; 

      _m = value; 

      if(_m != null) 
       _m.RequestChangeSpecialData += RequestChangeSpecialData; 

     } 
    } 

    public SpecialData Data { get; private set; } 

    private void RequestChangeSpecialData(object sender, ChangeSpecialDataEventArgs e) 
    { 
     // set the new reference 
     Data = e.SpecialData; 
    } 

} 

public class Manager 
{ 
    public void DoSomething() 
    { 
     // the manager class wants to do something, and wants to change the SpecialData instance.., so it fires the event RequestChangeSpecialData 


     SpecialData data = new SpecialData(); 

     // if the event is bound. 
     if(RequestChangeSpecialData != null) 
      RequestChangeSpecialData(this, new ChangeSpecialDataEventArgs(data)); 
    } 

    public event EventHandler<ChangeSpecialDataEventArgs> RequestChangeSpecialData; 
} 

public class ChangeSpecialDataEventArgs : EventArgs 
{ 
    public SpecialData Data {get; private set; } 

    public ChangeSpecialDataEventArgs(SpecialData Data) 
    { 
     Data = data; 
    } 
} 

untested (नोटपैड में लिखा था)

अब ManagerSpecialData संपत्ति को बदलने में सक्षम है। इस तरह प्रबंधक SomeClass/इंटरफ़ेस या असेंबली से निर्भर नहीं है।

+0

इवेंट विकल्प पोस्ट करने वाला था –

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