如何遍历所有字符串属性并使用 System.Reflection 更改它们的值

How to iterate through all string properties and change their values using System.Reflection

我需要遍历一个项目的所有 String 属性,检索它们的值,并操纵这些值——不需要知道项目的名称或 属性 本身。到目前为止,我看到的所有 SetValue 示例都假设您知道 属性 的名称,并使用该名称来引用它。在我的例子中,我没有按名称调用任何东西,而是简单地遍历每个字符串。

public class SpecialClass
{
    public string MyString1 { get; set; }
    public string MyString2 { get; set; }

    public void Sanitize()
    {
        Type CheckItemType = typeof(SpecialClass);
        Type strType = typeof(System.String);
        PropertyInfo[] propInfos = CheckItemType.GetProperties(
          BindingFlags.Public | BindingFlags.Instance);

        foreach (var propInfo in propInfos)
        {
            if (null != propInfo && propInfo.CanWrite)
            {
                if (propInfo.PropertyType == typeof(System.String))
                {
                    // Retrieve the value of the string, manipulate, and then set it

                }
            }
        }
    }
}

在上面的代码中,Sanitize 方法将循环遍历 class 中的字符串,并在满足特定条件时调整它们的值。

虽然我找到了 this post,但它描述的内容似乎要求您知道项目的名称和 属性。就我而言,我也不知道。我有一个方法,其目的是对 String.

类型的所有属性执行操作

我做不到 this 因为我在对象内部工作 - 不是在外部引用它 - 所以我不明白它是如何工作的。

我直觉上觉得这应该是可能的,但我不能完全理解它的语法。

另一种方法是将它创建为一个独立的函数,你 ref 一个对象,它做同样类型的事情,除了在那种情况下对象会有一个名字。

找到 属性 后,您可以写:

string value = (string)propInfo.GetValue(this);
// manipulate
propInfo.SetValue(this, value);

因此方法可以是:

public void Sanitize()
{
  var CheckItemType = typeof(SpecialClass);
  var strType = typeof(string);
  var propInfos = CheckItemType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
  foreach ( var propInfo in propInfos )
    if ( propInfo.PropertyType == strType && propInfo.CanWrite )
    {
      string value = (string)propInfo.GetValue(this);
      // manipulate
      propInfo.SetValue(this, value);
    }
}

您也可以使用 Linq:

public void Sanitize()
{
  var typeString = typeof(string);
  var propertiesInfos = GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)
                                 .Where(p => p.PropertyType == typeString
                                          && p.CanWrite
                                          && p.CanRead);
  foreach ( var propertyInfo in propertiesInfos )
  {
    string value = (string)propertyInfo.GetValue(this);
    // manipulate
    propertyInfo.SetValue(this, value);
  }
}

在这里我们解析实例(this)属性,而不是静态的...所以你可以看到@DmitryBychenko 的回答来考虑它们并通过添加 null 而不是静态成员上的 this BindingFlags.Static 到 select 如果需要的话。

我会做这样的事情。

SpecialClass sc = new SpecialClass()
{
    MyString1 = "abc",
    MyString2 = "xyz"
};

Sanitize(sc);

以及 Sanitize 方法。

public void Sanitize(object obj)
{
    //loop all the propterties
    foreach (PropertyInfo propInfo in obj.GetType().GetProperties())
    {
        //check if the property is a string
        if (propInfo.PropertyType != typeof(System.String))
            continue;

        //get the value
        string value = (string)propInfo.GetValue(obj, null);

        value = value + "_TEST";

        //set the value
        propInfo.SetValue(obj, value);
    }
}

我建议使用 Linq 以便 查询 类型并获得所需的属性:

var properties = GetType()                                    // current type 
  .GetProperties(BindingFlags.Public | BindingFlags.Instance) // public, not static
  .Where(p =>  p.CanRead && p.CanWrite)                       // can read and write
  .Where(p => !p.GetIndexParameters().Any())                  // not indexer 
  .Where(p =>  p.PropertyType == typeof(string));             // of type string

然后在 foreach 循环中分析这些属性及其值,如下所示:

using System.Linq;
using System.Reflection;

... 

public void Sanitize() {
  var properties = GetType()
    .GetProperties(BindingFlags.Public | BindingFlags.Instance)
    .Where(p => p.CanRead && p.CanWrite)
    .Where(p => !p.GetIndexParameters().Any())
    .Where(p => p.PropertyType == typeof(string));

  foreach (PropertyInfo prop in properties) {
    // just for reference: if you want to include static properties
    // you'll have to put null as instance
    object target = prop.GetGetMethod().IsStatic ? null : this;

    // current property value
    string value = prop.GetValue(target) as String;

    //ToDo: Put relevant code here
    string someModifiedValue = value + "_modified";

    // Write, if required
    prop.SetValue(target, someModifiedValue);
  }
}