2010-07-11 10 views
10

मेरे पास कई बड़ी वस्तुएं हैं जिनमें प्रत्येक के बारे में 60 तार हैं। मुझे उन सभी तारों को ट्रिम करना है, और मैं ऐसा करने के बिना ऐसा करना चाहता हूं। Mystring = this.mystring.Trim()। इसके बजाए, मैं प्रत्येक ऑब्जेक्ट को अपने तारों को स्वचालित रूप से खोजने के लिए एक तरीका ढूंढ रहा हूं और फिर ऑपरेशन निष्पादित करता हूं।ऑब्जेक्ट के अपने स्ट्रिंग्स और ट्रिम के माध्यम से प्रत्येक

मुझे प्रतिबिंब के बारे में कुछ पता है, लेकिन पर्याप्त नहीं है, लेकिन मुझे लगता है कि यह संभव है?

इसके अलावा, मुझे यकीन नहीं है कि यह मायने रखता है, लेकिन कुछ स्ट्रिंग गुण केवल पढ़ने के लिए हैं (केवल एक गेटटर है), इसलिए उन गुणों को छोड़ना होगा।

सहायता?

उत्तर

14

अच्छा, सभी गुणों को प्राप्त करना काफी आसान है, और पता लगाएं कि कौन से तार तार और लिखने योग्य हैं। LINQ इसे और भी आसान बनाता है।

var props = instance.GetType() 
        .GetProperties(BindingFlags.Instance | BindingFlags.Public) 
        // Ignore non-string properties 
        .Where(prop => prop.PropertyType == typeof(string)) 
        // Ignore indexers 
        .Where(prop => prop.GetIndexParameters().Length == 0) 
        // Must be both readable and writable 
        .Where(prop => prop.CanWrite && prop.CanRead); 

foreach (PropertyInfo prop in props) 
{ 
    string value = (string) prop.GetValue(instance, null); 
    if (value != null) 
    { 
     value = value.Trim(); 
     prop.SetValue(instance, value, null); 
    } 
} 

आप केवल गुण सेट करने के लिए करता है, तो वास्तव में काट-छाँट कुछ फ़र्क पड़ता है, जटिल संपत्तियों के लिए अनावश्यक संगणना से बचने के लिए चाहते हो सकता है - या यह आप के लिए एक मुद्दा नहीं हो सकता है।

  • , बस प्रत्येक प्रकार
  • के लिए प्रासंगिक गुण कैशिंग ही टिककर खेल के लिए प्रतिनिधियों और setters के निर्माण के लिए Delegate.CreateDelegate का उपयोग
  • संभवतः का उपयोग कर: - जैसे

    वहाँ प्रदर्शन यदि आवश्यक सुधार लाने के विभिन्न तरीके हैं अभिव्यक्ति पेड़, हालांकि मुझे यकीन नहीं है कि वे यहां मदद करेंगे

मैं निष्पादन तक उन चरणों में से कोई भी नहीं लेगा ई वास्तव में एक समस्या है हालांकि।

+0

मैंने सोचा कि डीबग मोड में नहीं होने पर संपत्ति पेड़ स्वचालित रूप से कैश किए जाते हैं? मैंने कुछ बार पढ़ा है। क्या यह सच नहीं है? – Alex

+1

इस मामले में, 'अभिव्यक्ति' एक दर्द होगा, यहां तक ​​कि 4.0 में भी; एक ही प्रतिनिधि में कई 'एक्शन ' संयोजन को अच्छी तरह से काम करना होगा। –

+0

@Alex - * स्रोत * में लैम्ब्डा अभिव्यक्तियां बैकिंग प्रतिनिधि फ़ील्ड का उपयोग करके कुछ चालाक चीजें कर सकती हैं। हालांकि, AFAIK जो रनटाइम पर मैन्युअल रूप से बनाए गए पेड़ों और संकलित ('कंपाइल') के पेड़ों से सच नहीं है। –

3

कुछ की तरह:

