2010-04-29 37 views
5

इम बाहर का उपयोग कर सामान्य प्रकार पैरामीटर का उपयोग कर एक सार्वभौमिक पार्सर बनाने की कोशिश कर पैरामीटर, लेकिन मैं अवधारणा को समझ नहीं कर सकते 100%जेनेरिक प्रकार

private bool TryParse<T>(XElement element, string attributeName, out T value) where T : struct 
    { 
     if (element.Attribute(attributeName) != null && !string.IsNullOrEmpty(element.Attribute(attributeName).Value)) 
     { 
      string valueString = element.Attribute(attributeName).Value; 
      if (typeof(T) == typeof(int)) 
      { 
       int valueInt; 
       if (int.TryParse(valueString, out valueInt)) 
       { 
        value = valueInt; 
        return true; 
       } 
      } 
      else if (typeof(T) == typeof(bool)) 
      { 
       bool valueBool; 
       if (bool.TryParse(valueString, out valueBool)) 
       { 
        value = valueBool; 
        return true; 
       } 
      } 
      else 
      { 
       value = valueString; 
       return true; 
      } 
     } 

     return false; 
    } 

आप अनुमान लगा सकते हैं, कोड संकलन नहीं करता है, के बाद से मैं int | bool | स्ट्रिंग को टी में परिवर्तित नहीं कर सकता (उदाहरण के लिए। value = valueInt)। फीडबैक के लिए धन्यवाद, शायद यह संभव नहीं है कि मैं इसे कर रहा हूं। एक TypeConverter उपयोग करने से पहले .NET 3.5

+0

वाह, अच्छा सवाल बाहर मदद कर सकता है। आज रात जब मेरे पास वापस आने का समय है, तो मैं हर विश्वसनीय उत्तर को ऊपर उठाने जा रहा हूं। –

उत्तर

2

के रूप में आप केवल एक बहुत बड़ी लिख रहे हैं देखकर यदि/तो कॉम्बो, मुझे लगता है कि आप बस भार के के एक समूह के साथ बेहतर होगा:

public static class Parser 
{ 
    private static string TryParseCommon(XElement element, string attributeName) 
    { 
     if (element.Attribute(attributeName) != null && !string.IsNullOrEmpty(element.Attribute(attributeName).Value)) 
     { 
      return element.Attribute(attributeName).Value; 
     } 

     return null; 
    } 

    public static bool TryParse(XElement element, string attributeName, out string value) 
    { 
     value = TryParseCommon(element, attributeName); 
     return true; 
    } 

    public static bool TryParse(XElement element, string attributeName, out int value) 
    { 
     return int.TryParse(TryParseCommon(element, attributeName), out value); 
    } 

    public static bool TryParse(XElement element, string attributeName, out bool value) 
    { 
     return bool.TryParse(TryParseCommon(element, attributeName), out value); 
    } 
} 
+0

हाँ यह आसान तरीका है ;-) –

1

मेरे द्वारा की गई पार्स तरीकों का उपयोग करना।

TypeConverter converter = TypeDescriptor.GetConverter(typeof(T)); 
try 
{ 
    return (T)converter.ConvertFrom(value); 
} 
+0

ने इसे खींचा! आपका बहुत बहुत धन्यवाद! –

+0

althought ints और bools के साथ नहीं .. –

1

यह आपके लिए काम कर सकता है।

private bool TryParse<T>(XElement element, string attributeName,out T value) 
{ 
    if (element.Attribute(attributeName) != null && !string.IsNullOrEmpty(element.Attribute(attributeName).Value)) 
    { 
     string valueString = element.Attribute(attributeName).Value; 
     TypeConverter converter = TypeDescriptor.GetConverter(typeof(T)); 
     try 
     { 
      value = (T)converter.ConvertFrom(valueString); 
      return true; 
     } 
     catch 
     { 
      value = default(T); 
      return false; 
     } 
    } 
    value = default(T); 
    return false; 
} 
+3

int और bool संरचना प्रकार हैं! – flq

+0

को इसे काम करने के लिए संरचना भाग को हटाना पड़ा (मुझे लगता है कि स्ट्रिंग की वजह से) –

2

