Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 遍历对象';s自己的弦&;修剪每个_C#_.net_Reflection_Trim - Fatal编程技术网

C# 遍历对象';s自己的弦&;修剪每个

C# 遍历对象';s自己的弦&;修剪每个,c#,.net,reflection,trim,C#,.net,Reflection,Trim,我有多个大对象,每个对象大约有60个字符串。我必须修剪所有这些字符串,我希望这样做而不必执行this.mystring=this.mystring.trim()。相反,我正在寻找一种方法,让每个对象自动发现自己的字符串,然后执行操作 我对反射有点了解,但还不够,但我认为这是可能的 另外,我不确定这是否重要,但有些字符串属性是只读的(只有getter),因此必须跳过这些属性 帮助?很容易获得所有属性,并找出哪些属性是字符串和可写的。LINQ让它变得更容易 var props = instance.

我有多个大对象,每个对象大约有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
    为getter和setter生成委托
  • 可能使用表达式树,尽管我不确定它们是否有帮助
我不会采取任何这些步骤,除非性能确实存在问题。

类似于:

    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的转换