foreach (PropertyInfo prop in obj.GetType().GetProperties(
     BindingFlags.Instance | BindingFlags.Public)) 
    { 
     if (prop.CanRead && prop.CanWrite && prop.PropertyType == typeof(string) 
      && (prop.GetIndexParameters().Length == 0)) // watch for indexers! 
     { 
      var s = (string)prop.GetValue(obj, null); 
      if (!string.IsNullOrEmpty(s)) s = s.Trim(); 
      prop.SetValue(obj, s, null); 
     } 
    } 
+0

पैरामीटर रहित 'टाइप।GetProperties() 'कॉल में स्थिर गुण शामिल हैं, जिन्हें मैं * संदेह * यहां शामिल नहीं किया जाना चाहिए। –

+1

@ जोन - अच्छा बिंदु, धन्यवाद। मैं 'IsReadable' का उल्लेख नहीं करूंगा; पी भी - आप इंडेक्सर्स की जांच करना चाहेंगे। –

+0

@Marc: ठीक हो जाएगा :) –

0

तो यह एक छोटे से पर विस्तार करने के लिए, मैं सूचियाँ की सूची के साथ एक जटिल वस्तु है और मुझे लगता है कि पार और ट्रिम बच्चे स्ट्रिंग के सभी के रूप में अच्छी वस्तुओं करना चाहता था। मैं जो पोस्ट करता हूं उसके अनुसार मैंने जो पोस्ट किया है, उसके बाद मैंने जो जवाब दिया था, वह पोस्ट कर रहा हूं। अगर मैं ऐसा करने का बेहतर तरीका था या अगर मुझे कुछ स्पष्ट याद आया तो मैं उत्सुक हूं।

मेरे पास जो वस्तुएं हैं उससे अधिक जटिल हैं लेकिन यह स्पष्ट करना चाहिए कि मैं क्या कर रहा था।

public class Customer 
{ 
    public string Name { get; set; } 
    public List<Contact> Contacts { get; set; } 
} 

public class Contact 
{ 
    public string Name { get; set; } 
    public List<Email> EmailAddresses {get; set;} 
} 

public class Email 
{ 
    public string EmailAddress {get; set;} 
} 


    private void TrimWhitespace(object instance) 
    { 
     if (instance != null) 
     { 
      var props = instance.GetType() 
        .GetProperties(BindingFlags.Instance | BindingFlags.Public) 
       // Ignore indexers 
        .Where(prop => prop.GetIndexParameters().Length == 0) 
       // Must be both readable and writable 
        .Where(prop => prop.CanWrite && prop.CanRead); 

      foreach (PropertyInfo prop in props) 
      { 
       if (instance is IEnumerable) 
       { 
        foreach (var item in (IEnumerable)instance) 
        { 
         TrimWhitespace(item); 
        } 
       } 
       else if (prop.GetValue(instance, null) is string) 
       { 
        string value = (string)prop.GetValue(instance, null); 
        if (value != null) 
        { 
         value = value.Trim(); 
         prop.SetValue(instance, value, null); 
        } 
       } 
       else 
        TrimWhitespace(prop.GetValue(instance, null)); 
      } 
     } 
    } 

विचार?

1

प्रोप-लूप में IEnumerable चेक करने के लिए आवश्यक नहीं है और यदि वास्तविक उदाहरण IEnumerable है, प्रोप को अनदेखा किया जाता है। IEnumerable भाग के लिए ठीक करें:

private void TrimWhitespace(object instance) 
{ 
    if (instance != null) 
    { 
     if (instance is IEnumerable) 
     { 
      foreach (var item in (IEnumerable)instance) 
      { 
       TrimWhitespace(item); 
      } 
     } 

     var props = instance.GetType() 
       .GetProperties(BindingFlags.Instance | BindingFlags.Public) 
      // Ignore indexers 
       .Where(prop => prop.GetIndexParameters().Length == 0) 
      // Must be both readable and writable 
       .Where(prop => prop.CanWrite && prop.CanRead); 

     foreach (PropertyInfo prop in props) 
     { 
      if (prop.GetValue(instance, null) is string) 
      { 
       string value = (string)prop.GetValue(instance, null); 
       if (value != null) 
       { 
        value = value.Trim(); 
        prop.SetValue(instance, value, null); 
       } 
      } 
      else 
       TrimWhitespace(prop.GetValue(instance, null)); 
     } 
    } 
} 
संबंधित मुद्दे