C# 遍历对象';s自己的弦&;修剪每个
我有多个大对象,每个对象大约有60个字符串。我必须修剪所有这些字符串,我希望这样做而不必执行this.mystring=this.mystring.trim()。相反,我正在寻找一种方法,让每个对象自动发现自己的字符串,然后执行操作 我对反射有点了解,但还不够,但我认为这是可能的 另外,我不确定这是否重要,但有些字符串属性是只读的(只有getter),因此必须跳过这些属性C# 遍历对象';s自己的弦&;修剪每个,c#,.net,reflection,trim,C#,.net,Reflection,Trim,我有多个大对象,每个对象大约有60个字符串。我必须修剪所有这些字符串,我希望这样做而不必执行this.mystring=this.mystring.trim()。相反,我正在寻找一种方法,让每个对象自动发现自己的字符串,然后执行操作 我对反射有点了解,但还不够,但我认为这是可能的 另外,我不确定这是否重要,但有些字符串属性是只读的(只有getter),因此必须跳过这些属性 帮助?很容易获得所有属性,并找出哪些属性是字符串和可写的。LINQ让它变得更容易 var props = instance.
帮助?很容易获得所有属性,并找出哪些属性是字符串和可写的。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);
}
}
您可能只希望在修剪确实产生影响时设置属性,以避免对复杂属性进行冗余计算,或者这可能不是您的问题
如有必要,可通过多种方式提高性能,如:
- 只需缓存每种类型的相关属性
- 使用
为getter和setter生成委托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);
}
}
为了进一步扩展,我有一个包含列表列表的复杂对象,我想遍历它并修剪所有的子字符串对象。我正在发布我在@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));
}
}
}
公共类客户
{
公共字符串名称{get;set;}
公共列表联系人{get;set;}
}
公共类联系人
{
公共字符串名称{get;set;}
公共列表电子邮件地址{get;set;}
}
公共类电子邮件
{
公共字符串电子邮件地址{get;set;}
}
私有空白(对象实例)
{
if(实例!=null)
{
var props=instance.GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
//忽略索引器
.Where(prop=>prop.GetIndexParameters().Length==0)
//必须可读写
.Where(prop=>prop.CanWrite和&prop.CanRead);
foreach(PropertyInfo props in props)
{
if(实例是IEnumerable)
{
foreach(IEnumerable实例中的变量项)
{
删除空白(项目);
}
}
else if(prop.GetValue(实例,null)为字符串)
{
字符串值=(字符串)prop.GetValue(实例,null);
if(值!=null)
{
value=value.Trim();
prop.SetValue(实例,值,null);
}
}
其他的
TrimWhitespace(prop.GetValue(实例,null));
}
}
}
想法?无需在props循环中检查
IEnumerable
,如果实际实例是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));
}
}
}
无参数的
Type.GetProperties()
调用包含静态属性,我怀疑这里不应该包含这些属性。@Jon-说得好,谢谢。我不会提到IsReadable
;p还-您可能需要检查索引器。您能解释一下为什么要检查prop.GetIndexParameters()。长度==0吗?这是做什么的?@Alex:它阻止它拾取索引器。@Alex-索引器类似于公共字符串this[int i]{get{…}set{…}
,它作为一种特殊的属性出现。我想如果不是在调试模式下,属性树会自动缓存吗?我已经读过好几次了。这不是真的吗?在这种情况下,表达式
将是一种痛苦,即使是在4.0中;将多个操作
组合成一个委托会很好,不过。@Alex-lambda表达式在源代码中可以做一些巧妙的事情,使用backing delegate字段。但是,对于手动构建并在运行时编译(Compile
)的树,这是不正确的。您的示例缺少从prop.GetValue到String的转换