A: 

BindingFlags.Public | BindingFlags.Instance should do it

GetSetMethod()

bassfriend
+3  A: 

You will find the properties as such with BindingFlags.Public | BindingFlags.Instance. Then you will need to examine each PropertyInfo instance by checking the CanWrite and CanRead properties, in order to find out whether they are are readable and/or writeable.

Update: code example

PropertyInfo[] props = yourClassInstance.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
for (int i = 0; i < props.Length; i++)
{
    if (props[i].PropertyType == typeof(string) && props[i].CanWrite)
    {
        // do your update
    }
}


I looked into it more in detail after your update. If you also examine the MethodInfo objects returned by GetGetMethod and GetSetMethod you will hit the target, I think;

 var properties = typeof(TestSubject).GetProperties(BindingFlags.Instance | BindingFlags.Public)
        .Where(ø => ø.CanRead && ø.CanWrite)
        .Where(ø => ø.PropertyType == typeof(string))
        .Where(ø => ø.GetGetMethod(true).IsPublic)
        .Where(ø => ø.GetSetMethod(true).IsPublic);

By default these two methods return only public getters and setters (risking a NullReferenceException in a case like this), but passing true as above makes them also return private ones. Then you can examine the IsPublic (or IsPrivate) properties.

Fredrik Mörk
This doesn't work. See my example. Even though the get or set is private, it says that it can both read and write, as long as one of them is public.
Svish
A: 

I suggest a different approach: AOP.
You can intercept the setter and set the desired value to a valid one. With PostSharp it's quite easy.

Ron Klein
Huh? How?
Svish
As I was saying, it's a different approach. Instead of changing the value *after* it is set, I suggest to intercept the setter, and change the value if needed. When using PostSharp, you can write attributes and use them with your properties.
Ron Klein
how would you intercept a setter? wouldn't you need to have access to the class or override properties or something then?
Svish
A: 

If you don't specify any binding flags you will get the public, instance properties -- which is what you want. But then you will need to check if the PropertyType on the PropertyInfo object is of type String. Unless you know in advance, you'll also need to check whether the property is readable/writable as @Fredrik indicates.

using System.Linq;

public static void ReplaceEmptyStrings<T>(List<T> list, string replacement)
{
    var properties = typeof(T).GetProperties()
                              .Where( p => p.PropertyType == typeof(string) );
    foreach(var p in properties)
    {
        foreach(var item in list)
        {
            if(string.IsNullOrEmpty((string) p.GetValue(item, null)))
                p.SetValue(item, replacement, null);
        }
    }
}
tvanfosson
+5  A: 

Your code rewritten. Does not use LINQ nor var.

public static void ReplaceEmptyStrings<T>(List<T> list, string replacement)
{
    PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

    foreach (PropertyInfo p in properties)
    {
        // Only work with strings
        if (p.PropertyType != typeof(string)) { continue; }

        // If not writable then cannot null it; if not readable then cannot check it's value
        if (!p.CanWrite || !p.CanRead) { continue; }

        MethodInfo mget = p.GetGetMethod(false);
        MethodInfo mset = p.GetSetMethod(false);

        // Get and set methods have to be public
        if (mget == null) { continue; }
        if (mset == null) { continue; }

        foreach (T item in list)
        {
            if (string.IsNullOrEmpty((string)p.GetValue(item, null)))
            {
                p.SetValue(item, replacement, null);
            }
        }
    }
}
Colin Burnett
Your example will first of all replace *all* values, and second of all, the CanWrite property doesn't seem to work the way we would think it would... =/
Svish
The CanWrite indeed does work the way it should. Can you explain what makes you think to the contrary?
Colin Burnett
As my example shows, a public property that is declared as i.e. public string Something {get; private set;}, will return true for both CanRead and CanWrite, even though I shouldn't be able to write, since the setter is private.
Svish
Ok, I think I know what you mean. The CanWrite and CanRead are just checking if a set and get accessor are assigned to the property. Check the public-ness of the get and set methods to determine if you can call them. I have updated my code.
Colin Burnett
Aaah, there we go! Thank you =)
Svish
A: 

I agree with other answers, but I prefer to refactor the search itself to be easly queried with Linq, so the query could be as follow:

        var asm = Assembly.GetExecutingAssembly();
        var properties = (from prop
                              in asm.GetType()
                                .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                          where 
                            prop.PropertyType == typeof (string) && 
                            prop.CanWrite && 
                            prop.CanRead
                          select prop).ToList();
        properties.ForEach(p => Debug.WriteLine(p.Name));

I took for my example the Assembly type, which hasn't read/write string properties, but if the same code search for just read properties, the result will be:

  • CodeBase
  • EscapedCodeBase
  • FullName
  • Location
  • ImageRuntimeVersion

Which are the string read-only Assembly type properties

Hoghweed
A: 

Hi you can refer to http://jefferytay.wordpress.com/2010/05/03/simple-and-useful-tostring/

for a tostring override method which allows you to get all the properties of the class

jeffery
Interesting. An html table isn't the best format though I would say...
Svish