.net - डब्ल्यूसीएफ: बिना सेट किए रीडोनली डेटामेम्बर गुणों का खुलासा?




wcf readonly (4)

इसे हासिल करने का एक तरीका है। लेकिन चेतावनी दीजिये कि यह सीधे इस उत्तर में उद्धृत निम्नलिखित सिद्धांतों का उल्लंघन करता है:

"3. सेवाएं शेयर स्कीमा और अनुबंध, वर्ग नहीं।"

यदि यह उल्लंघन आपको चिंता नहीं करता है, तो यह वही है जो आप करते हैं:

  1. सेवा और डेटा अनुबंधों को एक अलग (पोर्टेबल) कक्षा पुस्तकालय में ले जाएं। (आइए इस असेंबली को कुछ सेवा SomeService.ContractsSomeService.Contracts ।) इस प्रकार आप एक अपरिवर्तनीय [DataContract] कक्षा को परिभाषित करेंगे:

    namespace SomeService.Contracts
    {
        [DataContract]
        public sealed class Foo
        {
            public Foo(int x)
            {
                this.x = x;
            }
    
            public int X
            {
                get
                {
                    return x;
                }
            }
    
            [DataMember]  // NB: applied to the backing field, not to the property!
            private readonly int x;
        }
    }
    

    ध्यान दें कि [DataMember] बैकिंग फ़ील्ड पर लागू होता है, कि संबंधित पढ़ने-योग्य संपत्ति के लिए।

  2. अपनी सेवा आवेदन प्रोजेक्ट (मैं अपनी कुछ SomeService.Web कॉल SomeService.Web ) और आपके क्लाइंट प्रोजेक्ट्स से अनुबंध अनुबंध असेंबली का संदर्भ देता हूं (मेरा कुछ सेवा है। SomeService.Client )। इसके परिणामस्वरूप आपके समाधान के अंदर निम्नलिखित परियोजना निर्भरताएं हो सकती हैं:

  3. इसके बाद, जब आप अपने क्लाइंट प्रोजेक्ट में सेवा संदर्भ जोड़ते हैं, तो सुनिश्चित करें कि "पुन: उपयोग प्रकार" विकल्प सक्षम है, और सुनिश्चित करें कि आपकी अनुबंध असेंबली ( SomeService.Contracts ) इसमें शामिल की जाएगी:

देखा! सेवा स्टूडियो, सेवा के डब्लूएसडीएल स्कीमा से एक नया Foo प्रकार उत्पन्न करने के बजाय, आपके अनुबंध असेंबली से अपरिवर्तनीय Foo प्रकार का पुन: उपयोग करेगा।

एक आखिरी चेतावनी: आप पहले से ही उस अन्य उत्तर में उद्धृत सेवा सिद्धांतों से भटक गए हैं। लेकिन आगे किसी भी भटकने की कोशिश मत करो। आप अपने डेटा अनुबंध कक्षाओं में जोड़ने (व्यवसाय) तर्क शुरू करने के लिए प्रेरित हो सकते हैं; नहीं है। जब आप प्रबंधन कर सकते हैं तो उन्हें गूंगा डेटा ट्रांसफर ऑब्जेक्ट्स (डीटीओ) के करीब रहना चाहिए।

मेरे पास एक सर्वर साइड क्लास है जिसे मैं क्लाइंट साइड पर [DataContract] के माध्यम से उपलब्ध कराता हूं। इस वर्ग में एक पठनीय क्षेत्र है जिसे मैं एक संपत्ति के माध्यम से उपलब्ध करना चाहता हूं। हालांकि, मैं ऐसा करने में असमर्थ हूं क्योंकि ऐसा प्रतीत नहीं होता है कि मुझे प्राप्त करने और सेट किए बिना [डेटामेम्बर] संपत्ति जोड़ने की अनुमति है।

तो - क्या सेटर के बिना [डेटामेम्बर] संपत्ति रखने का कोई तरीका है?

[DataContract]
class SomeClass
{
    private readonly int _id; 

    public SomeClass() { .. }

    [DataMember]
    public int Id { get { return _id; } }        

    [DataMember]
    public string SomeString { get; set; }
}

