修剪所有字符串属性

我需要在我的对象中修剪一些字符串属性,但我不想去所有对象和属性,并且在set属性中做Trim方法(有很多对象,300+和很多字符串属性) 。

一个提示:我的所有对象都有一个名为CoreTransaction的超类,所以我可以使用它(带某种reflection)来更容易地做这件事。

那可能吗?

谢谢。

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) ; } 

感谢Bala R解决OP的问题。 我将您的解决方案转换为扩展方法并修复了空值抛出错误的问题。

  /// Trim all String properties of the given object public static TSelf TrimStringProperties(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; } 

我编写了一个扩展方法,它还处理引用类的子类和字符串(如parent.Child.Name)

 public static class ExtensionMethods { public static void TrimAllStrings(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(); } } } } 

我不确定如何改变访问者的行为。 这听起来并不容易。 如何将修剪添加到基类?

  class CoreTransaction { public void Trim() { IEnumerable 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 allCoreTransactions = new List(); public CoreTransaction() { allCoreTransactions.Add(new WeakReference(this)); } public static void TrimAll() { foreach (WeakReference reference in allCoreTransactions) { if (reference.IsAlive) { ((CoreTransaction)reference.Target).Trim(); } } } } 

您可以使用reflection来执行以下操作:

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

感谢landi的解决方案。 我改变了他的方法来添加对带有索引参数的类的支持,并在继续之前检查obj是否为null。

 public static void TrimAllStrings(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(); } } } } 

我修复了landi的答案以容纳子可空对象并处理IEnumerable集合(循环遍历对象列表和修剪字符串属性)。 我对他的答案进行了编辑,因为没有主题而被拒绝了,但那是一堆垃圾。 希望这有助于某人,因为兰迪的回答并不适用于我所拥有的每种对象类型。 现在确实如此。

 public static class ExtensionMethods { public static void TrimAllStrings(this TSelf obj) { if(obj != null) { if(obj is IEnumerable) { foreach(var listItem in obj as IEnumerable) { listItem.TrimAllStrings(); } } else { 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(); } } } } } } 

对于那些使用VB.NET的人,我转换了thrawnis的答案并添加了一个条件,只返回那些不是ReadOnly的属性。 否则,如果您的类具有只读属性,则在尝试为这些属性设置SetValue时将出现运行时错误。

 '''  ''' Trim all NOT ReadOnly String properties of the given object '''   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 

你可以尝试一下:

 static public class Trim where T : class { static public readonly Action TrimAllStringFields = Trim.CreateTrimAllStringFields(); static private Action CreatTrimAllStringFields() { var instance = Expression.Parameter(typeof(T)); return Expression.Lambda>(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.TrimAllStringFields(myinstance);