2011-10-11 17 views
11

मुझे अपनी ऑब्जेक्ट्स में कुछ स्ट्रिंग गुणों को ट्रिम करने की ज़रूरत है, लेकिन मैं सभी ऑब्जेक्ट्स और प्रॉपर्टीज पर नहीं जाना चाहता हूं और सेट में संपत्तियों में ट्रिम विधि है (बहुत सारी ऑब्जेक्ट्स हैं, 300+ और बहुत सी स्ट्रिंग गुण)।सभी स्ट्रिंग गुणों को ट्रिम करें

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

क्या यह संभव है?

धन्यवाद।

+0

आप किसी दिए गए संपत्ति सेटर में क्रम में ऐसा करना चाहते हैं या आप अपनी फ़ाइलों के सभी स्रोत-कोड बदलना चाहते कर रहे हैं? – Oliver

उत्तर

26
var stringProperties = obj.GetType().GetProperties() 
          .Where(p => p.PropertyType == typeof (string)); 

foreach (var stringProperty in stringProperties) 
{ 
    string currentValue = (string) stringProperty.GetValue(obj, null); 
    stringProperty.SetValue(obj, currentValue.Trim(), null) ; 
} 
+0

आपकी मदद के लिए धन्यवाद, लेकिन मैं सेट संपत्ति को "बदलना" चाहता हूं, इसलिए जब मैं myObject.propertyString = "foo" करता हूं; संपत्ति का मूल्य सिर्फ "foo" होगा। – rpf

+0

@ आरपीएफ आप प्रतिबिंब का उपयोग कर सेटर तर्क बदलने की कोशिश कर रहे हैं? –

+0

हां: $ क्या वह बहुत अजीब है? – rpf

2

आप इस तरह कुछ करने के लिए प्रतिबिंब इस्तेमाल कर सकते हैं:

// o is your instance object 
List<PropertyInfo> fields = o.GetType().GetProperties() 
     .Where(i => i.PropertyType == typeof(string)); 
fields.ForEach(i => i.SetValue(o, ((string)i.GetValue(o, null)).Trim(), new object[]{})); 
4

मैं अपने accessors के व्यवहार को बदलने के बारे यकीन नहीं है। यह बिल्कुल आसान नहीं लगता है। अपनी बेस क्लास में ट्रिमिंग जोड़ने के बारे में कैसे?

class CoreTransaction 
    { 
     public void Trim() 
     { 
      IEnumerable<PropertyInfo> stringProperties = 
       this.GetType().GetProperties() 
       .Where(p => p.PropertyType == typeof(string) && p.CanRead && p.CanWrite); 

      foreach (PropertyInfo property in stringProperties) 
      { 
       string value = (string)property.GetValue(this, null); 
       value = value.Trim(); 
       property.SetValue(this, value, null); 
      } 
     } 
    } 

(इसके अलावा, जांचें कि आपकी क्षेत्रों दोनों पढ़ सकते हैं और करने के लिए लिखा जा सकता है ध्यान दें।)

 

संपादित करें: तब आप अपने आधार वर्ग के लिए कुछ इस तरह जोड़ सकता है, और उन सभी को एक ही बार में ट्रिम करें। WeakReference वर्ग आप आसानी से कचरा कलेक्टर के रास्ते में आ बिना अपने उदाहरणों का ट्रैक रखने के लिए अनुमति देगा:

class CoreTransaction 
{ 
    private static List<WeakReference> allCoreTransactions = new List<WeakReference>(); 

    public CoreTransaction() 
    { 
     allCoreTransactions.Add(new WeakReference(this)); 
    } 

    public static void TrimAll() 
    { 
     foreach (WeakReference reference in allCoreTransactions) 
     { 
      if (reference.IsAlive) 
      { 
       ((CoreTransaction)reference.Target).Trim(); 
      } 
     } 
    } 
} 
11

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

/// <summary>Trim all String properties of the given object</summary> 
    public static TSelf TrimStringProperties<TSelf>(this TSelf input) 
    { 
     var stringProperties = input.GetType().GetProperties() 
      .Where(p => p.PropertyType == typeof(string)); 

     foreach (var stringProperty in stringProperties) 
     { 
      string currentValue = (string)stringProperty.GetValue(input, null); 
      if (currentValue != null) 
       stringProperty.SetValue(input, currentValue.Trim(), null); 
     } 
     return input; 
    } 
+0

धन्यवाद। मैंने उपclasses के लिए एक दूसरा foreach पाश भी जोड़ा और एक विशेषता जिसे आप IgnoreTrim नामक संपत्ति में जोड़ सकते हैं। – Rhyous

0

