2011-10-26 12 views
5

तो मेरे पास एक कक्षा है जो XML फ़ाइल को पढ़ने और पकड़ने का ख्याल रखती है। अभी इसके बारे में एक सरल संस्करण इस तरह दिखता है:शेक यदि XElement वैश्विक स्तर पर शून्य है

public class EstEIDPersoConfig 
{ 
    public bool LaunchDebugger { get ; set; } 
    public string Password { get; set; } 
    public int Slot { get; set; } 
    public string Reader { get; set; } 
    public string TestInput { get; set; } 
    public bool Logging { get; set; } 

    public EstEIDPersoConfig() 
    { 
     XElement xml = XElement.Load(myxml.xml); 
     XElement Configuration = xml.Element("Configuration"); 

     LaunchDebugger = Convert.ToBoolean(Configuration.Element("LaunchDebugger").Value); 
     Password = Configuration.Element("Password").Value; 
     Slot = Convert.ToInt32(Configuration.Element("Slot").Value); 
     Reader = Configuration.Element("Reader").Value; 
     TestInput = Configuration.Element("TestInput").Value; 
     Logging = Convert.ToBoolean(Configuration.Element("Logging").Value); 
    } 
} 

और यहां कुछ और बाद में किया जाएगा। तो समस्या यह है कि अगर कुछ तत्व xml में मौजूद नहीं है तो मुझे System.NullReferenceException मिलता है। इसलिए मुझे यह जांचने की आवश्यकता है कि तत्व null है या नहीं। ऐसा करने का एक तरीका है:

var value = Configuration.Element("LaunchDebugger").Value; 
if (value != null) 
    LaunchDebugger = Convert.ToBoolean(value); 
else 
    throw new Exception("LaunchDebugger element missing from xml!"); 

लेकिन प्रत्येक तत्व के लिए ऐसा करना बहुत अधिक होगा। तो मुझे इस प्रणाली को सरल बनाने के लिए कुछ अच्छे विचारों की आवश्यकता है ताकि यह कोड की 1000 पंक्तियों में समाप्त न हो।

संपादित करें: पिछले कोड स्निपेट संपादित, विचार एक डिफ़ॉल्ट मान सेट करने के लिए नहीं था, विचार उपयोगकर्ता है कि इस तत्व क्या अशक्त एक्सएमएल से लापता है सूचित करने के लिए किया गया था।

+0

एक्सएमएल का मूल्य शून्य होने पर उचित कन्स्ट्रक्टर को एक्सएमएल के आलसी प्रारंभिक नामक कहा जाता है। – mozillanerd

+1

@ hs2d - मुझे लगता है कि abatishchev का जवाब वह है जिसे आप ढूंढ रहे हैं। – Tim

उत्तर

4

विचार यहाँ सीधे abatischev के जवाब से तो वह श्रेय आता है।

जैसा कि माइक्रोसॉफ्ट here द्वारा निर्धारित किया गया है, आप बस अपनी इच्छानुसार XElement डाल सकते हैं।

LaunchDebugger = (bool?)Configuration.Element("LaunchDebugger"); 

मुझे लगता है कि आप अपने व्यापार के तर्क के आधार पर

LaunchDebugger = (bool)(Configuration.Element("LaunchDebugger") ?? true); 

या शायद

LaunchDebugger = (bool)(Configuration.Element("LaunchDebugger") ?? false); 

कर सकता है आप null मामले को संभालने के लिए चाहते हैं। यदि आप एक विशिष्ट प्रकार के लिए एक ही कोलेसेनिन करते हैं तो यह एक लाइनर को विधि, एक्सटेंशन या अन्यथा लपेटने के लिए उपयुक्त हो सकता है लेकिन मुझे अनिश्चितता है कि इसमें बहुत कुछ शामिल होगा।

+1

लगता है कि आपको 'bool?' – abatishchev

+0

अपडेट करने की आवश्यकता है, यह अन्य प्राइमेटिव के लिए भी सच होगा। – Jodrell

+1

+1 का उपयोग करने के लिए +1 ?? (शून्य coalescing ऑपरेटर, मुझे विश्वास है?) शून्य तत्वों के मामले में एक डिफ़ॉल्ट मूल्य निर्धारित करने के लिए। मैंने आज रात इस धागे से दो उपयोगी चीजें सीखी हैं :) – Tim

2

तर्क को एक विधि में निकालें और Int32, बूलियन और अन्य डेटा प्रकार रूपांतरण के लिए ओवरलोडेड विधियां हैं।

public static void GetElementValue(XElement xElement, string parameter, out bool value) 
    { 
     var stringValue = xElement.Element(parameter).Value; 
     value = false; 
     if (value != null) 
      value = Convert.ToBoolean(stringValue); 
    } 
+0

मैं 'आउट' पैरामीटर का उपयोग नहीं करता, लेकिन वापसी मूल्य। और स्ट्रिंग "लॉन्चडेबगर" एक पैरामीटर था, तो यह और अधिक उपयोगी होगा। –

+0

टाइपो गलती फिक्स्ड। कोड लिखने के लिए आईडीई का उपयोग नहीं कर रहा था। – luqi

+0

लेकिन इस तरह से मुझे अभी भी हर एक्सएमएल तत्व के लिए बाहरी विधि बनाना है? या मैं यहाँ कुछ याद कर रहा हूं .. – hs2d

1

कैसे एक बाहरी विधि के बारे में:

