user3174976
user3174976

Reputation: 351

Search all the string type member in a class(including searching the property in class type) C#

I tried to find out all the "string" type properties from a class, but wonder how can I do that if there is any class type property in this class.

The following codes show the target class and my solution.

public class Credit_Card
{
    public string brand { get; set; }
    public string billing_phone { get; set; }
    public Expiration expiration { get; set; }
}

public class Expiration
{
    public string month { get; set; }
}


class program
{
    static void Main(string[] args)
    {
        foreach (PropertyInfo prop in typeof(Credit_Card).GetProperties())
        { 
            if(prop.PropertyType == typeof(string))
            {
                Console.WriteLine(prop.Name);              
            }
        }
        Console.ReadLine();
    }
}

My "Main" method can only show "brand" and "billing_phone" properties in Credit_Card type, but missed "month" property in expiration class.

Is there any way that I can do recursive search in Credit_Card class?

Upvotes: 0

Views: 119

Answers (2)

Jon Hanna
Jon Hanna

Reputation: 113272

public static void Main (string[] args)
{
  foreach(PropertyInfo prop in GetStringProperties(typeof(Credit_Card)))
    Console.WriteLine(prop.Name);              
  Console.ReadLine();
}
public static IEnumerable<PropertyInfo> GetStringProperties(Type type)
{
  return GetStringProperties (type, new HashSet<Type> ());
}
public static IEnumerable<PropertyInfo> GetStringProperties(Type type, HashSet<Type> alreadySeen)
{
  foreach(var prop in type.GetProperties())
  {
    var propType = prop.PropertyType;
    if (propType == typeof(string))
      yield return prop;
    else if(alreadySeen.Add(propType))
      foreach(var indirectProp in GetStringProperties(propType, alreadySeen))
        yield return indirectProp;
  }
}

It's important to catch types we've already processed, or you can easily get into an infinite loop with the small mercy that since this takes a recursive approach it crashes with a StackOverflowException rather than just hanging forever like the iterative equivalent would. (Another case of the only thing worse than throwing an exception is no throwing an exception).

Upvotes: 0

StriplingWarrior
StriplingWarrior

Reputation: 156524

You should be able to make a method that will recursively call itself, with the type to search as a parameter:

public void OutputStringProperties(Type type)
{
    foreach (PropertyInfo prop in type.GetProperties())
    { 
        if(prop.PropertyType == typeof(string))
        {
            Console.WriteLine(prop.Name);              
        }
        else
        {
            OutputStringProperties(prop.PropertyType);
        }
    }
}

Then your initial call just invokes this with its starting point:

OutputStringProperties(typeof(Credit_Card));

However, bear in mind that this will cause a stack overflow if you have cyclic dependencies, unless you first modify it to keep track of which types it's already checked.

Upvotes: 1

Related Questions