2009-05-14 13 views
12

हमारे पास हमारे डोमेन मॉडल में बहुत से अपरिवर्तनीय मूल्य वस्तुएं हैं, इसका एक उदाहरण एक अक्षांश, रेखांश & ऊंचाई द्वारा परिभाषित एक स्थिति है।कोड को डुप्लिकेट किए बिना मैं WPF में अपरिवर्तनीय ऑब्जेक्ट्स को कैसे संपादित कर सकता हूं?

/// <remarks>When I grow up I want to be an F# record.</remarks> 
public class Position 
{ 
    public double Latitude 
    { 
     get; 
     private set; 
    } 

    // snip 

    public Position(double latitude, double longitude, double height) 
    { 
     Latitude = latitude; 
     // snip 
    } 
} 

की स्थिति का संपादन अनुमति देने के लिए स्पष्ट तरीका एक ViewModel जो टिककर खेल और setters, साथ ही मान्य अपरिवर्तनीय स्थिति उदाहरण को निकालने के लिए एक ToPosition() विधि है निर्माण करना है। हालांकि यह समाधान ठीक रहेगा, इसके परिणामस्वरूप बहुत सारे डुप्लिकेट कोड होंगे, खासकर एक्सएएमएल।

प्रश्न में मूल्य वस्तुएं तीन से पांच गुणों के बीच होती हैं जो आमतौर पर एक्स, वाई, जेड & कुछ सहायक सामान के कुछ प्रकार होते हैं। यह देखते हुए, मैंने विभिन्न संभावनाओं को संभालने के लिए तीन व्यू मॉडेल बनाने पर विचार किया था, जहां प्रत्येक व्यू मॉडेल को प्रत्येक संपत्ति के मूल्य के साथ-साथ प्रत्येक लेबल (उदाहरण के लिए "अक्षांश") के प्रदर्शन के लिए गुणों का खुलासा करने की आवश्यकता होगी।

आगे बढ़ते हुए, ऐसा लगता है कि मैं इसे एक सामान्य व्यू मॉडेल में सरल बना सकता हूं जो एन गुणों से निपट सकता है और प्रतिबिंब का उपयोग करके सब कुछ हुक कर सकता है। संपत्ति ग्रिड की तरह कुछ, लेकिन अपरिवर्तनीय वस्तुओं के लिए। एक संपत्ति ग्रिड के साथ एक मुद्दा है कि मैं स्वरूप बदलने के लिए तो मैं इस तरह के रूप लेबल और बक्सें हो सकता है सक्षम होना चाहते हैं:

Latitude: [  32 ] <- TextBox 
Longitude: [  115 ] 
Height:  [  12 ] 

या जैसे एक डेटा ग्रिड में रख:

Latitude | Longitude | Height 
     32   115   12 

तो मेरा सवाल है:

क्या आप इस समस्या को हल करने के लिए एक शानदार तरीका सोच सकते हैं? क्या कोई पुस्तकालय है जो ऐसा कुछ करता है या कुछ इसी तरह के लेख?

मैं मुख्य रूप से तलाश कर रहा हूँ:

  • कोड दोहराव कम से कम करने
  • आसान नया मान वस्तु प्रकार
  • संभव सत्यापन

उत्तर

2

मुझे इसी स्थिति में मेरे संभावित विकल्पों की खोज करते समय यह पुराना प्रश्न मिला। मैंने सोचा कि अगर किसी और ने इसे ठोकर दिया है तो उसे अपडेट करना चाहिए:

एक और विकल्प (जब पॉल ने अपना समाधान दिया था तब से उपलब्ध नहीं था क्योंकि नेट 4 अभी तक बाहर नहीं था) उसी रणनीति का उपयोग करना है, लेकिन कार्यान्वित करने के बजाय यह कस्टम टाइप टाइपस्क्रिप्टर्स का उपयोग करते हुए, जेनिक्स, गतिशील वस्तुओं और प्रतिबिंब के संयोजन का उपयोग उसी प्रभाव को प्राप्त करने के लिए करते हैं।

इस मामले में, आप एक वर्ग और एक प्रतिनिधि है कि एक शब्दकोश से बाहर का एक नया उदाहरण निर्माण करती है, बस पॉल जवाब में की तरह

class Mutable<ImmutableType> : DynamicObject 
{ 
    //... 
} 

यह निर्माता अपरिवर्तनीय प्रकार का एक उदाहरण लेता है परिभाषित करते हैं। हालांकि, यहां अंतर यह है कि आप TryGetMember और TrySetMember को एक आंतरिक शब्दकोश को पॉप्युलेट करने के लिए ओवरराइड करते हैं जिसे आप अंततः निर्माता-प्रतिनिधि के लिए तर्क के रूप में उपयोग करने जा रहे हैं। आप यह सत्यापित करने के लिए प्रतिबिंब का उपयोग करते हैं कि केवल उन्हीं गुणों को जिन्हें आप स्वीकार कर रहे हैं वे हैं जो वास्तव में ImmutableType में कार्यान्वित किए जाते हैं।

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