जो लोग VB.NET का उपयोग के लिए, मैं thrawnis के जवाब बदला जाएगा और शर्त का जोड़ा केवल उन गुणों है कि केवल पठनीय नहीं हैं वापस जाने के लिए। अन्यथा यदि आपकी कक्षा में केवल गुण हैं, तो आप उन गुणों के लिए SetValue को चलाने का प्रयास करते समय रनटाइम त्रुटि प्राप्त करेंगे।

''' <summary> 
''' Trim all NOT ReadOnly String properties of the given object 
''' </summary> 
<Extension()> 
Public Function TrimStringProperties(Of T)(ByVal input As T) As T 
    Dim stringProperties = input.GetType().GetProperties().Where(Function(p) p.PropertyType = GetType(String) AndAlso p.CanWrite) 

    For Each stringProperty In stringProperties 
     Dim currentValue As String = Convert.ToString(stringProperty.GetValue(input, Nothing)) 
     If currentValue IsNot Nothing Then 
      stringProperty.SetValue(input, currentValue.Trim(), Nothing) 
     End If 
    Next 
    Return input 
End Function 
0

आप इसे करने की कोशिश कर सकते हैं:

static public class Trim<T> 
    where T : class 
{ 
    static public readonly Action<T> TrimAllStringFields = Trim<T>.CreateTrimAllStringFields(); 

    static private Action<T> CreatTrimAllStringFields() 
    { 
     var instance = Expression.Parameter(typeof(T)); 
     return Expression.Lambda<Action<T>>(Expression.Block(instance.Type.GetFields(BindingsFlags.Instance| BindingFlags.NonPublic | BindingFlags.Public).Select(field => Expression.Assign(Expression.Field(instance, field)) as Expression), instance).Compile(); 
    } 
} 

इस तरह यह प्रयोग करें:

var myinstance = new MyClass(); 
Trim<MyClass>.TrimAllStringFields(myinstance); 
+0

शायद 'स्थिर' एक्शन में एक टाइपो CreatTrimAllStringFields() '''' पर 'गायब' e'? –

+0

इसके अलावा संशोधक पर ऑर्डर गलत है। यह सार्वजनिक/निजी स्थैतिक है, न कि दूसरी तरफ। – Viezevingertjes

4

मैं एक एक्सटेंशन विधि जो भी संदर्भित वर्गों पर उपवर्गों और तार का ख्याल रखता है लिखा है (जैसे parent.Child.Name)

public static class ExtensionMethods 
{ 
    public static void TrimAllStrings<TSelf>(this TSelf obj) 
    { 
     BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy; 

     foreach (PropertyInfo p in obj.GetType().GetProperties(flags)) 
     { 
      Type currentNodeType = p.PropertyType; 
      if (currentNodeType == typeof (String)) 
      { 
       string currentValue = (string)p.GetValue(obj, null); 
       if (currentValue != null) 
       { 
        p.SetValue(obj, currentValue.Trim(), null); 
       } 
      } 
      // see http://stackoverflow.com/questions/4444908/detecting-native-objects-with-reflection 
      else if (currentNodeType != typeof (object) && Type.GetTypeCode(currentNodeType) == TypeCode.Object) 
      { 
       p.GetValue(obj, null).TrimAllStrings(); 
      } 
     } 
    } 
} 
1

अपने समाधान के लिए लैंडी धन्यवाद। मैंने इंडेक्स पैरामीटर्स के साथ कक्षाओं के लिए समर्थन जोड़ने के लिए अपनी विधि बदल दी और यह भी जांचने के लिए कि ओबीजे जारी रखने से पहले शून्य है या नहीं।

public static void TrimAllStrings<TSelf>(this TSelf obj) 
    { 
     if (obj == null) 
      return; 

     BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy; 

     foreach (PropertyInfo p in obj.GetType().GetProperties(flags)) 
     { 
      Type currentNodeType = p.PropertyType; 
      if (currentNodeType == typeof(String)) 
      { 
       string currentValue = (string)p.GetValue(obj, null); 
       if (currentValue != null) 
       { 
        p.SetValue(obj, currentValue.Trim(), null); 
       } 
      } 
      // see http://stackoverflow.com/questions/4444908/detecting-native-objects-with-reflection 
      else if (currentNodeType != typeof(object) && Type.GetTypeCode(currentNodeType) == TypeCode.Object) 
      { 
       if (p.GetIndexParameters().Length == 0) 
       { 
        p.GetValue(obj, null).TrimAllStrings(); 
       }else 
       { 
        p.GetValue(obj, new Object[] { 0 }).TrimAllStrings(); 
       } 
      } 
     } 
    } 
संबंधित मुद्दे