public static class XElementExtensions 
{ 
    public static bool AsBoolean(this XElement self, bool defaultValue) 
    { 
     if (self == null) 
     { 
      return defaultValue; 
     } 
     if (!string.IsNullOrEmpty(self.Value)) 
     {   
      try 
      { 
       return XmlConvert.ToBoolean(self.Value); 
      } 
      catch 
      { 
       return defaultValue; 
      } 
     } 
     return defaultValue; 
    } 
} 

मैं SnippetCompiler के साथ इस परीक्षण किया है:

False 
True 
False 
False 
False 

ऐसे करें:

XElement test = new XElement("test", 
    new XElement("child1"), 
    new XElement("child2", new XText("true")), 
    new XElement("child3", new XText("false")), 
    new XElement("child4", new XText("rubbish"))); 

WL(test.Element("child1").AsBoolean(false)); // note, "child1" has no value (or is `""`) 
WL(test.Element("child2").AsBoolean(false)); 
WL(test.Element("child3").AsBoolean(false)); 
WL(test.Element("child4").AsBoolean(false)); 
WL(test.Element("child5").AsBoolean(false)); // note, "child5" doesn't exist   

इस परिणाम का उत्पादन करने के अन्य प्रकार के तरीकों और 012 भी जोड़ें, जैसा कि आप आसानी से आ सकते हैं, जब आप true पर डिफ़ॉल्ट करना चाहते हैं!

जैसा कि अन्य ने कहा है, आप ऑपरेटर का उपयोग null के लिए मूल्य प्रदान करने के लिए कर सकते हैं। यह घोंसला नहीं है, हालांकि, तो:

LaunchDebugger = XmlConvert.ToBoolean(Configuration.Element("LaunchDebugger").Value) ?? false; 

होगा एक NullReferenceException अगर वहाँ एक्सएमएल फ़ाइल में ऐसी कोई तत्व है के माध्यम से।

+2

'??' कोलेन्सेंस ऑपरेटर के साथ abatischev के उत्तर में माइक्रोसॉफ्ट निर्धारित दृष्टिकोण का उपयोग करना आसान नहीं होगा? – Jodrell

1

आप अपने लिए मूल्य निकालने के लिए एक विधि परिभाषित कर सकते हैं और कुछ शून्य पर जांच कर सकते हैं। तो इसलिए की तरह अपने स्वयं के विधि में मूल्य पुनर्प्राप्ति लपेट:

public string GetXMLValue(XElement config, string elementName){ 
    var element = Configuration.Element(elementName); 

    if(element == null) 
     return String.Empty; 

    return element.Value; 
} 
बेशक

आप इस विस्तार कर सकते हैं आदि बूलियन को

+3

फ्रेमवर्क डेवलपर्स ने इसे क्यों नहीं जोड़ा? उत्तर, क्योंकि इसकी आवश्यकता नहीं है। Abatischev का जवाब देखें। – Jodrell

+1

@ जोडरेल: मैं अब देखता हूं .... मुझे लगता है कि मैंने वास्तव में इस पोस्ट से कुछ सीखा;) धन्यवाद आदमी! –

2

मैं एक विस्तार विधि है कि मैं सिर्फ इस तरह के लिए उपयोग किया है पार्स करने के साथ सही ढंग से काम करने के लिए चीज:

public static T GetValue<T>(
      this XElement @this, 
      XName name, 
      Func<XElement, T> cast, 
      Func<T> @default) 
    { 
     var e = @this.Element(name); 
     return (e != null) ? cast(e) : @default(); 
    } 

यह आपको कास्टिंग आवश्यक और एक डिफ़ॉल्ट मूल्य फैक्ट्री देता है।

यहाँ कैसे आप इसे उपयोग करेंगे:

LaunchDebugger = Configuration.GetValue("LaunchDebugger", 
    x => Convert.ToBoolean(x),() => false); 
Password = Configuration.GetValue("CMKPassword", x => (string)x,() => ""); 
Slot = Configuration.GetValue("CMKSlot", x => (int)x,() => -1); 
Reader = Configuration.GetValue("Reader", x => (string)x,() => ""); 
TestInput = Configuration.GetValue("TestInput", x => (string)x,() => ""); 
Logging = Configuration.GetValue("Logging", 
    x => Convert.ToBoolean(x),() => false); 
+1

मैं नहीं देख सकता कि एक जेनेरिक को दो लैम्ब्स पास करना बेहतर है कि सिर्फ '??' नल कोलेन्सेंस ऑपरेटर कास्टिंग और उपयोग कर रहे हैं – Jodrell

+0

दूसरा "l" टाइप के सादे मूल्य के बजाय दूसरा लैम्ब्डा क्यों? –

+0

@ जोडरेल - 'कास्ट' लैम्ब्डा वास्तव में एक रूपांतरण के रूप में बेहतर विचार है। मैं कोड को सुसंगत बनाने के लिए ऐसा करता हूं। – Enigmativity

4
(bool)Configuration.Element("LaunchDebugger") 

या

(bool?)Configuration.Element("LaunchDebugger") 

अपवाद फेंक नहीं करना चाहिए।

MSDN देखें:

+0

डाउनवोट, मेरे लिए सबसे अच्छा जवाब क्यों दिखता है http://msdn.microsoft.com/en-us/library/bb387049.aspx – Jodrell

+0

@ जोड्रेल: आपको सही लगता है ... मेरा बुरा। हालांकि यह थोड़ा अजीब लग रहा है! –

+0

यह नहीं होना चाहिए '(बूल?) कॉन्फ़िगरेशन। एलिमेंट ("लॉन्चडिबगर") '? यानी, बूल को एक नालीदार प्रकार बनाओ। – Tim