https://bitbucket.org/jwrush/mutable-generic-example

+0

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

0
किसी तरह का साथ विस्तार करने के लिए जोड़ने के लिए

क्या आप इस समस्या को हल करने के लिए एक शानदार तरीका सोच सकते हैं?

ईमानदारी से, आप बस समस्या के आसपास नृत्य करते हैं, लेकिन समस्या का उल्लेख न करें;)।

यदि मैं आपकी समस्या का सही अनुमान लगाता हूं, तो मल्टीबाइंडिंग और IMultiValueConverter का संयोजन चाल करना चाहिए।

एचटीएच।

पीएस बीटीडब्लू, आपके पास अपरिवर्तनीय वर्ग के उदाहरण हैं, मूल्य वस्तुएं नहीं। मूल्य वस्तुओं के साथ (जिन्हें struct कीवर्ड द्वारा वर्णित किया गया है) आप सेटर्स थे या नहीं, इससे कोई फर्क नहीं पड़ता :)।

+2

मुझे लगता है कि आप मूल्य की वस्तुओं की एक गलतफहमी है:


यहाँ का अनुरोध सबूत अवधारणा-का-/ उदाहरण दिया गया है। जैसा कि आप कहते हैं वैल्यू प्रकार structs हैं, लेकिन एक मान वस्तु एक ही चीज़ नहीं है। अधिक जानकारी के लिए इस आलेख को देखें: http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/05/20/entities-value-objects-aggregates-and-roots.aspx –

+1

क्या आप शायद विस्तारित कर सकते हैं मैं समस्या को और स्पष्ट कैसे कर सकता हूं? संक्षेप में, मेरे पास एक ऑब्जेक्ट है जो अपरिवर्तनीय है, और मैं आसानी से टेक्स्टबॉक्स को अपनी गुणों में बाध्य करने में सक्षम होना चाहता हूं जैसा कि मैं एक परिवर्तनीय वस्तु के साथ कर सकता हूं। –

+0

मूल्य वस्तुओं के बारे में खेद है - मेरी गलती, पता नहीं था कि एक है। समस्या का विस्तार करने के बारे में - उदाहरण के लिए आप एक स्निप प्रदान कर सकते हैं जिसे आप जेनरेट करना चाहते हैं। शायद, यह भी उपयोगी होगा यदि आप एक्सएएमएल में आदर्श जेनेरिक समाधान के बारे में कुछ मेटा-स्निप प्रदान करते हैं। – archimed7592

5

कस्टम प्रकार वर्णनकर्ताओं का उपयोग इस समस्या को हल करने के लिए किया जा सकता है। किसी स्थिति से जुड़ने से पहले, आपके प्रकार का वर्णनकर्ता लात मार सकता है, और अस्थायी रूप से मूल्यों को बनाने के लिए विधियों को प्राप्त और सेट कर सकता है। जब परिवर्तन किए जाते हैं, तो यह अपरिवर्तनीय वस्तु का निर्माण कर सकता है।

वह कुछ इस तरह दिख सकता है:

DataContext = new Mutable(position, 
    dictionary => new Position(dictionary["lattitude"], ...) 
); 

आपका बाइंडिंग अभी भी इस तरह दिख सकता:

<TextBox Text="{Binding Path=Lattitude}" /> 

परिवर्त्य वस्तु 'नाटक' होगा इसकी TypeDescriptor को Lattitude धन्यवाद की तरह गुण हैं क्योंकि ।

वैकल्पिक रूप से आप अपने बाइंडिंग में एक कनवर्टर का उपयोग कर सकते हैं और किसी तरह के सम्मेलन के साथ आ सकते हैं।

आपकी उत्परिवर्ती कक्षा वर्तमान अपरिवर्तनीय वस्तु, और Func<IDictionary, object> ले जाएगी जो आपको संपादन पूर्ण करने के बाद नई अपरिवर्तनीय वस्तु बनाने की अनुमति देती है। आपकी उत्परिवर्ती वर्ग टाइप डिस्क्रिप्टर का उपयोग करेगी, जो प्रॉपर्टीडिस्क्रिप्टर्स बनाती है जो सेट होने पर नई अपरिवर्तनीय वस्तु बनाती है।

कैसे प्रकार वर्णनकर्ता का उपयोग करने का एक उदाहरण के लिए, यहाँ देखें:

http://www.paulstovell.com/editable-object-adapter

संपादित: यदि आप सीमित करने के लिए कितनी बार अपने अपरिवर्तनीय ऑब्जेक्ट का निर्माण होगा चाहते हैं, तो आप भी BindingGroups पर लग सकता है और IEditableObject, जो आपके उत्परिवर्तनीय भी कार्यान्वित कर सकते हैं।

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

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