我有多个大对象,每个对象都有大约 60 个字符串。我必须修剪所有这些字符串,而且我想这样做而不必使用 this.mystring = this.mystring.Trim()。相反,我正在寻找一种方法来自动让每个对象发现自己的字符串,然后执行操作。
我对反射有所了解,但还不够,但我认为这可能吗?
另外,我不确定这是否重要,但某些字符串属性是只读的(只有一个 getter),因此必须跳过这些属性。
帮助?
我有多个大对象,每个对象都有大约 60 个字符串。我必须修剪所有这些字符串,而且我想这样做而不必使用 this.mystring = this.mystring.Trim()。相反,我正在寻找一种方法来自动让每个对象发现自己的字符串,然后执行操作。
我对反射有所了解,但还不够,但我认为这可能吗?
另外,我不确定这是否重要,但某些字符串属性是只读的(只有一个 getter),因此必须跳过这些属性。
帮助?
好吧,很容易获得所有属性,并找出哪些是字符串和可写的。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);
}
}
您可能只想在修剪确实产生影响时才设置属性,以避免对复杂属性进行冗余计算 - 或者这对您来说可能不是问题。
如有必要,有多种方法可以提高性能 - 例如:
Delegate.CreateDelegate
构建委托除非性能实际上是一个问题,否则我不会采取任何这些步骤。
就像是:
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);
}
}
不需要在 props-loop 中进行IEnumerable
检查,如果实际实例是 a IEnumerable
,则忽略 props。修复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));
}
}
}
所以稍微扩展一下,我有一个带有 Lists of Lists 的复杂对象,我想遍历它并修剪所有子字符串对象。我正在发布我在@Jon 在他的回答中所做的事情。我很好奇是否有更好的方法可以做到这一点,或者我是否错过了一些明显的东西。
我拥有的对象比这更复杂,但它应该说明我正在尝试什么。
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));
}
}
}
想法?