या समाधान [डेटामेम्बर] को फ़ील्ड के रूप में उपयोग करेगा - (जैसे कि here दिखाया गया here )? ऐसा करने का भी प्रयास किया, लेकिन ऐसा लगता है कि क्षेत्र केवल पढ़ने के लिए नहीं है ..?

संपादित करें : क्या इस तरह हैकिंग करके एक पठनीय संपत्ति बनाने का एकमात्र तरीका है? (नहीं - मैं यह नहीं करना चाहता ...)

[DataMember]
public int Id
{
    get { return _id; }
    private set { /* NOOP */ }
}

उस क्षेत्र पर डेटामेम्बर विशेषता डालें जो संपत्ति नहीं है।

सोचा याद रखें, डब्ल्यूसीएफ को encapsulation नहीं पता है। Encapsulation एक ओओपी शब्द है, एसओए शब्द नहीं।

उस ने कहा, याद रखें कि क्षेत्र आपकी कक्षा का उपयोग करने वाले लोगों के लिए पढ़ा जाएगा - सेवा का उपयोग करने वाले किसी भी व्यक्ति के पास उनके पक्ष में क्षेत्र तक पूर्ण पहुंच होगी।


मेरी सेवा परत में कक्षा में कुछ गुण थे, मैं सिल्वरलाइट को पास करना चाहता था। मैं एक पूरी नई कक्षा नहीं बनाना चाहता था।

वास्तव में 'अनुशंसित' नहीं है, लेकिन यह Total संपत्ति को चांदी की रोशनी में पार करने के लिए दो बुराइयों में से कम लग रहा था (पूरी तरह से दृश्य डेटाबेस के लिए)।

public class PricingSummary
{
    public int TotalItemCount { get; set; } // doesnt ideally belong here but used by top bar when out of store area

    public decimal SubTotal { get; set; }
    public decimal? Taxes { get; set; }
    public decimal Discount { get; set; }
    public decimal? ShippingTotal { get; set; }
    public decimal Total
    {
        get
        {
            return + SubTotal
                   + (ShippingTotal ?? 0)
                   + (Taxes ?? 0)
                   - Discount;
        }
        set
        {
            throw new ApplicationException("Cannot be set");
        }
    }
}

वास्तव में, आपके "सर्वर-साइड" वर्ग को क्लाइंट को "उपलब्ध कराया नहीं जाएगा"।

यह क्या होता है: डेटा अनुबंध के आधार पर, ग्राहक सेवा के एक्सएमएल स्कीमा से एक नई अलग कक्षा बनाएगा। यह सर्वर-साइड क्लास प्रति से उपयोग नहीं कर सकता !

यह एक्सएमएल स्कीमा परिभाषा से एक नई कक्षा को फिर से बनाएगा, लेकिन उस स्कीमा में .NET विशिष्ट चीजों में से कोई भी दृश्यता या एक्सेस संशोधक नहीं है - यह केवल एक एक्सएमएल स्कीमा है, आखिरकार। क्लाइंट-साइड क्लास इस तरह से बनाई जाएगी कि तार पर एक ही "पदचिह्न" है - उदाहरण के लिए यह मूल रूप से उसी एक्सएमएल प्रारूप में क्रमबद्ध होता है।

आप मानक एसओएपी-आधारित सेवा के माध्यम से कक्षा के बारे में .NET विशिष्ट जानकारियों को "परिवहन" नहीं कर सकते हैं - आखिरकार, आप जो कुछ भी पारित कर रहे हैं वे क्रमबद्ध संदेश हैं - कोई कक्षा नहीं!

"एसओए के चार सिद्धांत" की जांच करें (माइक्रोसॉफ्ट के डॉन बॉक्स द्वारा परिभाषित):

  1. सीमाएं स्पष्ट हैं
  2. सेवाएं स्वायत्त हैं
  3. सेवा स्कीमा और अनुबंध साझा करें, वर्ग नहीं
  4. स्थिरता नीति पर आधारित है

बिंदु # 3 देखें - सेवाएं स्कीमा और अनुबंध साझा करें, कक्षा नहीं - आप डेटा अनुबंध के लिए केवल इंटरफ़ेस और एक्सएमएल स्कीमा साझा करते हैं - यह सब - कोई .NET कक्षा नहीं है।







datamember