नहीं चीजों का सबसे अच्छा है, लेकिन आप कुछ और करने के लिए अपने टी डाल सकता है अगर आप वस्तु पर आते-जाते हैं, यानी प्रथम डाली टी करने के लिए तो आपत्ति उठाने का, या इसके विपरीत। मैं इस बारे में कुछ नहीं कह रहा हूं कि आप मुक्केबाजी/अनबॉक्सिंग सामान में हैं या नहीं, लेकिन संकलक इसे स्वीकार करेगा।

1

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

क्यों आप ऐसा करें नहीं है?

public delegate bool TryParser<T>(string text, out T value); 

फिर अपने विधि पुनर्गठन एक पैरामीटर के रूप में इनमें से एक लेने के लिए:: सबसे पहले एक प्रतिनिधि है कि एक सामान्य TryParse विधि का वर्णन करता है परिभाषित,

// uglified code to fit within horizontal scroll area 
public bool TryParse<T> 
(XElement element, string attributeName, TryParser<T> tryParser, out T value) 
{ 
    value = default(T); 

    if (
     element.Attribute(attributeName) != null && 
     !string.IsNullOrEmpty(element.Attribute(attributeName).Value) 
    ) 
    { 
     string valueString = element.Attribute(attributeName).Value; 
     return tryParser(valueString, out value); 
    } 

    return false; 
} 

अब सभी मानक प्रकार के लिए यह अधिक भार काफी तुच्छ है :

public bool TryParseInt(XElement element, string attributeName, out int value) 
{ 
    return TryParse<int>(element, attributeName, int.TryParse, out value); 
} 

public bool TryParseBool(XElement element, string attributeName, out bool value) 
{ 
    return TryParse<bool>(element, attributeName, bool.TryParse, out value); 
} 

और इसी तरह।

इस दृष्टिकोण के बारे में अच्छा क्या है कि यह आपको where T : struct बाधा, या यहां तक ​​कि अंतर्निहित .NET प्रकारों का उपयोग करने के लिए भी प्रतिबंधित नहीं करता है। इस पार्सर वर्ग का एक उपयोगकर्ता केवल उसकी/उसके कस्टम प्रकार के लिए एक TryParse की तरह विधि को परिभाषित करते हुए एक XML दस्तावेज से उसकी/उसके स्वयं के कस्टम प्रकार पार्स आउट कर सकता है।

4

XElement और XAttribute कक्षाएं दोनों a set of explicit conversion operators (डाले) प्रदान आसानी से आदिम प्रकार नेट के लिए उनकी सामग्री परिवर्तित करने के लिए।

उदाहरण के लिए, आप बस कर सकते हैं:

XElement elem = // ... 

string value1 = (string)elem.Attribute("myString"); 
int value2 = (int)elem.Attribute("myInt"); 
int? value3 = (int?)elem.Attribute("myOptionalInt"); 
bool value4 = (bool)elem.Attribute("myBool"); 
+0

वाह, जानना अच्छा है। –

+0

शानदार पकड़। –

1

इस विधि मैं पहले उपयोग किए गए कुछ भी

public static T ChangeTypeTo<T>(this object value) 
{ 
    if (value == null) 
     return null; 

    Type underlyingType = typeof (T); 
    if (underlyingType == null) 
     throw new ArgumentNullException("value"); 

    if (underlyingType.IsGenericType && underlyingType.GetGenericTypeDefinition() 
              .Equals(typeof (Nullable<>))) 
    { 
     var converter = new NullableConverter(underlyingType); 
     underlyingType = converter.UnderlyingType; 
    } 

    // Guid convert 
    if (underlyingType == typeof (Guid)) 
    { 
     return new Guid(value.ToString()); 
    } 

    // Check for straight conversion or value.ToString conversion 
    var objType = value.GetType(); 

    // If this is false, lets hope value.ToString can convert otherwise exception 
    bool objTypeAssignable2typeT = underlyingType.IsAssignableFrom(objType); 

    // Do conversion 
    return (T) (objTypeAssignable2typeT ? 
       Convert.ChangeType(value, underlyingType) 
      : Convert.ChangeType(value.ToString(), underlyingType)); 
} 
संबंधित मुद्दे