0

I need to loop through all String properties of an item, retrieve their values, and manipulate the values - without needing to know the name of the item or property itself. So far, all the examples of SetValue that I've seen assume that you know the name of the property, and use that name to reference it. In my case, I'm not calling anything by name, but rather simply iterating through every string.

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

                }
            }
        }
    }
}

In the above code, the Sanitize method would loop through the strings in the class and adjust their values if they meet certain conditions.

While I found this post, what it describes seems to require that you know the name of the item and property. In my case, I don't know either. I have a Method whose purpose is to perform manipulation of all properties of type String.

I can't do this because I am working internally inside of the object - not referring to it externally - so I don't see how that could work.

I intuitively feel like this should be possible, but I can't quite put my head around the syntax of it.

An alternative would be to create this as a standalone function to which you ref an object, and it does the same type of thing, except in that scenario the object will have a name.

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
technonaut
  • 484
  • 3
  • 12
  • 1
    _"from inside the object itself without it having any knowledge of its own name"_ -- neither of the answers you claim helped address _"from inside the object itself"_ (which isn't even meaningful), nor are they different in any material way from existing duplicates. If you think those answers addressed your question, then your question is a duplicate. – Peter Duniho Sep 13 '20 at 20:02

3 Answers3

3

I suggest using Linq in order to query type and obtain desirable properties:

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

then analyze these properies and their values within foreach loop, something like this:

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);
  }
}
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
2

Once you have found a property you can write:

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

Hence the method can be:

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

You can also use 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);
  }
}

Here we parse instance (this) properties, not static... so you can see the @DmitryBychenko answer to consider them and use null instead of this on static member by adding BindingFlags.Static to select them if needed.

  • 2
    Your and Dmitry's answers both work perfectly for what I need. You are right in pointing out that `this` was the solution to my problem. That was what I needed to hear and be shown. While Dmitry used it, you took the extra step to call it out so I will mark this as the answer. Thanks a million! – technonaut Sep 13 '20 at 20:38
0

I would do something like this.

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

Sanitize(sc);

And the Sanitize method.

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);
    }
}
VDWWD
  • 35,079
  • 22
  • 62
  • 79
  • Not every property can be written as `propInfo.SetValue(obj, value);`; say, property can well appear to be *readonly*, that's why I'll suggest adding `propertyInfo.CanWrite` check – Dmitry Bychenko Sep 12 '20 at 21:09